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