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