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