xref: /optee_os/ta/pkcs11/src/processing.c (revision 03e07432b68f9d78dbad4b9a8af50705948e7893)
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_hash_op_handle != TEE_HANDLE_NULL) {
108 		TEE_FreeOperation(session->processing->tee_hash_op_handle);
109 		session->processing->tee_hash_op_handle = TEE_HANDLE_NULL;
110 		session->processing->tee_hash_algo = 0;
111 	}
112 
113 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
114 		TEE_FreeOperation(session->processing->tee_op_handle);
115 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
116 	}
117 
118 	TEE_Free(session->processing->extra_ctx);
119 
120 	TEE_Free(session->processing);
121 	session->processing = NULL;
122 }
123 
124 size_t get_object_key_bit_size(struct pkcs11_object *obj)
125 {
126 	void *a_ptr = NULL;
127 	uint32_t a_size = 0;
128 	struct obj_attrs *attrs = obj->attributes;
129 
130 	switch (get_key_type(attrs)) {
131 	case PKCS11_CKK_AES:
132 	case PKCS11_CKK_GENERIC_SECRET:
133 	case PKCS11_CKK_MD5_HMAC:
134 	case PKCS11_CKK_SHA_1_HMAC:
135 	case PKCS11_CKK_SHA224_HMAC:
136 	case PKCS11_CKK_SHA256_HMAC:
137 	case PKCS11_CKK_SHA384_HMAC:
138 	case PKCS11_CKK_SHA512_HMAC:
139 		if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
140 			return 0;
141 
142 		return a_size * 8;
143 	case PKCS11_CKK_RSA:
144 		if (get_attribute_ptr(attrs, PKCS11_CKA_MODULUS, NULL, &a_size))
145 			return 0;
146 
147 		return a_size * 8;
148 	case PKCS11_CKK_EC:
149 	case PKCS11_CKK_EC_EDWARDS:
150 		if (get_attribute_ptr(attrs, PKCS11_CKA_EC_PARAMS,
151 				      &a_ptr, &a_size) || !a_ptr)
152 			return 0;
153 
154 		return ec_params2tee_keysize(a_ptr, a_size);
155 	default:
156 		TEE_Panic(0);
157 		return 0;
158 	}
159 }
160 
161 static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
162 {
163 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
164 	void *data = NULL;
165 	uint32_t data_size = 0;
166 	uint32_t value_len = 0;
167 	void *value = NULL;
168 
169 	if (!*head)
170 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
171 
172 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
173 	if (rc || data_size != sizeof(uint32_t)) {
174 		DMSG("%s", rc ? "No attribute value_len found" :
175 		     "Invalid size for attribute VALUE_LEN");
176 
177 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
178 	}
179 	TEE_MemMove(&value_len, data, data_size);
180 
181 	/* Remove the default empty value attribute if found */
182 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
183 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
184 		return PKCS11_CKR_GENERAL_ERROR;
185 
186 	value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
187 	if (!value)
188 		return PKCS11_CKR_DEVICE_MEMORY;
189 
190 	TEE_GenerateRandom(value, value_len);
191 
192 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
193 
194 	TEE_Free(value);
195 
196 	return rc;
197 }
198 
199 enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
200 				     uint32_t ptypes, TEE_Param *params)
201 {
202 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
203 						TEE_PARAM_TYPE_NONE,
204 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
205 						TEE_PARAM_TYPE_NONE);
206 	TEE_Param *ctrl = params;
207 	TEE_Param *out = params + 2;
208 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
209 	struct serialargs ctrlargs = { };
210 	struct pkcs11_session *session = NULL;
211 	struct pkcs11_attribute_head *proc_params = NULL;
212 	struct obj_attrs *head = NULL;
213 	struct pkcs11_object_head *template = NULL;
214 	size_t template_size = 0;
215 	uint32_t obj_handle = 0;
216 
217 	if (!client || ptypes != exp_pt ||
218 	    out->memref.size != sizeof(obj_handle))
219 		return PKCS11_CKR_ARGUMENTS_BAD;
220 
221 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
222 
223 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
224 	if (rc)
225 		return rc;
226 
227 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
228 	if (rc)
229 		goto out;
230 
231 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
232 	if (rc)
233 		goto out;
234 
235 	if (serialargs_remaining_bytes(&ctrlargs)) {
236 		rc = PKCS11_CKR_ARGUMENTS_BAD;
237 		goto out;
238 	}
239 
240 	rc = get_ready_session(session);
241 	if (rc)
242 		goto out;
243 
244 	template_size = sizeof(*template) + template->attrs_size;
245 
246 	rc = check_mechanism_against_processing(session, proc_params->id,
247 						PKCS11_FUNCTION_GENERATE,
248 						PKCS11_FUNC_STEP_INIT);
249 	if (rc) {
250 		DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
251 		goto out;
252 	}
253 
254 	/*
255 	 * Prepare a clean initial state for the requested object attributes.
256 	 * Free temporary template once done.
257 	 */
258 	rc = create_attributes_from_template(&head, template, template_size,
259 					     NULL, PKCS11_FUNCTION_GENERATE,
260 					     proc_params->id,
261 					     PKCS11_CKO_UNDEFINED_ID);
262 	if (rc)
263 		goto out;
264 
265 	TEE_Free(template);
266 	template = NULL;
267 
268 	rc = check_created_attrs(head, NULL);
269 	if (rc)
270 		goto out;
271 
272 	rc = check_created_attrs_against_processing(proc_params->id, head);
273 	if (rc)
274 		goto out;
275 
276 	rc = check_created_attrs_against_token(session, head);
277 	if (rc)
278 		goto out;
279 
280 	/*
281 	 * Execute target processing and add value as attribute
282 	 * PKCS11_CKA_VALUE. Symm key generation: depends on target
283 	 * processing to be used.
284 	 */
285 	switch (proc_params->id) {
286 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
287 	case PKCS11_CKM_AES_KEY_GEN:
288 		/* Generate random of size specified by attribute VALUE_LEN */
289 		rc = generate_random_key_value(&head);
290 		if (rc)
291 			goto out;
292 		break;
293 
294 	default:
295 		rc = PKCS11_CKR_MECHANISM_INVALID;
296 		goto out;
297 	}
298 
299 	TEE_Free(proc_params);
300 	proc_params = NULL;
301 
302 	/*
303 	 * Object is ready, register it and return a handle.
304 	 */
305 	rc = create_object(session, head, &obj_handle);
306 	if (rc)
307 		goto out;
308 
309 	/*
310 	 * Now obj_handle (through the related struct pkcs11_object instance)
311 	 * owns the serialized buffer that holds the object attributes.
312 	 * We reset head to NULL as it is no more the buffer owner and would
313 	 * be freed at function out.
314 	 */
315 	head = NULL;
316 
317 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
318 	out->memref.size = sizeof(obj_handle);
319 
320 	DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
321 	     session->handle, obj_handle);
322 
323 out:
324 	TEE_Free(proc_params);
325 	TEE_Free(template);
326 	TEE_Free(head);
327 
328 	return rc;
329 }
330 
331 enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj,
332 					    uint32_t attribute,
333 					    void **data, size_t *size)
334 {
335 	TEE_Result res = TEE_ERROR_GENERIC;
336 	void *ptr = NULL;
337 	uint32_t sz = 0;
338 
339 	res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz);
340 	if (res != TEE_ERROR_SHORT_BUFFER)
341 		return PKCS11_CKR_FUNCTION_FAILED;
342 
343 	ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
344 	if (!ptr)
345 		return PKCS11_CKR_DEVICE_MEMORY;
346 
347 	res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz);
348 	if (res) {
349 		TEE_Free(ptr);
350 	} else {
351 		*data = ptr;
352 		*size = sz;
353 	}
354 
355 	return tee2pkcs_error(res);
356 }
357 
358 enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head,
359 				      uint32_t pkcs11_id,
360 				      TEE_ObjectHandle tee_obj,
361 				      uint32_t tee_id)
362 {
363 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
364 	void *a_ptr = NULL;
365 	size_t a_size = 0;
366 
367 	rc = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size);
368 	if (rc)
369 		goto out;
370 
371 	rc = add_attribute(head, pkcs11_id, a_ptr, a_size);
372 
373 	TEE_Free(a_ptr);
374 
375 out:
376 	if (rc)
377 		EMSG("Failed TEE attribute %#"PRIx32" for %#"PRIx32"/%s",
378 		     tee_id, pkcs11_id, id2str_attr(pkcs11_id));
379 	return rc;
380 }
381 
382 enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client,
383 				       uint32_t ptypes, TEE_Param *params)
384 {
385 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
386 						TEE_PARAM_TYPE_NONE,
387 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
388 						TEE_PARAM_TYPE_NONE);
389 	TEE_Param *ctrl = params;
390 	TEE_Param *out = params + 2;
391 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
392 	struct serialargs ctrlargs = { };
393 	struct pkcs11_session *session = NULL;
394 	struct pkcs11_attribute_head *proc_params = NULL;
395 	struct obj_attrs *pub_head = NULL;
396 	struct obj_attrs *priv_head = NULL;
397 	struct pkcs11_object_head *pub_template = NULL;
398 	struct pkcs11_object_head *priv_template = NULL;
399 	struct pkcs11_object *object = NULL;
400 	size_t pub_template_size = 0;
401 	size_t priv_template_size = 0;
402 	uint32_t pubkey_handle = 0;
403 	uint32_t privkey_handle = 0;
404 	uint32_t *hdl_ptr = NULL;
405 	size_t out_ref_size = sizeof(pubkey_handle) + sizeof(privkey_handle);
406 
407 	if (!client || ptypes != exp_pt || out->memref.size != out_ref_size)
408 		return PKCS11_CKR_ARGUMENTS_BAD;
409 
410 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
411 
412 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
413 	if (rc)
414 		return rc;
415 
416 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
417 	if (rc)
418 		goto out;
419 
420 	rc = serialargs_alloc_get_attributes(&ctrlargs, &pub_template);
421 	if (rc)
422 		goto out;
423 
424 	rc = serialargs_alloc_get_attributes(&ctrlargs, &priv_template);
425 	if (rc)
426 		goto out;
427 
428 	if (serialargs_remaining_bytes(&ctrlargs)) {
429 		rc = PKCS11_CKR_ARGUMENTS_BAD;
430 		goto out;
431 	}
432 
433 	rc = get_ready_session(session);
434 	if (rc)
435 		goto out;
436 
437 	rc = check_mechanism_against_processing(session, proc_params->id,
438 						PKCS11_FUNCTION_GENERATE_PAIR,
439 						PKCS11_FUNC_STEP_INIT);
440 	if (rc)
441 		goto out;
442 
443 	pub_template_size = sizeof(*pub_template) + pub_template->attrs_size;
444 
445 	rc = create_attributes_from_template(&pub_head, pub_template,
446 					     pub_template_size, NULL,
447 					     PKCS11_FUNCTION_GENERATE_PAIR,
448 					     proc_params->id,
449 					     PKCS11_CKO_PUBLIC_KEY);
450 	if (rc)
451 		goto out;
452 
453 	TEE_Free(pub_template);
454 	pub_template = NULL;
455 
456 	priv_template_size = sizeof(*priv_template) +
457 			     priv_template->attrs_size;
458 
459 	rc = create_attributes_from_template(&priv_head, priv_template,
460 					     priv_template_size, NULL,
461 					     PKCS11_FUNCTION_GENERATE_PAIR,
462 					     proc_params->id,
463 					     PKCS11_CKO_PRIVATE_KEY);
464 	if (rc)
465 		goto out;
466 
467 	TEE_Free(priv_template);
468 	priv_template = NULL;
469 
470 	/* Generate CKA_ID for keys if not specified by the templates */
471 	rc = add_missing_attribute_id(&pub_head, &priv_head);
472 	if (rc)
473 		goto out;
474 
475 	/* Check created object against processing and token state */
476 	rc = check_created_attrs(pub_head, priv_head);
477 	if (rc)
478 		goto out;
479 
480 	rc = check_created_attrs_against_processing(proc_params->id, pub_head);
481 	if (rc)
482 		goto out;
483 
484 	rc = check_created_attrs_against_processing(proc_params->id,
485 						    priv_head);
486 	if (rc)
487 		goto out;
488 
489 	rc = check_created_attrs_against_token(session, pub_head);
490 	if (rc)
491 		goto out;
492 
493 	rc = check_access_attrs_against_token(session, pub_head);
494 	if (rc)
495 		goto out;
496 
497 	rc = check_created_attrs_against_token(session, priv_head);
498 	if (rc)
499 		goto out;
500 
501 	rc = check_access_attrs_against_token(session, priv_head);
502 	if (rc)
503 		goto out;
504 
505 	/* Generate key pair */
506 	switch (proc_params->id) {
507 	case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
508 		rc = generate_eddsa_keys(proc_params, &pub_head, &priv_head);
509 		break;
510 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
511 		rc = generate_ec_keys(proc_params, &pub_head, &priv_head);
512 		break;
513 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
514 		rc = generate_rsa_keys(proc_params, &pub_head, &priv_head);
515 		break;
516 	default:
517 		rc = PKCS11_CKR_MECHANISM_INVALID;
518 		break;
519 	}
520 	if (rc)
521 		goto out;
522 
523 	TEE_Free(proc_params);
524 	proc_params = NULL;
525 
526 	/*
527 	 * Object is ready, register it and return a handle.
528 	 */
529 	rc = create_object(session, pub_head, &pubkey_handle);
530 	if (rc)
531 		goto out;
532 
533 	/*
534 	 * Now obj_handle (through the related struct pkcs11_object instance)
535 	 * owns the serialized buffer that holds the object attributes.
536 	 * We reset local pub_head to NULL to mark that ownership has been
537 	 * transferred.
538 	 */
539 	pub_head = NULL;
540 
541 	rc = create_object(session, priv_head, &privkey_handle);
542 	if (rc)
543 		goto out;
544 
545 	/* Ownership has been transferred so mark it with NULL */
546 	priv_head = NULL;
547 
548 	hdl_ptr = (uint32_t *)out->memref.buffer;
549 
550 	TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(pubkey_handle));
551 	TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(privkey_handle));
552 
553 	pubkey_handle = 0;
554 	privkey_handle = 0;
555 
556 	DMSG("PKCS11 session %"PRIu32": create key pair %#"PRIx32"/%#"PRIx32,
557 	     session->handle, privkey_handle, pubkey_handle);
558 
559 out:
560 	if (pubkey_handle) {
561 		object = pkcs11_handle2object(pubkey_handle, session);
562 		if (!object)
563 			TEE_Panic(0);
564 		destroy_object(session, object, false);
565 	}
566 	TEE_Free(priv_head);
567 	TEE_Free(pub_head);
568 	TEE_Free(priv_template);
569 	TEE_Free(pub_template);
570 	TEE_Free(proc_params);
571 
572 	return rc;
573 }
574 
575 /*
576  * entry_processing_init - Generic entry for initializing a processing
577  *
578  * @client = client reference
579  * @ptype = Invocation parameter types
580  * @params = Invocation parameters reference
581  * @function - encrypt, decrypt, sign, verify, digest, ...
582  */
583 enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
584 				     uint32_t ptypes, TEE_Param *params,
585 				     enum processing_func function)
586 {
587 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
588 						TEE_PARAM_TYPE_NONE,
589 						TEE_PARAM_TYPE_NONE,
590 						TEE_PARAM_TYPE_NONE);
591 	TEE_Param *ctrl = params;
592 	enum pkcs11_rc rc = PKCS11_CKR_OK;
593 	struct serialargs ctrlargs = { };
594 	struct pkcs11_session *session = NULL;
595 	struct pkcs11_attribute_head *proc_params = NULL;
596 	uint32_t key_handle = 0;
597 	struct pkcs11_object *obj = NULL;
598 
599 	if (!client || ptypes != exp_pt)
600 		return PKCS11_CKR_ARGUMENTS_BAD;
601 
602 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
603 
604 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
605 	if (rc)
606 		return rc;
607 
608 	if (function != PKCS11_FUNCTION_DIGEST) {
609 		rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
610 		if (rc)
611 			return rc;
612 	}
613 
614 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
615 	if (rc)
616 		return rc;
617 
618 	if (serialargs_remaining_bytes(&ctrlargs)) {
619 		rc = PKCS11_CKR_ARGUMENTS_BAD;
620 		goto out_free;
621 	}
622 
623 	rc = get_ready_session(session);
624 	if (rc)
625 		goto out_free;
626 
627 	if (function != PKCS11_FUNCTION_DIGEST) {
628 		obj = pkcs11_handle2object(key_handle, session);
629 		if (!obj) {
630 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
631 			goto out_free;
632 		}
633 	}
634 
635 	rc = set_processing_state(session, function, obj, NULL);
636 	if (rc)
637 		goto out;
638 
639 	rc = check_mechanism_against_processing(session, proc_params->id,
640 						function,
641 						PKCS11_FUNC_STEP_INIT);
642 	if (rc)
643 		goto out;
644 
645 	if (obj) {
646 		rc = check_parent_attrs_against_processing(proc_params->id,
647 							   function,
648 							   obj->attributes);
649 		if (rc)
650 			goto out;
651 
652 		rc = check_access_attrs_against_token(session,
653 						      obj->attributes);
654 		if (rc)
655 			goto out;
656 	}
657 
658 	if (processing_is_tee_symm(proc_params->id))
659 		rc = init_symm_operation(session, function, proc_params, obj);
660 	else if (processing_is_tee_asymm(proc_params->id))
661 		rc = init_asymm_operation(session, function, proc_params, obj);
662 	else if (processing_is_tee_digest(proc_params->id))
663 		rc = init_digest_operation(session, proc_params);
664 	else
665 		rc = PKCS11_CKR_MECHANISM_INVALID;
666 
667 	if (rc == PKCS11_CKR_OK) {
668 		session->processing->mecha_type = proc_params->id;
669 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
670 		     session->handle, id2str_proc(proc_params->id),
671 		     id2str_function(function));
672 	}
673 
674 out:
675 	if (rc)
676 		release_active_processing(session);
677 out_free:
678 	TEE_Free(proc_params);
679 
680 	return rc;
681 }
682 
683 /*
684  * entry_processing_step - Generic entry on active processing
685  *
686  * @client = client reference
687  * @ptype = Invocation parameter types
688  * @params = Invocation parameters reference
689  * @function - encrypt, decrypt, sign, verify, digest, ...
690  * @step - update, oneshot, final
691  */
692 enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
693 				     uint32_t ptypes, TEE_Param *params,
694 				     enum processing_func function,
695 				     enum processing_step step)
696 {
697 	TEE_Param *ctrl = params;
698 	enum pkcs11_rc rc = PKCS11_CKR_OK;
699 	struct serialargs ctrlargs = { };
700 	struct pkcs11_session *session = NULL;
701 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
702 	uint32_t key_handle = 0;
703 	struct pkcs11_object *obj = NULL;
704 
705 	if (!client ||
706 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
707 		return PKCS11_CKR_ARGUMENTS_BAD;
708 
709 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
710 
711 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
712 	if (rc)
713 		return rc;
714 
715 	if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
716 		assert(function == PKCS11_FUNCTION_DIGEST);
717 
718 		rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
719 		if (rc)
720 			return rc;
721 	}
722 
723 	if (serialargs_remaining_bytes(&ctrlargs))
724 		return PKCS11_CKR_ARGUMENTS_BAD;
725 
726 	rc = get_active_session(session, function);
727 	if (rc)
728 		return rc;
729 
730 	if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
731 		assert(function == PKCS11_FUNCTION_DIGEST);
732 
733 		obj = pkcs11_handle2object(key_handle, session);
734 		if (!obj) {
735 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
736 			goto out;
737 		}
738 
739 		rc = check_access_attrs_against_token(session,
740 						      obj->attributes);
741 		if (rc) {
742 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
743 			goto out;
744 		}
745 	}
746 
747 	mecha_type = session->processing->mecha_type;
748 	rc = check_mechanism_against_processing(session, mecha_type,
749 						function, step);
750 	if (rc)
751 		goto out;
752 
753 	if (processing_is_tee_symm(mecha_type))
754 		rc = step_symm_operation(session, function, step,
755 					 ptypes, params);
756 	else if (processing_is_tee_asymm(mecha_type))
757 		rc = step_asymm_operation(session, function, step,
758 					  ptypes, params);
759 	else if (processing_is_tee_digest(mecha_type))
760 		rc = step_digest_operation(session, step, obj, ptypes, params);
761 	else
762 		rc = PKCS11_CKR_MECHANISM_INVALID;
763 
764 	if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE ||
765 				    step == PKCS11_FUNC_STEP_UPDATE_KEY)) {
766 		session->processing->step = PKCS11_FUNC_STEP_UPDATE;
767 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
768 		     session->handle, id2str_proc(mecha_type),
769 		     id2str_function(function));
770 	}
771 
772 	if (rc == PKCS11_CKR_BUFFER_TOO_SMALL &&
773 	    step == PKCS11_FUNC_STEP_ONESHOT)
774 		session->processing->step = PKCS11_FUNC_STEP_ONESHOT;
775 
776 	if (rc == PKCS11_CKR_BUFFER_TOO_SMALL && step == PKCS11_FUNC_STEP_FINAL)
777 		session->processing->step = PKCS11_FUNC_STEP_FINAL;
778 
779 out:
780 	switch (step) {
781 	case PKCS11_FUNC_STEP_UPDATE:
782 	case PKCS11_FUNC_STEP_UPDATE_KEY:
783 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
784 			release_active_processing(session);
785 		break;
786 	default:
787 		/* ONESHOT and FINAL terminates processing on success */
788 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
789 			release_active_processing(session);
790 		break;
791 	}
792 
793 	return rc;
794 }
795 
796 enum pkcs11_rc entry_processing_key(struct pkcs11_client *client,
797 				    uint32_t ptypes, TEE_Param *params,
798 				    enum processing_func function)
799 {
800 	TEE_Param *ctrl = params;
801 	TEE_Param *out = params + 2;
802 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
803 	struct serialargs ctrlargs = { };
804 	struct pkcs11_session *session = NULL;
805 	struct pkcs11_attribute_head *proc_params = NULL;
806 	struct pkcs11_object_head *template = NULL;
807 	uint32_t parent_handle = 0;
808 	uint32_t obj_handle = 0;
809 	struct pkcs11_object *parent = NULL;
810 	struct obj_attrs *head = NULL;
811 	size_t template_size = 0;
812 	void *in_buf = NULL;
813 	uint32_t in_size = 0;
814 	void *out_buf = NULL;
815 	uint32_t out_size = 0;
816 	enum processing_func operation = PKCS11_FUNCTION_UNKNOWN;
817 
818 	if (!client ||
819 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT ||
820 	    TEE_PARAM_TYPE_GET(ptypes, 2) != TEE_PARAM_TYPE_MEMREF_OUTPUT ||
821 	    out->memref.size != sizeof(obj_handle) ||
822 	    TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
823 		return PKCS11_CKR_ARGUMENTS_BAD;
824 
825 	switch (function) {
826 	case PKCS11_FUNCTION_UNWRAP:
827 		if (TEE_PARAM_TYPE_GET(ptypes, 1) !=
828 				TEE_PARAM_TYPE_MEMREF_INPUT)
829 			return PKCS11_CKR_ARGUMENTS_BAD;
830 
831 		in_buf = params[1].memref.buffer;
832 		in_size = params[1].memref.size;
833 		if (in_size && !in_buf)
834 			return PKCS11_CKR_ARGUMENTS_BAD;
835 
836 		/*
837 		 * Some unwrap mechanisms require encryption to be
838 		 * performed on the data passed in proc_params by parent
839 		 * key. Hence set operation as PKCS11_FUNCTION_DECRYPT
840 		 * to be used with init_symm_operation()
841 		 */
842 		operation = PKCS11_FUNCTION_DECRYPT;
843 		break;
844 	case PKCS11_FUNCTION_DERIVE:
845 		if (TEE_PARAM_TYPE_GET(ptypes, 1) != TEE_PARAM_TYPE_NONE)
846 			return PKCS11_CKR_ARGUMENTS_BAD;
847 
848 		/*
849 		 * Some derivation mechanism require encryption to be
850 		 * performed on the data passed in proc_params by parent
851 		 * key. Hence set operation as PKCS11_FUNCTION_ENCRYPT
852 		 * to be used with init_symm_operation()
853 		 */
854 		operation = PKCS11_FUNCTION_ENCRYPT;
855 		break;
856 	default:
857 		return PKCS11_CKR_ARGUMENTS_BAD;
858 	}
859 
860 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
861 
862 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
863 	if (rc)
864 		return rc;
865 
866 	rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
867 	if (rc)
868 		return rc;
869 
870 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
871 	if (rc)
872 		return rc;
873 
874 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
875 	if (rc)
876 		goto out_free;
877 
878 	if (serialargs_remaining_bytes(&ctrlargs)) {
879 		rc = PKCS11_CKR_ARGUMENTS_BAD;
880 		goto out_free;
881 	}
882 
883 	/* Return error if processing already active */
884 	rc = get_ready_session(session);
885 	if (rc)
886 		goto out_free;
887 
888 	/* Check parent handle */
889 	parent = pkcs11_handle2object(parent_handle, session);
890 	if (!parent) {
891 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
892 		goto out_free;
893 	}
894 
895 	/* Check if mechanism can be used for derivation function */
896 	rc = check_mechanism_against_processing(session, proc_params->id,
897 						function,
898 						PKCS11_FUNC_STEP_INIT);
899 	if (rc)
900 		goto out_free;
901 
902 	/* Set the processing state to active */
903 	rc = set_processing_state(session, function, parent, NULL);
904 	if (rc)
905 		goto out_free;
906 
907 	/*
908 	 * Check if base/parent key has CKA_DERIVE set and its key type is
909 	 * compatible with the mechanism passed
910 	 */
911 	rc = check_parent_attrs_against_processing(proc_params->id, function,
912 						   parent->attributes);
913 	if (rc) {
914 		/*
915 		 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
916 		 * specified with C_Derive/Unwrap() in the specification. So
917 		 * return the next most appropriate error.
918 		 */
919 		if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) {
920 			if (function == PKCS11_FUNCTION_UNWRAP)
921 				rc =
922 				  PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
923 			else
924 				rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT;
925 		}
926 		goto out;
927 	}
928 
929 	/* Check access of base/parent key */
930 	rc = check_access_attrs_against_token(session, parent->attributes);
931 	if (rc)
932 		goto out;
933 
934 	template_size = sizeof(*template) + template->attrs_size;
935 	/*
936 	 * Prepare a clean initial state for the requested object attributes
937 	 * using base/parent key attributes. Free temporary template once done.
938 	 */
939 	rc = create_attributes_from_template(&head, template, template_size,
940 					     parent->attributes,
941 					     function,
942 					     proc_params->id,
943 					     PKCS11_CKO_UNDEFINED_ID);
944 	if (rc)
945 		goto out;
946 
947 	TEE_Free(template);
948 	template = NULL;
949 
950 	/* check_created_attrs() is called later once key size is known */
951 
952 	rc = check_created_attrs_against_processing(proc_params->id, head);
953 	if (rc)
954 		goto out;
955 
956 	rc = check_created_attrs_against_token(session, head);
957 	if (rc)
958 		goto out;
959 
960 	rc = check_access_attrs_against_token(session, head);
961 	if (rc)
962 		goto out;
963 
964 	if (processing_is_tee_symm(proc_params->id)) {
965 		rc = init_symm_operation(session, operation, proc_params,
966 					 parent);
967 		if (rc)
968 			goto out;
969 
970 		session->processing->mecha_type = proc_params->id;
971 
972 		switch (function) {
973 		case PKCS11_FUNCTION_DERIVE:
974 			rc = derive_key_by_symm_enc(session, &out_buf,
975 						    &out_size);
976 			break;
977 		case PKCS11_FUNCTION_UNWRAP:
978 			rc = unwrap_key_by_symm(session, in_buf, in_size,
979 						&out_buf, &out_size);
980 			break;
981 		default:
982 			TEE_Panic(function);
983 		}
984 		if (rc)
985 			goto out;
986 
987 	} else if (processing_is_tee_asymm(proc_params->id)) {
988 		assert(function == PKCS11_FUNCTION_DERIVE);
989 
990 		rc = init_asymm_operation(session, function, proc_params,
991 					  parent);
992 		if (rc)
993 			goto out;
994 
995 		rc = do_asymm_derivation(session, proc_params, &head);
996 		if (rc)
997 			goto out;
998 
999 		goto done;
1000 	} else {
1001 		rc = PKCS11_CKR_MECHANISM_INVALID;
1002 		goto out;
1003 	}
1004 
1005 	rc = set_key_data(&head, out_buf, out_size);
1006 	if (rc)
1007 		goto out;
1008 
1009 done:
1010 	TEE_Free(out_buf);
1011 	out_buf = NULL;
1012 
1013 	TEE_Free(proc_params);
1014 	proc_params = NULL;
1015 
1016 	/*
1017 	 * Object is ready, register it and return a handle.
1018 	 */
1019 	rc = create_object(session, head, &obj_handle);
1020 	if (rc)
1021 		goto out;
1022 
1023 	/*
1024 	 * Now obj_handle (through the related struct pkcs11_object instance)
1025 	 * owns the serialized buffer that holds the object attributes.
1026 	 * We reset head to NULL as it is no more the buffer owner and would
1027 	 * be freed at function out.
1028 	 */
1029 	head = NULL;
1030 
1031 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
1032 	out->memref.size = sizeof(obj_handle);
1033 
1034 	DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32,
1035 	     session->handle, obj_handle);
1036 
1037 out:
1038 	release_active_processing(session);
1039 out_free:
1040 	TEE_Free(proc_params);
1041 	TEE_Free(template);
1042 	TEE_Free(head);
1043 	TEE_Free(out_buf);
1044 
1045 	return rc;
1046 }
1047 
1048 enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client,
1049 					       uint32_t ptypes,
1050 					       TEE_Param *params)
1051 {
1052 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1053 						TEE_PARAM_TYPE_NONE,
1054 						TEE_PARAM_TYPE_NONE,
1055 						TEE_PARAM_TYPE_NONE);
1056 	TEE_Param *ctrl = params;
1057 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1058 	struct serialargs ctrlargs = { };
1059 	struct pkcs11_session *session = NULL;
1060 	enum processing_func function = PKCS11_FUNCTION_UNKNOWN;
1061 	uint32_t cmd = 0;
1062 
1063 	if (!client || ptypes != exp_pt)
1064 		return PKCS11_CKR_ARGUMENTS_BAD;
1065 
1066 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1067 
1068 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1069 	if (rc)
1070 		return rc;
1071 
1072 	rc = serialargs_get_u32(&ctrlargs, &cmd);
1073 
1074 	if (serialargs_remaining_bytes(&ctrlargs))
1075 		return PKCS11_CKR_ARGUMENTS_BAD;
1076 
1077 	function = func_for_cmd(cmd);
1078 	if (function == PKCS11_FUNCTION_UNKNOWN)
1079 		return PKCS11_CKR_ARGUMENTS_BAD;
1080 
1081 	rc = get_active_session(session, function);
1082 	if (rc)
1083 		return rc;
1084 
1085 	release_active_processing(session);
1086 
1087 	DMSG("PKCS11 session %"PRIu32": release processing", session->handle);
1088 
1089 	return PKCS11_CKR_OK;
1090 }
1091 
1092 enum pkcs11_rc entry_wrap_key(struct pkcs11_client *client,
1093 			      uint32_t ptypes, TEE_Param *params)
1094 {
1095 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1096 						TEE_PARAM_TYPE_NONE,
1097 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
1098 						TEE_PARAM_TYPE_NONE);
1099 	TEE_Param *ctrl = params;
1100 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1101 	struct serialargs ctrlargs = { };
1102 	struct pkcs11_session *session = NULL;
1103 	struct pkcs11_attribute_head *proc_params = NULL;
1104 	struct pkcs11_object *wrapping_key = NULL;
1105 	struct pkcs11_object *key = NULL;
1106 	void *req_attrs = NULL;
1107 	uint32_t wrapping_key_handle = 0;
1108 	uint32_t key_handle = 0;
1109 	uint32_t size = 0;
1110 	void *key_data = NULL;
1111 	uint32_t key_sz = 0;
1112 	void *out_buf = params[2].memref.buffer;
1113 	uint32_t out_size = params[2].memref.size;
1114 	const enum processing_func function = PKCS11_FUNCTION_WRAP;
1115 
1116 	if (!client || ptypes != exp_pt ||
1117 	    (out_size && !out_buf))
1118 		return PKCS11_CKR_ARGUMENTS_BAD;
1119 
1120 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1121 
1122 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1123 	if (rc)
1124 		return rc;
1125 
1126 	rc = serialargs_get(&ctrlargs, &wrapping_key_handle, sizeof(uint32_t));
1127 	if (rc)
1128 		return rc;
1129 
1130 	rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
1131 	if (rc)
1132 		return rc;
1133 
1134 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
1135 	if (rc)
1136 		return rc;
1137 
1138 	if (serialargs_remaining_bytes(&ctrlargs)) {
1139 		rc = PKCS11_CKR_ARGUMENTS_BAD;
1140 		goto out_free;
1141 	}
1142 
1143 	rc = get_ready_session(session);
1144 	if (rc)
1145 		goto out_free;
1146 
1147 	wrapping_key = pkcs11_handle2object(wrapping_key_handle, session);
1148 	if (!wrapping_key) {
1149 		rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID;
1150 		goto out_free;
1151 	}
1152 
1153 	key = pkcs11_handle2object(key_handle, session);
1154 	if (!key) {
1155 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
1156 		goto out_free;
1157 	}
1158 
1159 	/*
1160 	 * The wrapping key and key to be wrapped shouldn't be same.
1161 	 * PKCS#11 spec doesn't explicitly state that but logically this isn't
1162 	 * a use case and also acts as an attack vector, so explicitly
1163 	 * disallow this.
1164 	 */
1165 	if (key == wrapping_key) {
1166 		rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID;
1167 		goto out_free;
1168 	}
1169 
1170 	rc = set_processing_state(session, function, wrapping_key, NULL);
1171 	if (rc)
1172 		goto out_free;
1173 
1174 	/* Check if mechanism can be used for wrapping function */
1175 	rc = check_mechanism_against_processing(session, proc_params->id,
1176 						function,
1177 						PKCS11_FUNC_STEP_INIT);
1178 	if (rc)
1179 		goto out;
1180 
1181 	/*
1182 	 * Check if wrapping key has CKA_WRAP set and its key type is
1183 	 * compatible with the mechanism passed
1184 	 */
1185 	rc = check_parent_attrs_against_processing(proc_params->id, function,
1186 						   wrapping_key->attributes);
1187 	if (rc) {
1188 		/*
1189 		 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
1190 		 * specified with C_Wrap() in the specification. So
1191 		 * return the next most appropriate error.
1192 		 */
1193 		if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED)
1194 			rc = PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
1195 
1196 		goto out;
1197 	}
1198 
1199 	/* Check access of wrapping key */
1200 	rc = check_access_attrs_against_token(session,
1201 					      wrapping_key->attributes);
1202 	if (rc)
1203 		goto out;
1204 
1205 	switch (get_class(key->attributes)) {
1206 	case PKCS11_CKO_SECRET_KEY:
1207 		break;
1208 	/* Key type not supported as yet */
1209 	case PKCS11_CKO_PRIVATE_KEY:
1210 	default:
1211 		rc = PKCS11_CKR_KEY_NOT_WRAPPABLE;
1212 		goto out;
1213 	}
1214 
1215 	/* Check if key to be wrapped is extractable */
1216 	if (!get_bool(key->attributes, PKCS11_CKA_EXTRACTABLE)) {
1217 		DMSG("Extractable property is false");
1218 		rc = PKCS11_CKR_KEY_UNEXTRACTABLE;
1219 		goto out;
1220 	}
1221 
1222 	if (get_bool(key->attributes, PKCS11_CKA_WRAP_WITH_TRUSTED) &&
1223 	    !get_bool(wrapping_key->attributes, PKCS11_CKA_TRUSTED)) {
1224 		DMSG("Wrap with trusted not satisfied");
1225 		rc = PKCS11_CKR_KEY_NOT_WRAPPABLE;
1226 		goto out;
1227 	}
1228 
1229 	rc = check_access_attrs_against_token(session, key->attributes);
1230 	if (rc)
1231 		goto out;
1232 
1233 	rc = get_attribute_ptr(wrapping_key->attributes,
1234 			       PKCS11_CKA_WRAP_TEMPLATE, &req_attrs, &size);
1235 	if (rc == PKCS11_CKR_OK && size != 0) {
1236 		if (!attributes_match_reference(key->attributes, req_attrs)) {
1237 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
1238 			goto out;
1239 		}
1240 	}
1241 
1242 	rc = get_key_data_to_wrap(key->attributes, &key_data, &key_sz);
1243 	if (rc)
1244 		goto out;
1245 
1246 	if (processing_is_tee_symm(proc_params->id)) {
1247 		rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
1248 					 proc_params, wrapping_key);
1249 		if (rc)
1250 			goto out;
1251 
1252 		session->processing->mecha_type = proc_params->id;
1253 
1254 		rc = wrap_data_by_symm_enc(session, key_data, key_sz, out_buf,
1255 					   &out_size);
1256 	} else {
1257 		rc = PKCS11_CKR_MECHANISM_INVALID;
1258 	}
1259 
1260 	if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)
1261 		params[2].memref.size = out_size;
1262 
1263 out:
1264 	release_active_processing(session);
1265 out_free:
1266 	TEE_Free(proc_params);
1267 	return rc;
1268 }
1269