xref: /optee_os/ta/pkcs11/src/processing.c (revision 02b16804d0d9b434b1ceb1cfa000c5778a742967)
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 enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj,
313 					    uint32_t attribute,
314 					    void **data, size_t *size)
315 {
316 	TEE_Result res = TEE_ERROR_GENERIC;
317 	void *ptr = NULL;
318 	uint32_t sz = 0;
319 
320 	res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz);
321 	if (res != TEE_ERROR_SHORT_BUFFER)
322 		return PKCS11_CKR_FUNCTION_FAILED;
323 
324 	ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
325 	if (!ptr)
326 		return PKCS11_CKR_DEVICE_MEMORY;
327 
328 	res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz);
329 	if (res) {
330 		TEE_Free(ptr);
331 	} else {
332 		*data = ptr;
333 		*size = sz;
334 	}
335 
336 	return tee2pkcs_error(res);
337 }
338 
339 enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head,
340 				      uint32_t pkcs11_id,
341 				      TEE_ObjectHandle tee_obj,
342 				      uint32_t tee_id)
343 {
344 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
345 	void *a_ptr = NULL;
346 	size_t a_size = 0;
347 
348 	rc = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size);
349 	if (rc)
350 		goto out;
351 
352 	rc = add_attribute(head, pkcs11_id, a_ptr, a_size);
353 
354 	TEE_Free(a_ptr);
355 
356 out:
357 	if (rc)
358 		EMSG("Failed TEE attribute %#"PRIx32" for %#"PRIx32"/%s",
359 		     tee_id, pkcs11_id, id2str_attr(pkcs11_id));
360 	return rc;
361 }
362 
363 enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client,
364 				       uint32_t ptypes, TEE_Param *params)
365 {
366 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
367 						TEE_PARAM_TYPE_NONE,
368 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
369 						TEE_PARAM_TYPE_NONE);
370 	TEE_Param *ctrl = params;
371 	TEE_Param *out = params + 2;
372 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
373 	struct serialargs ctrlargs = { };
374 	struct pkcs11_session *session = NULL;
375 	struct pkcs11_attribute_head *proc_params = NULL;
376 	struct obj_attrs *pub_head = NULL;
377 	struct obj_attrs *priv_head = NULL;
378 	struct pkcs11_object_head *pub_template = NULL;
379 	struct pkcs11_object_head *priv_template = NULL;
380 	struct pkcs11_object *object = NULL;
381 	size_t pub_template_size = 0;
382 	size_t priv_template_size = 0;
383 	uint32_t pubkey_handle = 0;
384 	uint32_t privkey_handle = 0;
385 	uint32_t *hdl_ptr = NULL;
386 	size_t out_ref_size = sizeof(pubkey_handle) + sizeof(privkey_handle);
387 
388 	if (!client || ptypes != exp_pt || out->memref.size != out_ref_size)
389 		return PKCS11_CKR_ARGUMENTS_BAD;
390 
391 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
392 
393 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
394 	if (rc)
395 		return rc;
396 
397 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
398 	if (rc)
399 		goto out;
400 
401 	rc = serialargs_alloc_get_attributes(&ctrlargs, &pub_template);
402 	if (rc)
403 		goto out;
404 
405 	rc = serialargs_alloc_get_attributes(&ctrlargs, &priv_template);
406 	if (rc)
407 		goto out;
408 
409 	if (serialargs_remaining_bytes(&ctrlargs)) {
410 		rc = PKCS11_CKR_ARGUMENTS_BAD;
411 		goto out;
412 	}
413 
414 	rc = get_ready_session(session);
415 	if (rc)
416 		goto out;
417 
418 	rc = check_mechanism_against_processing(session, proc_params->id,
419 						PKCS11_FUNCTION_GENERATE_PAIR,
420 						PKCS11_FUNC_STEP_INIT);
421 	if (rc)
422 		goto out;
423 
424 	pub_template_size = sizeof(*pub_template) + pub_template->attrs_size;
425 
426 	rc = create_attributes_from_template(&pub_head, pub_template,
427 					     pub_template_size, NULL,
428 					     PKCS11_FUNCTION_GENERATE_PAIR,
429 					     proc_params->id,
430 					     PKCS11_CKO_PUBLIC_KEY);
431 	if (rc)
432 		goto out;
433 
434 	TEE_Free(pub_template);
435 	pub_template = NULL;
436 
437 	priv_template_size = sizeof(*priv_template) +
438 			     priv_template->attrs_size;
439 
440 	rc = create_attributes_from_template(&priv_head, priv_template,
441 					     priv_template_size, NULL,
442 					     PKCS11_FUNCTION_GENERATE_PAIR,
443 					     proc_params->id,
444 					     PKCS11_CKO_PRIVATE_KEY);
445 	if (rc)
446 		goto out;
447 
448 	TEE_Free(priv_template);
449 	priv_template = NULL;
450 
451 	/* Generate CKA_ID for keys if not specified by the templates */
452 	rc = add_missing_attribute_id(&pub_head, &priv_head);
453 	if (rc)
454 		goto out;
455 
456 	/* Check created object against processing and token state */
457 	rc = check_created_attrs(pub_head, priv_head);
458 	if (rc)
459 		goto out;
460 
461 	rc = check_created_attrs_against_processing(proc_params->id, pub_head);
462 	if (rc)
463 		goto out;
464 
465 	rc = check_created_attrs_against_processing(proc_params->id,
466 						    priv_head);
467 	if (rc)
468 		goto out;
469 
470 	rc = check_created_attrs_against_token(session, pub_head);
471 	if (rc)
472 		goto out;
473 
474 	rc = check_access_attrs_against_token(session, pub_head);
475 	if (rc)
476 		goto out;
477 
478 	rc = check_created_attrs_against_token(session, priv_head);
479 	if (rc)
480 		goto out;
481 
482 	rc = check_access_attrs_against_token(session, priv_head);
483 	if (rc)
484 		goto out;
485 
486 	/* Generate key pair */
487 	switch (proc_params->id) {
488 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
489 		rc = generate_ec_keys(proc_params, &pub_head, &priv_head);
490 		break;
491 	default:
492 		rc = PKCS11_CKR_MECHANISM_INVALID;
493 		break;
494 	}
495 	if (rc)
496 		goto out;
497 
498 	TEE_Free(proc_params);
499 	proc_params = NULL;
500 
501 	/*
502 	 * Object is ready, register it and return a handle.
503 	 */
504 	rc = create_object(session, pub_head, &pubkey_handle);
505 	if (rc)
506 		goto out;
507 
508 	/*
509 	 * Now obj_handle (through the related struct pkcs11_object instance)
510 	 * owns the serialized buffer that holds the object attributes.
511 	 * We reset local pub_head to NULL to mark that ownership has been
512 	 * transferred.
513 	 */
514 	pub_head = NULL;
515 
516 	rc = create_object(session, priv_head, &privkey_handle);
517 	if (rc)
518 		goto out;
519 
520 	/* Ownership has been transferred so mark it with NULL */
521 	priv_head = NULL;
522 
523 	hdl_ptr = (uint32_t *)out->memref.buffer;
524 
525 	TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(pubkey_handle));
526 	TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(privkey_handle));
527 
528 	pubkey_handle = 0;
529 	privkey_handle = 0;
530 
531 	DMSG("PKCS11 session %"PRIu32": create key pair %#"PRIx32"/%#"PRIx32,
532 	     session->handle, privkey_handle, pubkey_handle);
533 
534 out:
535 	if (pubkey_handle) {
536 		object = pkcs11_handle2object(pubkey_handle, session);
537 		if (!object)
538 			TEE_Panic(0);
539 		destroy_object(session, object, false);
540 	}
541 	TEE_Free(priv_head);
542 	TEE_Free(pub_head);
543 	TEE_Free(priv_template);
544 	TEE_Free(pub_template);
545 	TEE_Free(proc_params);
546 
547 	return rc;
548 }
549 
550 /*
551  * entry_processing_init - Generic entry for initializing a processing
552  *
553  * @client = client reference
554  * @ptype = Invocation parameter types
555  * @params = Invocation parameters reference
556  * @function - encrypt, decrypt, sign, verify, digest, ...
557  */
558 enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
559 				     uint32_t ptypes, TEE_Param *params,
560 				     enum processing_func function)
561 {
562 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
563 						TEE_PARAM_TYPE_NONE,
564 						TEE_PARAM_TYPE_NONE,
565 						TEE_PARAM_TYPE_NONE);
566 	TEE_Param *ctrl = params;
567 	enum pkcs11_rc rc = PKCS11_CKR_OK;
568 	struct serialargs ctrlargs = { };
569 	struct pkcs11_session *session = NULL;
570 	struct pkcs11_attribute_head *proc_params = NULL;
571 	uint32_t key_handle = 0;
572 	struct pkcs11_object *obj = NULL;
573 
574 	if (!client || ptypes != exp_pt)
575 		return PKCS11_CKR_ARGUMENTS_BAD;
576 
577 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
578 
579 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
580 	if (rc)
581 		return rc;
582 
583 	if (function != PKCS11_FUNCTION_DIGEST) {
584 		rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
585 		if (rc)
586 			return rc;
587 	}
588 
589 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
590 	if (rc)
591 		return rc;
592 
593 	if (serialargs_remaining_bytes(&ctrlargs)) {
594 		rc = PKCS11_CKR_ARGUMENTS_BAD;
595 		goto out;
596 	}
597 
598 	rc = get_ready_session(session);
599 	if (rc)
600 		goto out;
601 
602 	if (function != PKCS11_FUNCTION_DIGEST) {
603 		obj = pkcs11_handle2object(key_handle, session);
604 		if (!obj) {
605 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
606 			goto out;
607 		}
608 	}
609 
610 	rc = set_processing_state(session, function, obj, NULL);
611 	if (rc)
612 		goto out;
613 
614 	rc = check_mechanism_against_processing(session, proc_params->id,
615 						function,
616 						PKCS11_FUNC_STEP_INIT);
617 	if (rc)
618 		goto out;
619 
620 	if (obj) {
621 		rc = check_parent_attrs_against_processing(proc_params->id,
622 							   function,
623 							   obj->attributes);
624 		if (rc)
625 			goto out;
626 
627 		rc = check_access_attrs_against_token(session,
628 						      obj->attributes);
629 		if (rc)
630 			goto out;
631 	}
632 
633 	if (processing_is_tee_symm(proc_params->id))
634 		rc = init_symm_operation(session, function, proc_params, obj);
635 	else if (processing_is_tee_digest(proc_params->id))
636 		rc = init_digest_operation(session, proc_params);
637 	else
638 		rc = PKCS11_CKR_MECHANISM_INVALID;
639 
640 	if (rc == PKCS11_CKR_OK) {
641 		session->processing->mecha_type = proc_params->id;
642 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
643 		     session->handle, id2str_proc(proc_params->id),
644 		     id2str_function(function));
645 	}
646 
647 out:
648 	if (rc && session)
649 		release_active_processing(session);
650 
651 	TEE_Free(proc_params);
652 
653 	return rc;
654 }
655 
656 /*
657  * entry_processing_step - Generic entry on active processing
658  *
659  * @client = client reference
660  * @ptype = Invocation parameter types
661  * @params = Invocation parameters reference
662  * @function - encrypt, decrypt, sign, verify, digest, ...
663  * @step - update, oneshot, final
664  */
665 enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
666 				     uint32_t ptypes, TEE_Param *params,
667 				     enum processing_func function,
668 				     enum processing_step step)
669 {
670 	TEE_Param *ctrl = params;
671 	enum pkcs11_rc rc = PKCS11_CKR_OK;
672 	struct serialargs ctrlargs = { };
673 	struct pkcs11_session *session = NULL;
674 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
675 	uint32_t key_handle = 0;
676 	struct pkcs11_object *obj = NULL;
677 
678 	if (!client ||
679 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
680 		return PKCS11_CKR_ARGUMENTS_BAD;
681 
682 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
683 
684 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
685 	if (rc)
686 		return rc;
687 
688 	if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
689 		assert(function == PKCS11_FUNCTION_DIGEST);
690 
691 		rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
692 		if (rc)
693 			return rc;
694 	}
695 
696 	if (serialargs_remaining_bytes(&ctrlargs))
697 		return PKCS11_CKR_ARGUMENTS_BAD;
698 
699 	rc = get_active_session(session, function);
700 	if (rc)
701 		return rc;
702 
703 	if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
704 		assert(function == PKCS11_FUNCTION_DIGEST);
705 
706 		obj = pkcs11_handle2object(key_handle, session);
707 		if (!obj) {
708 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
709 			goto out;
710 		}
711 
712 		rc = check_access_attrs_against_token(session,
713 						      obj->attributes);
714 		if (rc) {
715 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
716 			goto out;
717 		}
718 	}
719 
720 	mecha_type = session->processing->mecha_type;
721 	rc = check_mechanism_against_processing(session, mecha_type,
722 						function, step);
723 	if (rc)
724 		goto out;
725 
726 	if (processing_is_tee_symm(mecha_type))
727 		rc = step_symm_operation(session, function, step,
728 					 ptypes, params);
729 	else if (processing_is_tee_digest(mecha_type))
730 		rc = step_digest_operation(session, step, obj, ptypes, params);
731 	else
732 		rc = PKCS11_CKR_MECHANISM_INVALID;
733 
734 	if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE ||
735 				    step == PKCS11_FUNC_STEP_UPDATE_KEY)) {
736 		session->processing->updated = true;
737 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
738 		     session->handle, id2str_proc(mecha_type),
739 		     id2str_function(function));
740 	}
741 
742 out:
743 	switch (step) {
744 	case PKCS11_FUNC_STEP_UPDATE:
745 	case PKCS11_FUNC_STEP_UPDATE_KEY:
746 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
747 			release_active_processing(session);
748 		break;
749 	default:
750 		/* ONESHOT and FINAL terminates processing on success */
751 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
752 			release_active_processing(session);
753 		break;
754 	}
755 
756 	return rc;
757 }
758 
759 enum pkcs11_rc entry_processing_key(struct pkcs11_client *client,
760 				    uint32_t ptypes, TEE_Param *params,
761 				    enum processing_func function)
762 {
763 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
764 						TEE_PARAM_TYPE_NONE,
765 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
766 						TEE_PARAM_TYPE_NONE);
767 	TEE_Param *ctrl = params;
768 	TEE_Param *out = params + 2;
769 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
770 	struct serialargs ctrlargs = { };
771 	struct pkcs11_session *session = NULL;
772 	struct pkcs11_attribute_head *proc_params = NULL;
773 	struct pkcs11_object_head *template = NULL;
774 	uint32_t parent_handle = 0;
775 	uint32_t obj_handle = 0;
776 	struct pkcs11_object *parent = NULL;
777 	struct obj_attrs *head = NULL;
778 	size_t template_size = 0;
779 	void *out_buf = NULL;
780 	uint32_t out_size = 0;
781 
782 	if (!client || ptypes != exp_pt ||
783 	    out->memref.size != sizeof(obj_handle))
784 		return PKCS11_CKR_ARGUMENTS_BAD;
785 
786 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
787 
788 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
789 	if (rc)
790 		return rc;
791 
792 	rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
793 	if (rc)
794 		return rc;
795 
796 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
797 	if (rc)
798 		goto out_free;
799 
800 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
801 	if (rc)
802 		goto out_free;
803 
804 	if (serialargs_remaining_bytes(&ctrlargs)) {
805 		rc = PKCS11_CKR_ARGUMENTS_BAD;
806 		goto out_free;
807 	}
808 
809 	/* Return error if processing already active */
810 	rc = get_ready_session(session);
811 	if (rc)
812 		goto out_free;
813 
814 	/* Check parent handle */
815 	parent = pkcs11_handle2object(parent_handle, session);
816 	if (!parent) {
817 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
818 		goto out_free;
819 	}
820 
821 	/* Check if mechanism can be used for derivation function */
822 	rc = check_mechanism_against_processing(session, proc_params->id,
823 						function,
824 						PKCS11_FUNC_STEP_INIT);
825 	if (rc)
826 		goto out_free;
827 
828 	/* Set the processing state to active */
829 	rc = set_processing_state(session, function, parent, NULL);
830 	if (rc)
831 		goto out_free;
832 
833 	/*
834 	 * Check if base/parent key has CKA_DERIVE set and its key type is
835 	 * compatible with the mechanism passed
836 	 */
837 	rc = check_parent_attrs_against_processing(proc_params->id, function,
838 						   parent->attributes);
839 	if (rc) {
840 		/*
841 		 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
842 		 * specified with C_Derive/Unwrap() in the specification. So
843 		 * return the next most appropriate error.
844 		 */
845 		if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED)
846 			rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT;
847 		goto out;
848 	}
849 
850 	/* Check access of base/parent key */
851 	rc = check_access_attrs_against_token(session, parent->attributes);
852 	if (rc)
853 		goto out;
854 
855 	template_size = sizeof(*template) + template->attrs_size;
856 	/*
857 	 * Prepare a clean initial state for the requested object attributes
858 	 * using base/parent key attributes. Free temporary template once done.
859 	 */
860 	rc = create_attributes_from_template(&head, template, template_size,
861 					     parent->attributes,
862 					     function,
863 					     proc_params->id,
864 					     PKCS11_CKO_UNDEFINED_ID);
865 	if (rc)
866 		goto out;
867 
868 	TEE_Free(template);
869 	template = NULL;
870 
871 	/* check_created_attrs() is called later once key size is known */
872 
873 	rc = check_created_attrs_against_processing(proc_params->id, head);
874 	if (rc)
875 		goto out;
876 
877 	rc = check_created_attrs_against_token(session, head);
878 	if (rc)
879 		goto out;
880 
881 	if (processing_is_tee_symm(proc_params->id)) {
882 		/*
883 		 * These derivation mechanism require encryption to be
884 		 * performed on the data passed in proc_params by parent
885 		 * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT
886 		 * to init_symm_operation()
887 		 */
888 		rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
889 					 proc_params, parent);
890 		if (rc)
891 			goto out;
892 
893 		session->processing->mecha_type = proc_params->id;
894 
895 		rc = derive_key_by_symm_enc(session, &out_buf, &out_size);
896 		if (rc)
897 			goto out;
898 	} else {
899 		rc = PKCS11_CKR_MECHANISM_INVALID;
900 		goto out;
901 	}
902 
903 	rc = set_key_data(&head, out_buf, out_size);
904 	if (rc)
905 		goto out;
906 
907 	TEE_Free(out_buf);
908 	out_buf = NULL;
909 
910 	TEE_Free(proc_params);
911 	proc_params = NULL;
912 
913 	/*
914 	 * Object is ready, register it and return a handle.
915 	 */
916 	rc = create_object(session, head, &obj_handle);
917 	if (rc)
918 		goto out;
919 
920 	/*
921 	 * Now obj_handle (through the related struct pkcs11_object instance)
922 	 * owns the serialized buffer that holds the object attributes.
923 	 * We reset head to NULL as it is no more the buffer owner and would
924 	 * be freed at function out.
925 	 */
926 	head = NULL;
927 
928 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
929 	out->memref.size = sizeof(obj_handle);
930 
931 	DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32,
932 	     session->handle, obj_handle);
933 
934 out:
935 	release_active_processing(session);
936 out_free:
937 	TEE_Free(proc_params);
938 	TEE_Free(template);
939 	TEE_Free(head);
940 	TEE_Free(out_buf);
941 
942 	return rc;
943 }
944 
945 enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client,
946 					       uint32_t ptypes,
947 					       TEE_Param *params)
948 {
949 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
950 						TEE_PARAM_TYPE_NONE,
951 						TEE_PARAM_TYPE_NONE,
952 						TEE_PARAM_TYPE_NONE);
953 	TEE_Param *ctrl = params;
954 	enum pkcs11_rc rc = PKCS11_CKR_OK;
955 	struct serialargs ctrlargs = { };
956 	struct pkcs11_session *session = NULL;
957 	enum processing_func function = PKCS11_FUNCTION_UNKNOWN;
958 	uint32_t cmd = 0;
959 
960 	if (!client || ptypes != exp_pt)
961 		return PKCS11_CKR_ARGUMENTS_BAD;
962 
963 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
964 
965 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
966 	if (rc)
967 		return rc;
968 
969 	rc = serialargs_get_u32(&ctrlargs, &cmd);
970 
971 	if (serialargs_remaining_bytes(&ctrlargs))
972 		return PKCS11_CKR_ARGUMENTS_BAD;
973 
974 	function = func_for_cmd(cmd);
975 	if (function == PKCS11_FUNCTION_UNKNOWN)
976 		return PKCS11_CKR_ARGUMENTS_BAD;
977 
978 	rc = get_active_session(session, function);
979 	if (rc)
980 		return rc;
981 
982 	release_active_processing(session);
983 
984 	DMSG("PKCS11 session %"PRIu32": release processing", session->handle);
985 
986 	return PKCS11_CKR_OK;
987 }
988