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