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