xref: /optee_os/ta/pkcs11/src/processing.c (revision eb6141b6e9d643b3a2cd1a40de52f1d9a80fcb30)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017-2020, Linaro Limited
4  */
5 
6 #include <assert.h>
7 #include <pkcs11_ta.h>
8 #include <string.h>
9 #include <tee_api_defines.h>
10 #include <tee_internal_api.h>
11 #include <tee_internal_api_extensions.h>
12 #include <util.h>
13 
14 #include "attributes.h"
15 #include "object.h"
16 #include "pkcs11_attributes.h"
17 #include "pkcs11_helpers.h"
18 #include "pkcs11_token.h"
19 #include "processing.h"
20 #include "serializer.h"
21 
22 static enum pkcs11_rc get_ready_session(struct pkcs11_session *session)
23 {
24 	if (session_is_active(session))
25 		return PKCS11_CKR_OPERATION_ACTIVE;
26 
27 	return PKCS11_CKR_OK;
28 }
29 
30 static enum processing_func func_for_cmd(enum pkcs11_ta_cmd cmd)
31 {
32 	switch (cmd) {
33 	case PKCS11_CMD_ENCRYPT_UPDATE:
34 	case PKCS11_CMD_ENCRYPT_ONESHOT:
35 	case PKCS11_CMD_ENCRYPT_FINAL:
36 		return PKCS11_FUNCTION_ENCRYPT;
37 	case PKCS11_CMD_DECRYPT_UPDATE:
38 	case PKCS11_CMD_DECRYPT_ONESHOT:
39 	case PKCS11_CMD_DECRYPT_FINAL:
40 		return PKCS11_FUNCTION_DECRYPT;
41 	case PKCS11_CMD_SIGN_ONESHOT:
42 	case PKCS11_CMD_SIGN_UPDATE:
43 	case PKCS11_CMD_SIGN_FINAL:
44 		return PKCS11_FUNCTION_SIGN;
45 	case PKCS11_CMD_VERIFY_ONESHOT:
46 	case PKCS11_CMD_VERIFY_UPDATE:
47 	case PKCS11_CMD_VERIFY_FINAL:
48 		return PKCS11_FUNCTION_VERIFY;
49 	default:
50 		return PKCS11_FUNCTION_UNKNOWN;
51 	}
52 }
53 
54 static bool func_matches_state(enum processing_func function,
55 			       enum pkcs11_proc_state state)
56 {
57 	switch (function) {
58 	case PKCS11_FUNCTION_ENCRYPT:
59 		return state == PKCS11_SESSION_ENCRYPTING ||
60 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING ||
61 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
62 	case PKCS11_FUNCTION_DECRYPT:
63 		return state == PKCS11_SESSION_DECRYPTING ||
64 		       state == PKCS11_SESSION_DECRYPTING_DIGESTING ||
65 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
66 	case PKCS11_FUNCTION_DIGEST:
67 		return state == PKCS11_SESSION_DIGESTING ||
68 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING;
69 	case PKCS11_FUNCTION_SIGN:
70 		return state == PKCS11_SESSION_SIGNING ||
71 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
72 	case PKCS11_FUNCTION_VERIFY:
73 		return state == PKCS11_SESSION_VERIFYING ||
74 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
75 	case PKCS11_FUNCTION_SIGN_RECOVER:
76 		return state == PKCS11_SESSION_SIGNING_RECOVER;
77 	case PKCS11_FUNCTION_VERIFY_RECOVER:
78 		return state == PKCS11_SESSION_SIGNING_RECOVER;
79 	default:
80 		TEE_Panic(function);
81 		return false;
82 	}
83 }
84 
85 static enum pkcs11_rc get_active_session(struct pkcs11_session *session,
86 					 enum processing_func function)
87 {
88 	enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED;
89 
90 	if (session->processing &&
91 	    func_matches_state(function, session->processing->state))
92 		rc = PKCS11_CKR_OK;
93 
94 	return rc;
95 }
96 
97 void release_active_processing(struct pkcs11_session *session)
98 {
99 	if (!session->processing)
100 		return;
101 
102 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
103 		TEE_FreeOperation(session->processing->tee_op_handle);
104 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
105 	}
106 
107 	TEE_Free(session->processing->extra_ctx);
108 
109 	TEE_Free(session->processing);
110 	session->processing = NULL;
111 }
112 
113 size_t get_object_key_bit_size(struct pkcs11_object *obj)
114 {
115 	uint32_t a_size = 0;
116 	struct obj_attrs *attrs = obj->attributes;
117 
118 	switch (get_key_type(attrs)) {
119 	case PKCS11_CKK_AES:
120 	case PKCS11_CKK_GENERIC_SECRET:
121 	case PKCS11_CKK_MD5_HMAC:
122 	case PKCS11_CKK_SHA_1_HMAC:
123 	case PKCS11_CKK_SHA224_HMAC:
124 	case PKCS11_CKK_SHA256_HMAC:
125 	case PKCS11_CKK_SHA384_HMAC:
126 	case PKCS11_CKK_SHA512_HMAC:
127 		if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
128 			return 0;
129 
130 		return a_size * 8;
131 	default:
132 		TEE_Panic(0);
133 		return 0;
134 	}
135 }
136 
137 static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
138 {
139 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
140 	void *data = NULL;
141 	uint32_t data_size = 0;
142 	uint32_t value_len = 0;
143 	void *value = NULL;
144 
145 	if (!*head)
146 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
147 
148 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
149 	if (rc || data_size != sizeof(uint32_t)) {
150 		DMSG("%s", rc ? "No attribute value_len found" :
151 		     "Invalid size for attribute VALUE_LEN");
152 
153 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
154 	}
155 	TEE_MemMove(&value_len, data, data_size);
156 
157 	/* Remove the default empty value attribute if found */
158 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
159 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
160 		return PKCS11_CKR_GENERAL_ERROR;
161 
162 	value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
163 	if (!value)
164 		return PKCS11_CKR_DEVICE_MEMORY;
165 
166 	TEE_GenerateRandom(value, value_len);
167 
168 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
169 
170 	TEE_Free(value);
171 
172 	return rc;
173 }
174 
175 enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
176 				     uint32_t ptypes, TEE_Param *params)
177 {
178 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
179 						TEE_PARAM_TYPE_NONE,
180 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
181 						TEE_PARAM_TYPE_NONE);
182 	TEE_Param *ctrl = params;
183 	TEE_Param *out = params + 2;
184 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
185 	struct serialargs ctrlargs = { };
186 	struct pkcs11_session *session = NULL;
187 	struct pkcs11_attribute_head *proc_params = NULL;
188 	struct obj_attrs *head = NULL;
189 	struct pkcs11_object_head *template = NULL;
190 	size_t template_size = 0;
191 	uint32_t obj_handle = 0;
192 
193 	if (!client || ptypes != exp_pt ||
194 	    out->memref.size != sizeof(obj_handle))
195 		return PKCS11_CKR_ARGUMENTS_BAD;
196 
197 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
198 
199 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
200 	if (rc)
201 		return rc;
202 
203 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
204 	if (rc)
205 		goto out;
206 
207 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
208 	if (rc)
209 		goto out;
210 
211 	if (serialargs_remaining_bytes(&ctrlargs)) {
212 		rc = PKCS11_CKR_ARGUMENTS_BAD;
213 		goto out;
214 	}
215 
216 	rc = get_ready_session(session);
217 	if (rc)
218 		goto out;
219 
220 	template_size = sizeof(*template) + template->attrs_size;
221 
222 	rc = check_mechanism_against_processing(session, proc_params->id,
223 						PKCS11_FUNCTION_GENERATE,
224 						PKCS11_FUNC_STEP_INIT);
225 	if (rc) {
226 		DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
227 		goto out;
228 	}
229 
230 	/*
231 	 * Prepare a clean initial state for the requested object attributes.
232 	 * Free temporary template once done.
233 	 */
234 	rc = create_attributes_from_template(&head, template, template_size,
235 					     NULL, PKCS11_FUNCTION_GENERATE,
236 					     proc_params->id,
237 					     PKCS11_CKO_UNDEFINED_ID);
238 	if (rc)
239 		goto out;
240 
241 	TEE_Free(template);
242 	template = NULL;
243 
244 	rc = check_created_attrs(head, NULL);
245 	if (rc)
246 		goto out;
247 
248 	rc = check_created_attrs_against_processing(proc_params->id, head);
249 	if (rc)
250 		goto out;
251 
252 	rc = check_created_attrs_against_token(session, head);
253 	if (rc)
254 		goto out;
255 
256 	/*
257 	 * Execute target processing and add value as attribute
258 	 * PKCS11_CKA_VALUE. Symm key generation: depends on target
259 	 * processing to be used.
260 	 */
261 	switch (proc_params->id) {
262 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
263 	case PKCS11_CKM_AES_KEY_GEN:
264 		/* Generate random of size specified by attribute VALUE_LEN */
265 		rc = generate_random_key_value(&head);
266 		if (rc)
267 			goto out;
268 		break;
269 
270 	default:
271 		rc = PKCS11_CKR_MECHANISM_INVALID;
272 		goto out;
273 	}
274 
275 	TEE_Free(proc_params);
276 	proc_params = NULL;
277 
278 	/*
279 	 * Object is ready, register it and return a handle.
280 	 */
281 	rc = create_object(session, head, &obj_handle);
282 	if (rc)
283 		goto out;
284 
285 	/*
286 	 * Now obj_handle (through the related struct pkcs11_object instance)
287 	 * owns the serialized buffer that holds the object attributes.
288 	 * We reset head to NULL as it is no more the buffer owner and would
289 	 * be freed at function out.
290 	 */
291 	head = NULL;
292 
293 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
294 	out->memref.size = sizeof(obj_handle);
295 
296 	DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
297 	     session->handle, obj_handle);
298 
299 out:
300 	TEE_Free(proc_params);
301 	TEE_Free(template);
302 	TEE_Free(head);
303 
304 	return rc;
305 }
306 
307 /*
308  * entry_processing_init - Generic entry for initializing a processing
309  *
310  * @client = client reference
311  * @ptype = Invocation parameter types
312  * @params = Invocation parameters reference
313  * @function - encrypt, decrypt, sign, verify, digest, ...
314  */
315 enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
316 				     uint32_t ptypes, TEE_Param *params,
317 				     enum processing_func function)
318 {
319 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
320 						TEE_PARAM_TYPE_NONE,
321 						TEE_PARAM_TYPE_NONE,
322 						TEE_PARAM_TYPE_NONE);
323 	TEE_Param *ctrl = params;
324 	enum pkcs11_rc rc = PKCS11_CKR_OK;
325 	struct serialargs ctrlargs = { };
326 	struct pkcs11_session *session = NULL;
327 	struct pkcs11_attribute_head *proc_params = NULL;
328 	uint32_t key_handle = 0;
329 	struct pkcs11_object *obj = NULL;
330 
331 	if (!client || ptypes != exp_pt)
332 		return PKCS11_CKR_ARGUMENTS_BAD;
333 
334 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
335 
336 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
337 	if (rc)
338 		return rc;
339 
340 	rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
341 	if (rc)
342 		return rc;
343 
344 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
345 	if (rc)
346 		return rc;
347 
348 	if (serialargs_remaining_bytes(&ctrlargs)) {
349 		rc = PKCS11_CKR_ARGUMENTS_BAD;
350 		goto out;
351 	}
352 
353 	rc = get_ready_session(session);
354 	if (rc)
355 		goto out;
356 
357 	obj = pkcs11_handle2object(key_handle, session);
358 	if (!obj) {
359 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
360 		goto out;
361 	}
362 
363 	rc = set_processing_state(session, function, obj, NULL);
364 	if (rc)
365 		goto out;
366 
367 	rc = check_mechanism_against_processing(session, proc_params->id,
368 						function,
369 						PKCS11_FUNC_STEP_INIT);
370 	if (rc)
371 		goto out;
372 
373 	rc = check_parent_attrs_against_processing(proc_params->id, function,
374 						   obj->attributes);
375 	if (rc)
376 		goto out;
377 
378 	rc = check_access_attrs_against_token(session, obj->attributes);
379 	if (rc)
380 		goto out;
381 
382 	if (processing_is_tee_symm(proc_params->id))
383 		rc = init_symm_operation(session, function, proc_params, obj);
384 	else
385 		rc = PKCS11_CKR_MECHANISM_INVALID;
386 
387 	if (rc == PKCS11_CKR_OK) {
388 		session->processing->mecha_type = proc_params->id;
389 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
390 		     session->handle, id2str_proc(proc_params->id),
391 		     id2str_function(function));
392 	}
393 
394 out:
395 	if (rc && session)
396 		release_active_processing(session);
397 
398 	TEE_Free(proc_params);
399 
400 	return rc;
401 }
402 
403 /*
404  * entry_processing_step - Generic entry on active processing
405  *
406  * @client = client reference
407  * @ptype = Invocation parameter types
408  * @params = Invocation parameters reference
409  * @function - encrypt, decrypt, sign, verify, digest, ...
410  * @step - update, oneshot, final
411  */
412 enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
413 				     uint32_t ptypes, TEE_Param *params,
414 				     enum processing_func function,
415 				     enum processing_step step)
416 {
417 	TEE_Param *ctrl = params;
418 	enum pkcs11_rc rc = PKCS11_CKR_OK;
419 	struct serialargs ctrlargs = { };
420 	struct pkcs11_session *session = NULL;
421 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
422 
423 	if (!client ||
424 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
425 		return PKCS11_CKR_ARGUMENTS_BAD;
426 
427 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
428 
429 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
430 	if (rc)
431 		return rc;
432 
433 	if (serialargs_remaining_bytes(&ctrlargs))
434 		return PKCS11_CKR_ARGUMENTS_BAD;
435 
436 	rc = get_active_session(session, function);
437 	if (rc)
438 		return rc;
439 
440 	mecha_type = session->processing->mecha_type;
441 	rc = check_mechanism_against_processing(session, mecha_type,
442 						function, step);
443 	if (rc)
444 		goto out;
445 
446 	if (processing_is_tee_symm(mecha_type))
447 		rc = step_symm_operation(session, function, step,
448 					 ptypes, params);
449 	else
450 		rc = PKCS11_CKR_MECHANISM_INVALID;
451 
452 	if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) {
453 		session->processing->updated = true;
454 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
455 		     session->handle, id2str_proc(mecha_type),
456 		     id2str_function(function));
457 	}
458 
459 out:
460 	switch (step) {
461 	case PKCS11_FUNC_STEP_UPDATE:
462 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
463 			release_active_processing(session);
464 		break;
465 	default:
466 		/* ONESHOT and FINAL terminates processing on success */
467 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
468 			release_active_processing(session);
469 		break;
470 	}
471 
472 	return rc;
473 }
474 
475 enum pkcs11_rc entry_processing_key(struct pkcs11_client *client,
476 				    uint32_t ptypes, TEE_Param *params,
477 				    enum processing_func function)
478 {
479 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
480 						TEE_PARAM_TYPE_NONE,
481 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
482 						TEE_PARAM_TYPE_NONE);
483 	TEE_Param *ctrl = params;
484 	TEE_Param *out = params + 2;
485 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
486 	struct serialargs ctrlargs = { };
487 	struct pkcs11_session *session = NULL;
488 	struct pkcs11_attribute_head *proc_params = NULL;
489 	struct pkcs11_object_head *template = NULL;
490 	uint32_t parent_handle = 0;
491 	uint32_t obj_handle = 0;
492 	struct pkcs11_object *parent = NULL;
493 	struct obj_attrs *head = NULL;
494 	size_t template_size = 0;
495 	void *out_buf = NULL;
496 	uint32_t out_size = 0;
497 
498 	if (!client || ptypes != exp_pt ||
499 	    out->memref.size != sizeof(obj_handle))
500 		return PKCS11_CKR_ARGUMENTS_BAD;
501 
502 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
503 
504 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
505 	if (rc)
506 		return rc;
507 
508 	rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
509 	if (rc)
510 		return rc;
511 
512 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
513 	if (rc)
514 		goto out_free;
515 
516 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
517 	if (rc)
518 		goto out_free;
519 
520 	if (serialargs_remaining_bytes(&ctrlargs)) {
521 		rc = PKCS11_CKR_ARGUMENTS_BAD;
522 		goto out_free;
523 	}
524 
525 	/* Return error if processing already active */
526 	rc = get_ready_session(session);
527 	if (rc)
528 		goto out_free;
529 
530 	/* Check parent handle */
531 	parent = pkcs11_handle2object(parent_handle, session);
532 	if (!parent) {
533 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
534 		goto out_free;
535 	}
536 
537 	/* Check if mechanism can be used for derivation function */
538 	rc = check_mechanism_against_processing(session, proc_params->id,
539 						function,
540 						PKCS11_FUNC_STEP_INIT);
541 	if (rc)
542 		goto out_free;
543 
544 	/* Set the processing state to active */
545 	rc = set_processing_state(session, function, parent, NULL);
546 	if (rc)
547 		goto out_free;
548 
549 	/*
550 	 * Check if base/parent key has CKA_DERIVE set and its key type is
551 	 * compatible with the mechanism passed
552 	 */
553 	rc = check_parent_attrs_against_processing(proc_params->id, function,
554 						   parent->attributes);
555 	if (rc) {
556 		/*
557 		 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
558 		 * specified with C_Derive/Unwrap() in the specification. So
559 		 * return the next most appropriate error.
560 		 */
561 		if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED)
562 			rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT;
563 		goto out;
564 	}
565 
566 	/* Check access of base/parent key */
567 	rc = check_access_attrs_against_token(session, parent->attributes);
568 	if (rc)
569 		goto out;
570 
571 	template_size = sizeof(*template) + template->attrs_size;
572 	/*
573 	 * Prepare a clean initial state for the requested object attributes
574 	 * using base/parent key attributes. Free temporary template once done.
575 	 */
576 	rc = create_attributes_from_template(&head, template, template_size,
577 					     parent->attributes,
578 					     function,
579 					     proc_params->id,
580 					     PKCS11_CKO_UNDEFINED_ID);
581 	if (rc)
582 		goto out;
583 
584 	TEE_Free(template);
585 	template = NULL;
586 
587 	/* check_created_attrs() is called later once key size is known */
588 
589 	rc = check_created_attrs_against_processing(proc_params->id, head);
590 	if (rc)
591 		goto out;
592 
593 	rc = check_created_attrs_against_token(session, head);
594 	if (rc)
595 		goto out;
596 
597 	if (processing_is_tee_symm(proc_params->id)) {
598 		/*
599 		 * These derivation mechanism require encryption to be
600 		 * performed on the data passed in proc_params by parent
601 		 * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT
602 		 * to init_symm_operation()
603 		 */
604 		rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
605 					 proc_params, parent);
606 		if (rc)
607 			goto out;
608 
609 		session->processing->mecha_type = proc_params->id;
610 
611 		rc = derive_key_by_symm_enc(session, &out_buf, &out_size);
612 		if (rc)
613 			goto out;
614 	} else {
615 		rc = PKCS11_CKR_MECHANISM_INVALID;
616 		goto out;
617 	}
618 
619 	rc = set_key_data(&head, out_buf, out_size);
620 	if (rc)
621 		goto out;
622 
623 	TEE_Free(out_buf);
624 	out_buf = NULL;
625 
626 	TEE_Free(proc_params);
627 	proc_params = NULL;
628 
629 	/*
630 	 * Object is ready, register it and return a handle.
631 	 */
632 	rc = create_object(session, head, &obj_handle);
633 	if (rc)
634 		goto out;
635 
636 	/*
637 	 * Now obj_handle (through the related struct pkcs11_object instance)
638 	 * owns the serialized buffer that holds the object attributes.
639 	 * We reset head to NULL as it is no more the buffer owner and would
640 	 * be freed at function out.
641 	 */
642 	head = NULL;
643 
644 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
645 	out->memref.size = sizeof(obj_handle);
646 
647 	DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32,
648 	     session->handle, obj_handle);
649 
650 out:
651 	release_active_processing(session);
652 out_free:
653 	TEE_Free(proc_params);
654 	TEE_Free(template);
655 	TEE_Free(head);
656 	TEE_Free(out_buf);
657 
658 	return rc;
659 }
660 
661 enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client,
662 					       uint32_t ptypes,
663 					       TEE_Param *params)
664 {
665 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
666 						TEE_PARAM_TYPE_NONE,
667 						TEE_PARAM_TYPE_NONE,
668 						TEE_PARAM_TYPE_NONE);
669 	TEE_Param *ctrl = params;
670 	enum pkcs11_rc rc = PKCS11_CKR_OK;
671 	struct serialargs ctrlargs = { };
672 	struct pkcs11_session *session = NULL;
673 	enum processing_func function = PKCS11_FUNCTION_UNKNOWN;
674 	uint32_t cmd = 0;
675 
676 	if (!client || ptypes != exp_pt)
677 		return PKCS11_CKR_ARGUMENTS_BAD;
678 
679 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
680 
681 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
682 	if (rc)
683 		return rc;
684 
685 	rc = serialargs_get_u32(&ctrlargs, &cmd);
686 
687 	if (serialargs_remaining_bytes(&ctrlargs))
688 		return PKCS11_CKR_ARGUMENTS_BAD;
689 
690 	function = func_for_cmd(cmd);
691 	if (function == PKCS11_FUNCTION_UNKNOWN)
692 		return PKCS11_CKR_ARGUMENTS_BAD;
693 
694 	rc = get_active_session(session, function);
695 	if (rc)
696 		return rc;
697 
698 	release_active_processing(session);
699 
700 	DMSG("PKCS11 session %"PRIu32": release processing", session->handle);
701 
702 	return PKCS11_CKR_OK;
703 }
704