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