xref: /optee_os/ta/pkcs11/src/processing.c (revision eb6141b6e9d643b3a2cd1a40de52f1d9a80fcb30)
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 
30*eb6141b6SVesa Jääskeläinen static enum processing_func func_for_cmd(enum pkcs11_ta_cmd cmd)
31*eb6141b6SVesa Jääskeläinen {
32*eb6141b6SVesa Jääskeläinen 	switch (cmd) {
33*eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_ENCRYPT_UPDATE:
34*eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_ENCRYPT_ONESHOT:
35*eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_ENCRYPT_FINAL:
36*eb6141b6SVesa Jääskeläinen 		return PKCS11_FUNCTION_ENCRYPT;
37*eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_DECRYPT_UPDATE:
38*eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_DECRYPT_ONESHOT:
39*eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_DECRYPT_FINAL:
40*eb6141b6SVesa Jääskeläinen 		return PKCS11_FUNCTION_DECRYPT;
41*eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_SIGN_ONESHOT:
42*eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_SIGN_UPDATE:
43*eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_SIGN_FINAL:
44*eb6141b6SVesa Jääskeläinen 		return PKCS11_FUNCTION_SIGN;
45*eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_VERIFY_ONESHOT:
46*eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_VERIFY_UPDATE:
47*eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_VERIFY_FINAL:
48*eb6141b6SVesa Jääskeläinen 		return PKCS11_FUNCTION_VERIFY;
49*eb6141b6SVesa Jääskeläinen 	default:
50*eb6141b6SVesa Jääskeläinen 		return PKCS11_FUNCTION_UNKNOWN;
51*eb6141b6SVesa Jääskeläinen 	}
52*eb6141b6SVesa Jääskeläinen }
53*eb6141b6SVesa Jääskeläinen 
54512cbf1dSJens Wiklander static bool func_matches_state(enum processing_func function,
55512cbf1dSJens Wiklander 			       enum pkcs11_proc_state state)
56512cbf1dSJens Wiklander {
57512cbf1dSJens Wiklander 	switch (function) {
58512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
59512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_ENCRYPTING ||
60512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING ||
61512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
62512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
63512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_DECRYPTING ||
64512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_DIGESTING ||
65512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
66512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DIGEST:
67512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_DIGESTING ||
68512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING;
69512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
70512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING ||
71512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
72512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
73512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_VERIFYING ||
74512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
75512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN_RECOVER:
76512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING_RECOVER;
77512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY_RECOVER:
78512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING_RECOVER;
79512cbf1dSJens Wiklander 	default:
80512cbf1dSJens Wiklander 		TEE_Panic(function);
81512cbf1dSJens Wiklander 		return false;
82512cbf1dSJens Wiklander 	}
83512cbf1dSJens Wiklander }
84512cbf1dSJens Wiklander 
85512cbf1dSJens Wiklander static enum pkcs11_rc get_active_session(struct pkcs11_session *session,
86512cbf1dSJens Wiklander 					 enum processing_func function)
87512cbf1dSJens Wiklander {
88512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED;
89512cbf1dSJens Wiklander 
90512cbf1dSJens Wiklander 	if (session->processing &&
91512cbf1dSJens Wiklander 	    func_matches_state(function, session->processing->state))
92512cbf1dSJens Wiklander 		rc = PKCS11_CKR_OK;
93512cbf1dSJens Wiklander 
94512cbf1dSJens Wiklander 	return rc;
95512cbf1dSJens Wiklander }
96512cbf1dSJens Wiklander 
97512cbf1dSJens Wiklander void release_active_processing(struct pkcs11_session *session)
98512cbf1dSJens Wiklander {
99512cbf1dSJens Wiklander 	if (!session->processing)
100512cbf1dSJens Wiklander 		return;
101512cbf1dSJens Wiklander 
102512cbf1dSJens Wiklander 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
103512cbf1dSJens Wiklander 		TEE_FreeOperation(session->processing->tee_op_handle);
104512cbf1dSJens Wiklander 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
105512cbf1dSJens Wiklander 	}
106512cbf1dSJens Wiklander 
1072158ea6cSRuchika Gupta 	TEE_Free(session->processing->extra_ctx);
1082158ea6cSRuchika Gupta 
109512cbf1dSJens Wiklander 	TEE_Free(session->processing);
110512cbf1dSJens Wiklander 	session->processing = NULL;
111512cbf1dSJens Wiklander }
112512cbf1dSJens Wiklander 
113512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj)
114512cbf1dSJens Wiklander {
115512cbf1dSJens Wiklander 	uint32_t a_size = 0;
116512cbf1dSJens Wiklander 	struct obj_attrs *attrs = obj->attributes;
117512cbf1dSJens Wiklander 
118512cbf1dSJens Wiklander 	switch (get_key_type(attrs)) {
119512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
120689f4e5bSRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
121689f4e5bSRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
122689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
123689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
124689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA256_HMAC:
125689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
126689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
127512cbf1dSJens Wiklander 		if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
128512cbf1dSJens Wiklander 			return 0;
129512cbf1dSJens Wiklander 
130512cbf1dSJens Wiklander 		return a_size * 8;
131512cbf1dSJens Wiklander 	default:
132512cbf1dSJens Wiklander 		TEE_Panic(0);
133512cbf1dSJens Wiklander 		return 0;
134512cbf1dSJens Wiklander 	}
135512cbf1dSJens Wiklander }
136512cbf1dSJens Wiklander 
137fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
138fa247a2aSRuchika Gupta {
139fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
140fa247a2aSRuchika Gupta 	void *data = NULL;
141fa247a2aSRuchika Gupta 	uint32_t data_size = 0;
142fa247a2aSRuchika Gupta 	uint32_t value_len = 0;
143fa247a2aSRuchika Gupta 	void *value = NULL;
144fa247a2aSRuchika Gupta 
145fa247a2aSRuchika Gupta 	if (!*head)
146fa247a2aSRuchika Gupta 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
147fa247a2aSRuchika Gupta 
148fa247a2aSRuchika Gupta 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
149fa247a2aSRuchika Gupta 	if (rc || data_size != sizeof(uint32_t)) {
150fa247a2aSRuchika Gupta 		DMSG("%s", rc ? "No attribute value_len found" :
151fa247a2aSRuchika Gupta 		     "Invalid size for attribute VALUE_LEN");
152fa247a2aSRuchika Gupta 
153fa247a2aSRuchika Gupta 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
154fa247a2aSRuchika Gupta 	}
155fa247a2aSRuchika Gupta 	TEE_MemMove(&value_len, data, data_size);
156fa247a2aSRuchika Gupta 
157fa247a2aSRuchika Gupta 	/* Remove the default empty value attribute if found */
158fa247a2aSRuchika Gupta 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
159fa247a2aSRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
160fa247a2aSRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
161fa247a2aSRuchika Gupta 
162fa247a2aSRuchika Gupta 	value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
163fa247a2aSRuchika Gupta 	if (!value)
164fa247a2aSRuchika Gupta 		return PKCS11_CKR_DEVICE_MEMORY;
165fa247a2aSRuchika Gupta 
166fa247a2aSRuchika Gupta 	TEE_GenerateRandom(value, value_len);
167fa247a2aSRuchika Gupta 
168fa247a2aSRuchika Gupta 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
169fa247a2aSRuchika Gupta 
170fa247a2aSRuchika Gupta 	TEE_Free(value);
171fa247a2aSRuchika Gupta 
172fa247a2aSRuchika Gupta 	return rc;
173fa247a2aSRuchika Gupta }
174fa247a2aSRuchika Gupta 
175fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
176fa247a2aSRuchika Gupta 				     uint32_t ptypes, TEE_Param *params)
177fa247a2aSRuchika Gupta {
178fa247a2aSRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
179fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE,
180fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
181fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE);
182fa247a2aSRuchika Gupta 	TEE_Param *ctrl = params;
183fa247a2aSRuchika Gupta 	TEE_Param *out = params + 2;
184fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
185fa247a2aSRuchika Gupta 	struct serialargs ctrlargs = { };
186fa247a2aSRuchika Gupta 	struct pkcs11_session *session = NULL;
187fa247a2aSRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
188fa247a2aSRuchika Gupta 	struct obj_attrs *head = NULL;
189fa247a2aSRuchika Gupta 	struct pkcs11_object_head *template = NULL;
190fa247a2aSRuchika Gupta 	size_t template_size = 0;
191fa247a2aSRuchika Gupta 	uint32_t obj_handle = 0;
192fa247a2aSRuchika Gupta 
193fa247a2aSRuchika Gupta 	if (!client || ptypes != exp_pt ||
194fa247a2aSRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
195fa247a2aSRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
196fa247a2aSRuchika Gupta 
197fa247a2aSRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
198fa247a2aSRuchika Gupta 
199fa247a2aSRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
200fa247a2aSRuchika Gupta 	if (rc)
201fa247a2aSRuchika Gupta 		return rc;
202fa247a2aSRuchika Gupta 
203fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
204fa247a2aSRuchika Gupta 	if (rc)
205fa247a2aSRuchika Gupta 		goto out;
206fa247a2aSRuchika Gupta 
207fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
208fa247a2aSRuchika Gupta 	if (rc)
209fa247a2aSRuchika Gupta 		goto out;
210fa247a2aSRuchika Gupta 
211fa247a2aSRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
212fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
213fa247a2aSRuchika Gupta 		goto out;
214fa247a2aSRuchika Gupta 	}
215fa247a2aSRuchika Gupta 
216fa247a2aSRuchika Gupta 	rc = get_ready_session(session);
217fa247a2aSRuchika Gupta 	if (rc)
218fa247a2aSRuchika Gupta 		goto out;
219fa247a2aSRuchika Gupta 
220fa247a2aSRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
221fa247a2aSRuchika Gupta 
222fa247a2aSRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
223fa247a2aSRuchika Gupta 						PKCS11_FUNCTION_GENERATE,
224fa247a2aSRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
225fa247a2aSRuchika Gupta 	if (rc) {
226fa247a2aSRuchika Gupta 		DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
227fa247a2aSRuchika Gupta 		goto out;
228fa247a2aSRuchika Gupta 	}
229fa247a2aSRuchika Gupta 
230fa247a2aSRuchika Gupta 	/*
231fa247a2aSRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes.
232fa247a2aSRuchika Gupta 	 * Free temporary template once done.
233fa247a2aSRuchika Gupta 	 */
234fa247a2aSRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
235fa247a2aSRuchika Gupta 					     NULL, PKCS11_FUNCTION_GENERATE,
2364cfce748SRuchika Gupta 					     proc_params->id,
2374cfce748SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
238fa247a2aSRuchika Gupta 	if (rc)
239fa247a2aSRuchika Gupta 		goto out;
240fa247a2aSRuchika Gupta 
241fa247a2aSRuchika Gupta 	TEE_Free(template);
242fa247a2aSRuchika Gupta 	template = NULL;
243fa247a2aSRuchika Gupta 
244fa247a2aSRuchika Gupta 	rc = check_created_attrs(head, NULL);
245fa247a2aSRuchika Gupta 	if (rc)
246fa247a2aSRuchika Gupta 		goto out;
247fa247a2aSRuchika Gupta 
248fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
249fa247a2aSRuchika Gupta 	if (rc)
250fa247a2aSRuchika Gupta 		goto out;
251fa247a2aSRuchika Gupta 
252fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
253fa247a2aSRuchika Gupta 	if (rc)
254fa247a2aSRuchika Gupta 		goto out;
255fa247a2aSRuchika Gupta 
256fa247a2aSRuchika Gupta 	/*
257fa247a2aSRuchika Gupta 	 * Execute target processing and add value as attribute
258fa247a2aSRuchika Gupta 	 * PKCS11_CKA_VALUE. Symm key generation: depends on target
259fa247a2aSRuchika Gupta 	 * processing to be used.
260fa247a2aSRuchika Gupta 	 */
261fa247a2aSRuchika Gupta 	switch (proc_params->id) {
262fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
263fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
264fa247a2aSRuchika Gupta 		/* Generate random of size specified by attribute VALUE_LEN */
265fa247a2aSRuchika Gupta 		rc = generate_random_key_value(&head);
266fa247a2aSRuchika Gupta 		if (rc)
267fa247a2aSRuchika Gupta 			goto out;
268fa247a2aSRuchika Gupta 		break;
269fa247a2aSRuchika Gupta 
270fa247a2aSRuchika Gupta 	default:
271fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
272fa247a2aSRuchika Gupta 		goto out;
273fa247a2aSRuchika Gupta 	}
274fa247a2aSRuchika Gupta 
275fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
276fa247a2aSRuchika Gupta 	proc_params = NULL;
277fa247a2aSRuchika Gupta 
278fa247a2aSRuchika Gupta 	/*
279fa247a2aSRuchika Gupta 	 * Object is ready, register it and return a handle.
280fa247a2aSRuchika Gupta 	 */
281fa247a2aSRuchika Gupta 	rc = create_object(session, head, &obj_handle);
282fa247a2aSRuchika Gupta 	if (rc)
283fa247a2aSRuchika Gupta 		goto out;
284fa247a2aSRuchika Gupta 
285fa247a2aSRuchika Gupta 	/*
286fa247a2aSRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
287fa247a2aSRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
288fa247a2aSRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
289fa247a2aSRuchika Gupta 	 * be freed at function out.
290fa247a2aSRuchika Gupta 	 */
291fa247a2aSRuchika Gupta 	head = NULL;
292fa247a2aSRuchika Gupta 
293fa247a2aSRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
294fa247a2aSRuchika Gupta 	out->memref.size = sizeof(obj_handle);
295fa247a2aSRuchika Gupta 
296fa247a2aSRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
297fa247a2aSRuchika Gupta 	     session->handle, obj_handle);
298fa247a2aSRuchika Gupta 
299fa247a2aSRuchika Gupta out:
300fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
301fa247a2aSRuchika Gupta 	TEE_Free(template);
302fa247a2aSRuchika Gupta 	TEE_Free(head);
303fa247a2aSRuchika Gupta 
304fa247a2aSRuchika Gupta 	return rc;
305fa247a2aSRuchika Gupta }
306fa247a2aSRuchika Gupta 
307512cbf1dSJens Wiklander /*
308512cbf1dSJens Wiklander  * entry_processing_init - Generic entry for initializing a processing
309512cbf1dSJens Wiklander  *
310512cbf1dSJens Wiklander  * @client = client reference
311512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
312512cbf1dSJens Wiklander  * @params = Invocation parameters reference
313512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
314512cbf1dSJens Wiklander  */
315512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
316512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
317512cbf1dSJens Wiklander 				     enum processing_func function)
318512cbf1dSJens Wiklander {
319512cbf1dSJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
320512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
321512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
322512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE);
323512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
324512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
325512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
326512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
327512cbf1dSJens Wiklander 	struct pkcs11_attribute_head *proc_params = NULL;
328512cbf1dSJens Wiklander 	uint32_t key_handle = 0;
329512cbf1dSJens Wiklander 	struct pkcs11_object *obj = NULL;
330512cbf1dSJens Wiklander 
331512cbf1dSJens Wiklander 	if (!client || ptypes != exp_pt)
332512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
333512cbf1dSJens Wiklander 
334512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
335512cbf1dSJens Wiklander 
336512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
337512cbf1dSJens Wiklander 	if (rc)
338512cbf1dSJens Wiklander 		return rc;
339512cbf1dSJens Wiklander 
340512cbf1dSJens Wiklander 	rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
341512cbf1dSJens Wiklander 	if (rc)
342512cbf1dSJens Wiklander 		return rc;
343512cbf1dSJens Wiklander 
344512cbf1dSJens Wiklander 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
345512cbf1dSJens Wiklander 	if (rc)
346512cbf1dSJens Wiklander 		return rc;
347512cbf1dSJens Wiklander 
348512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs)) {
349512cbf1dSJens Wiklander 		rc = PKCS11_CKR_ARGUMENTS_BAD;
350512cbf1dSJens Wiklander 		goto out;
351512cbf1dSJens Wiklander 	}
352512cbf1dSJens Wiklander 
353512cbf1dSJens Wiklander 	rc = get_ready_session(session);
354512cbf1dSJens Wiklander 	if (rc)
355512cbf1dSJens Wiklander 		goto out;
356512cbf1dSJens Wiklander 
357512cbf1dSJens Wiklander 	obj = pkcs11_handle2object(key_handle, session);
358512cbf1dSJens Wiklander 	if (!obj) {
359512cbf1dSJens Wiklander 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
360512cbf1dSJens Wiklander 		goto out;
361512cbf1dSJens Wiklander 	}
362512cbf1dSJens Wiklander 
363512cbf1dSJens Wiklander 	rc = set_processing_state(session, function, obj, NULL);
364512cbf1dSJens Wiklander 	if (rc)
365512cbf1dSJens Wiklander 		goto out;
366512cbf1dSJens Wiklander 
367512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, proc_params->id,
368512cbf1dSJens Wiklander 						function,
369512cbf1dSJens Wiklander 						PKCS11_FUNC_STEP_INIT);
370512cbf1dSJens Wiklander 	if (rc)
371512cbf1dSJens Wiklander 		goto out;
372512cbf1dSJens Wiklander 
373512cbf1dSJens Wiklander 	rc = check_parent_attrs_against_processing(proc_params->id, function,
374512cbf1dSJens Wiklander 						   obj->attributes);
375512cbf1dSJens Wiklander 	if (rc)
376512cbf1dSJens Wiklander 		goto out;
377512cbf1dSJens Wiklander 
378512cbf1dSJens Wiklander 	rc = check_access_attrs_against_token(session, obj->attributes);
379512cbf1dSJens Wiklander 	if (rc)
380512cbf1dSJens Wiklander 		goto out;
381512cbf1dSJens Wiklander 
382512cbf1dSJens Wiklander 	if (processing_is_tee_symm(proc_params->id))
383512cbf1dSJens Wiklander 		rc = init_symm_operation(session, function, proc_params, obj);
384512cbf1dSJens Wiklander 	else
385512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
386512cbf1dSJens Wiklander 
387512cbf1dSJens Wiklander 	if (rc == PKCS11_CKR_OK) {
388512cbf1dSJens Wiklander 		session->processing->mecha_type = proc_params->id;
389512cbf1dSJens Wiklander 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
390512cbf1dSJens Wiklander 		     session->handle, id2str_proc(proc_params->id),
391512cbf1dSJens Wiklander 		     id2str_function(function));
392512cbf1dSJens Wiklander 	}
393512cbf1dSJens Wiklander 
394512cbf1dSJens Wiklander out:
395512cbf1dSJens Wiklander 	if (rc && session)
396512cbf1dSJens Wiklander 		release_active_processing(session);
397512cbf1dSJens Wiklander 
398512cbf1dSJens Wiklander 	TEE_Free(proc_params);
399512cbf1dSJens Wiklander 
400512cbf1dSJens Wiklander 	return rc;
401512cbf1dSJens Wiklander }
402512cbf1dSJens Wiklander 
403512cbf1dSJens Wiklander /*
404512cbf1dSJens Wiklander  * entry_processing_step - Generic entry on active processing
405512cbf1dSJens Wiklander  *
406512cbf1dSJens Wiklander  * @client = client reference
407512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
408512cbf1dSJens Wiklander  * @params = Invocation parameters reference
409512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
410512cbf1dSJens Wiklander  * @step - update, oneshot, final
411512cbf1dSJens Wiklander  */
412512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
413512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
414512cbf1dSJens Wiklander 				     enum processing_func function,
415512cbf1dSJens Wiklander 				     enum processing_step step)
416512cbf1dSJens Wiklander {
417512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
418512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
419512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
420512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
421512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
422512cbf1dSJens Wiklander 
423512cbf1dSJens Wiklander 	if (!client ||
424512cbf1dSJens Wiklander 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
425512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
426512cbf1dSJens Wiklander 
427512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
428512cbf1dSJens Wiklander 
429512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
430512cbf1dSJens Wiklander 	if (rc)
431512cbf1dSJens Wiklander 		return rc;
432512cbf1dSJens Wiklander 
433512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs))
434512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
435512cbf1dSJens Wiklander 
436512cbf1dSJens Wiklander 	rc = get_active_session(session, function);
437512cbf1dSJens Wiklander 	if (rc)
438512cbf1dSJens Wiklander 		return rc;
439512cbf1dSJens Wiklander 
440512cbf1dSJens Wiklander 	mecha_type = session->processing->mecha_type;
441512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, mecha_type,
442512cbf1dSJens Wiklander 						function, step);
443512cbf1dSJens Wiklander 	if (rc)
444512cbf1dSJens Wiklander 		goto out;
445512cbf1dSJens Wiklander 
446512cbf1dSJens Wiklander 	if (processing_is_tee_symm(mecha_type))
447512cbf1dSJens Wiklander 		rc = step_symm_operation(session, function, step,
448512cbf1dSJens Wiklander 					 ptypes, params);
449512cbf1dSJens Wiklander 	else
450512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
451512cbf1dSJens Wiklander 
452689f4e5bSRuchika Gupta 	if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) {
453512cbf1dSJens Wiklander 		session->processing->updated = true;
454512cbf1dSJens Wiklander 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
455512cbf1dSJens Wiklander 		     session->handle, id2str_proc(mecha_type),
456512cbf1dSJens Wiklander 		     id2str_function(function));
457512cbf1dSJens Wiklander 	}
458512cbf1dSJens Wiklander 
459512cbf1dSJens Wiklander out:
460512cbf1dSJens Wiklander 	switch (step) {
461512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
462512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
463512cbf1dSJens Wiklander 			release_active_processing(session);
464512cbf1dSJens Wiklander 		break;
465512cbf1dSJens Wiklander 	default:
466512cbf1dSJens Wiklander 		/* ONESHOT and FINAL terminates processing on success */
467512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
468512cbf1dSJens Wiklander 			release_active_processing(session);
469512cbf1dSJens Wiklander 		break;
470512cbf1dSJens Wiklander 	}
471512cbf1dSJens Wiklander 
472512cbf1dSJens Wiklander 	return rc;
473512cbf1dSJens Wiklander }
47448799892SRuchika Gupta 
4754dad6642SRuchika Gupta enum pkcs11_rc entry_processing_key(struct pkcs11_client *client,
4764dad6642SRuchika Gupta 				    uint32_t ptypes, TEE_Param *params,
4774dad6642SRuchika Gupta 				    enum processing_func function)
47848799892SRuchika Gupta {
47948799892SRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
48048799892SRuchika Gupta 						TEE_PARAM_TYPE_NONE,
48148799892SRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
48248799892SRuchika Gupta 						TEE_PARAM_TYPE_NONE);
48348799892SRuchika Gupta 	TEE_Param *ctrl = params;
48448799892SRuchika Gupta 	TEE_Param *out = params + 2;
48548799892SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
48648799892SRuchika Gupta 	struct serialargs ctrlargs = { };
48748799892SRuchika Gupta 	struct pkcs11_session *session = NULL;
48848799892SRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
48948799892SRuchika Gupta 	struct pkcs11_object_head *template = NULL;
49048799892SRuchika Gupta 	uint32_t parent_handle = 0;
49148799892SRuchika Gupta 	uint32_t obj_handle = 0;
49248799892SRuchika Gupta 	struct pkcs11_object *parent = NULL;
49348799892SRuchika Gupta 	struct obj_attrs *head = NULL;
49448799892SRuchika Gupta 	size_t template_size = 0;
4958c499324SRuchika Gupta 	void *out_buf = NULL;
4968c499324SRuchika Gupta 	uint32_t out_size = 0;
49748799892SRuchika Gupta 
49848799892SRuchika Gupta 	if (!client || ptypes != exp_pt ||
49948799892SRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
50048799892SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
50148799892SRuchika Gupta 
50248799892SRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
50348799892SRuchika Gupta 
50448799892SRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
50548799892SRuchika Gupta 	if (rc)
50648799892SRuchika Gupta 		return rc;
50748799892SRuchika Gupta 
50848799892SRuchika Gupta 	rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
50948799892SRuchika Gupta 	if (rc)
51048799892SRuchika Gupta 		return rc;
51148799892SRuchika Gupta 
51248799892SRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
51348799892SRuchika Gupta 	if (rc)
51448799892SRuchika Gupta 		goto out_free;
51548799892SRuchika Gupta 
51648799892SRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
51748799892SRuchika Gupta 	if (rc)
51848799892SRuchika Gupta 		goto out_free;
51948799892SRuchika Gupta 
52048799892SRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
52148799892SRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
52248799892SRuchika Gupta 		goto out_free;
52348799892SRuchika Gupta 	}
52448799892SRuchika Gupta 
52548799892SRuchika Gupta 	/* Return error if processing already active */
52648799892SRuchika Gupta 	rc = get_ready_session(session);
52748799892SRuchika Gupta 	if (rc)
52848799892SRuchika Gupta 		goto out_free;
52948799892SRuchika Gupta 
53048799892SRuchika Gupta 	/* Check parent handle */
53148799892SRuchika Gupta 	parent = pkcs11_handle2object(parent_handle, session);
53248799892SRuchika Gupta 	if (!parent) {
53348799892SRuchika Gupta 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
53448799892SRuchika Gupta 		goto out_free;
53548799892SRuchika Gupta 	}
53648799892SRuchika Gupta 
53748799892SRuchika Gupta 	/* Check if mechanism can be used for derivation function */
53848799892SRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
53948799892SRuchika Gupta 						function,
54048799892SRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
54148799892SRuchika Gupta 	if (rc)
54248799892SRuchika Gupta 		goto out_free;
54348799892SRuchika Gupta 
54448799892SRuchika Gupta 	/* Set the processing state to active */
54548799892SRuchika Gupta 	rc = set_processing_state(session, function, parent, NULL);
54648799892SRuchika Gupta 	if (rc)
54748799892SRuchika Gupta 		goto out_free;
54848799892SRuchika Gupta 
54948799892SRuchika Gupta 	/*
55048799892SRuchika Gupta 	 * Check if base/parent key has CKA_DERIVE set and its key type is
55148799892SRuchika Gupta 	 * compatible with the mechanism passed
55248799892SRuchika Gupta 	 */
55348799892SRuchika Gupta 	rc = check_parent_attrs_against_processing(proc_params->id, function,
55448799892SRuchika Gupta 						   parent->attributes);
555d05ab5feSRuchika Gupta 	if (rc) {
556d05ab5feSRuchika Gupta 		/*
557d05ab5feSRuchika Gupta 		 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
558d05ab5feSRuchika Gupta 		 * specified with C_Derive/Unwrap() in the specification. So
559d05ab5feSRuchika Gupta 		 * return the next most appropriate error.
560d05ab5feSRuchika Gupta 		 */
561d05ab5feSRuchika Gupta 		if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED)
562d05ab5feSRuchika Gupta 			rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT;
56348799892SRuchika Gupta 		goto out;
564d05ab5feSRuchika Gupta 	}
56548799892SRuchika Gupta 
56648799892SRuchika Gupta 	/* Check access of base/parent key */
56748799892SRuchika Gupta 	rc = check_access_attrs_against_token(session, parent->attributes);
56848799892SRuchika Gupta 	if (rc)
56948799892SRuchika Gupta 		goto out;
57048799892SRuchika Gupta 
57148799892SRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
57248799892SRuchika Gupta 	/*
57348799892SRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes
57448799892SRuchika Gupta 	 * using base/parent key attributes. Free temporary template once done.
57548799892SRuchika Gupta 	 */
57648799892SRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
57748799892SRuchika Gupta 					     parent->attributes,
57848799892SRuchika Gupta 					     function,
57948799892SRuchika Gupta 					     proc_params->id,
58048799892SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
58148799892SRuchika Gupta 	if (rc)
58248799892SRuchika Gupta 		goto out;
58348799892SRuchika Gupta 
58448799892SRuchika Gupta 	TEE_Free(template);
58548799892SRuchika Gupta 	template = NULL;
58648799892SRuchika Gupta 
58748799892SRuchika Gupta 	/* check_created_attrs() is called later once key size is known */
58848799892SRuchika Gupta 
58948799892SRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
59048799892SRuchika Gupta 	if (rc)
59148799892SRuchika Gupta 		goto out;
59248799892SRuchika Gupta 
59348799892SRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
59448799892SRuchika Gupta 	if (rc)
59548799892SRuchika Gupta 		goto out;
59648799892SRuchika Gupta 
5978c499324SRuchika Gupta 	if (processing_is_tee_symm(proc_params->id)) {
59848799892SRuchika Gupta 		/*
59948799892SRuchika Gupta 		 * These derivation mechanism require encryption to be
60048799892SRuchika Gupta 		 * performed on the data passed in proc_params by parent
60148799892SRuchika Gupta 		 * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT
60248799892SRuchika Gupta 		 * to init_symm_operation()
60348799892SRuchika Gupta 		 */
60448799892SRuchika Gupta 		rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
60548799892SRuchika Gupta 					 proc_params, parent);
60648799892SRuchika Gupta 		if (rc)
60748799892SRuchika Gupta 			goto out;
60848799892SRuchika Gupta 
6098c499324SRuchika Gupta 		session->processing->mecha_type = proc_params->id;
6108c499324SRuchika Gupta 
6118c499324SRuchika Gupta 		rc = derive_key_by_symm_enc(session, &out_buf, &out_size);
61248799892SRuchika Gupta 		if (rc)
61348799892SRuchika Gupta 			goto out;
6148c499324SRuchika Gupta 	} else {
61548799892SRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
61648799892SRuchika Gupta 		goto out;
61748799892SRuchika Gupta 	}
61848799892SRuchika Gupta 
6198c499324SRuchika Gupta 	rc = set_key_data(&head, out_buf, out_size);
6208c499324SRuchika Gupta 	if (rc)
6218c499324SRuchika Gupta 		goto out;
6228c499324SRuchika Gupta 
6238c499324SRuchika Gupta 	TEE_Free(out_buf);
6248c499324SRuchika Gupta 	out_buf = NULL;
6258c499324SRuchika Gupta 
62648799892SRuchika Gupta 	TEE_Free(proc_params);
62748799892SRuchika Gupta 	proc_params = NULL;
62848799892SRuchika Gupta 
62948799892SRuchika Gupta 	/*
63048799892SRuchika Gupta 	 * Object is ready, register it and return a handle.
63148799892SRuchika Gupta 	 */
63248799892SRuchika Gupta 	rc = create_object(session, head, &obj_handle);
63348799892SRuchika Gupta 	if (rc)
63448799892SRuchika Gupta 		goto out;
63548799892SRuchika Gupta 
63648799892SRuchika Gupta 	/*
63748799892SRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
63848799892SRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
63948799892SRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
64048799892SRuchika Gupta 	 * be freed at function out.
64148799892SRuchika Gupta 	 */
64248799892SRuchika Gupta 	head = NULL;
64348799892SRuchika Gupta 
64448799892SRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
64548799892SRuchika Gupta 	out->memref.size = sizeof(obj_handle);
64648799892SRuchika Gupta 
64748799892SRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32,
64848799892SRuchika Gupta 	     session->handle, obj_handle);
64948799892SRuchika Gupta 
65048799892SRuchika Gupta out:
65148799892SRuchika Gupta 	release_active_processing(session);
65248799892SRuchika Gupta out_free:
65348799892SRuchika Gupta 	TEE_Free(proc_params);
65448799892SRuchika Gupta 	TEE_Free(template);
65548799892SRuchika Gupta 	TEE_Free(head);
6568c499324SRuchika Gupta 	TEE_Free(out_buf);
65748799892SRuchika Gupta 
65848799892SRuchika Gupta 	return rc;
65948799892SRuchika Gupta }
660*eb6141b6SVesa Jääskeläinen 
661*eb6141b6SVesa Jääskeläinen enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client,
662*eb6141b6SVesa Jääskeläinen 					       uint32_t ptypes,
663*eb6141b6SVesa Jääskeläinen 					       TEE_Param *params)
664*eb6141b6SVesa Jääskeläinen {
665*eb6141b6SVesa Jääskeläinen 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
666*eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
667*eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
668*eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE);
669*eb6141b6SVesa Jääskeläinen 	TEE_Param *ctrl = params;
670*eb6141b6SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
671*eb6141b6SVesa Jääskeläinen 	struct serialargs ctrlargs = { };
672*eb6141b6SVesa Jääskeläinen 	struct pkcs11_session *session = NULL;
673*eb6141b6SVesa Jääskeläinen 	enum processing_func function = PKCS11_FUNCTION_UNKNOWN;
674*eb6141b6SVesa Jääskeläinen 	uint32_t cmd = 0;
675*eb6141b6SVesa Jääskeläinen 
676*eb6141b6SVesa Jääskeläinen 	if (!client || ptypes != exp_pt)
677*eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
678*eb6141b6SVesa Jääskeläinen 
679*eb6141b6SVesa Jääskeläinen 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
680*eb6141b6SVesa Jääskeläinen 
681*eb6141b6SVesa Jääskeläinen 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
682*eb6141b6SVesa Jääskeläinen 	if (rc)
683*eb6141b6SVesa Jääskeläinen 		return rc;
684*eb6141b6SVesa Jääskeläinen 
685*eb6141b6SVesa Jääskeläinen 	rc = serialargs_get_u32(&ctrlargs, &cmd);
686*eb6141b6SVesa Jääskeläinen 
687*eb6141b6SVesa Jääskeläinen 	if (serialargs_remaining_bytes(&ctrlargs))
688*eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
689*eb6141b6SVesa Jääskeläinen 
690*eb6141b6SVesa Jääskeläinen 	function = func_for_cmd(cmd);
691*eb6141b6SVesa Jääskeläinen 	if (function == PKCS11_FUNCTION_UNKNOWN)
692*eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
693*eb6141b6SVesa Jääskeläinen 
694*eb6141b6SVesa Jääskeläinen 	rc = get_active_session(session, function);
695*eb6141b6SVesa Jääskeläinen 	if (rc)
696*eb6141b6SVesa Jääskeläinen 		return rc;
697*eb6141b6SVesa Jääskeläinen 
698*eb6141b6SVesa Jääskeläinen 	release_active_processing(session);
699*eb6141b6SVesa Jääskeläinen 
700*eb6141b6SVesa Jääskeläinen 	DMSG("PKCS11 session %"PRIu32": release processing", session->handle);
701*eb6141b6SVesa Jääskeläinen 
702*eb6141b6SVesa Jääskeläinen 	return PKCS11_CKR_OK;
703*eb6141b6SVesa Jääskeläinen }
704