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