1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017-2020, Linaro Limited
4  */
5 
6 #include <assert.h>
7 #include <inttypes.h>
8 #include <string_ext.h>
9 #include <tee_internal_api.h>
10 #include <tee_internal_api_extensions.h>
11 
12 #include "attributes.h"
13 #include "handle.h"
14 #include "object.h"
15 #include "pkcs11_attributes.h"
16 #include "pkcs11_helpers.h"
17 #include "pkcs11_token.h"
18 #include "sanitize_object.h"
19 #include "serializer.h"
20 
21 /*
22  * Temporary list used to register allocated struct pkcs11_object instances
23  * so that destroy_object() can unconditionally remove the object from its
24  * list, being from an object destruction request or because object creation
25  * failed before being completed. Objects are moved to their target list at
26  * creation completion.
27  */
28 LIST_HEAD(temp_obj_list, pkcs11_object) temporary_object_list =
29 	LIST_HEAD_INITIALIZER(temp_obj_list);
30 
31 static struct ck_token *get_session_token(void *session);
32 
pkcs11_handle2object(uint32_t handle,struct pkcs11_session * session)33 struct pkcs11_object *pkcs11_handle2object(uint32_t handle,
34 					   struct pkcs11_session *session)
35 {
36 	struct pkcs11_object *object = NULL;
37 
38 	object = handle_lookup(get_object_handle_db(session), handle);
39 	if (!object)
40 		return NULL;
41 
42 	/*
43 	 * If object is session only then no extra checks are needed as session
44 	 * objects has flat access control space
45 	 */
46 	if (!object->token)
47 		return object;
48 
49 	/*
50 	 * Only allow access to token object if session is associated with
51 	 * the token
52 	 */
53 	if (object->token != get_session_token(session))
54 		return NULL;
55 
56 	return object;
57 }
58 
pkcs11_object2handle(struct pkcs11_object * obj,struct pkcs11_session * session)59 uint32_t pkcs11_object2handle(struct pkcs11_object *obj,
60 			      struct pkcs11_session *session)
61 {
62 	return handle_lookup_handle(get_object_handle_db(session), obj);
63 }
64 
65 /* Currently handle pkcs11 sessions and tokens */
66 
get_session_objects(void * session)67 static struct object_list *get_session_objects(void *session)
68 {
69 	/* Currently supporting only pkcs11 session */
70 	struct pkcs11_session *ck_session = session;
71 
72 	return pkcs11_get_session_objects(ck_session);
73 }
74 
get_session_token(void * session)75 static struct ck_token *get_session_token(void *session)
76 {
77 	struct pkcs11_session *ck_session = session;
78 
79 	return pkcs11_session2token(ck_session);
80 }
81 
82 /* Release resources of a non-persistent object */
cleanup_volatile_obj_ref(struct pkcs11_object * obj)83 static void cleanup_volatile_obj_ref(struct pkcs11_object *obj)
84 {
85 	if (!obj)
86 		return;
87 
88 	LIST_REMOVE(obj, link);
89 
90 	if (obj->key_handle != TEE_HANDLE_NULL)
91 		TEE_FreeTransientObject(obj->key_handle);
92 
93 	if (obj->attribs_hdl != TEE_HANDLE_NULL)
94 		TEE_CloseObject(obj->attribs_hdl);
95 
96 	TEE_Free(obj->attributes);
97 	TEE_Free(obj->uuid);
98 	TEE_Free(obj);
99 }
100 
101 /* Release resources of a persistent object including volatile resources */
cleanup_persistent_object(struct pkcs11_object * obj,struct ck_token * token)102 void cleanup_persistent_object(struct pkcs11_object *obj,
103 			       struct ck_token *token)
104 {
105 	TEE_Result res = TEE_SUCCESS;
106 
107 	if (!obj)
108 		return;
109 
110 	/* Open handle with write properties to destroy the object */
111 	if (obj->attribs_hdl != TEE_HANDLE_NULL)
112 		TEE_CloseObject(obj->attribs_hdl);
113 
114 	res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
115 				       obj->uuid, sizeof(TEE_UUID),
116 				       TEE_DATA_FLAG_ACCESS_WRITE_META,
117 				       &obj->attribs_hdl);
118 	if (!res)
119 		TEE_CloseAndDeletePersistentObject1(obj->attribs_hdl);
120 
121 	obj->attribs_hdl = TEE_HANDLE_NULL;
122 	destroy_object_uuid(token, obj);
123 
124 	cleanup_volatile_obj_ref(obj);
125 }
126 
127 /*
128  * destroy_object - destroy an PKCS11 TA object
129  *
130  * @session - session requesting object destruction
131  * @obj - reference to the PKCS11 TA object
132  * @session_only - true if only session object shall be destroyed
133  */
destroy_object(struct pkcs11_session * session,struct pkcs11_object * obj,bool session_only)134 void destroy_object(struct pkcs11_session *session, struct pkcs11_object *obj,
135 		    bool session_only)
136 {
137 #ifdef DEBUG
138 	trace_attributes("[destroy]", obj->attributes);
139 	if (obj->uuid)
140 		MSG_RAW("[destroy] obj uuid %pUl", (void *)obj->uuid);
141 #endif
142 
143 	if (session_only) {
144 		/* Destroy object due to session closure */
145 		handle_put(get_object_handle_db(session),
146 			   pkcs11_object2handle(obj, session));
147 		cleanup_volatile_obj_ref(obj);
148 
149 		return;
150 	}
151 
152 	/* Destroy target object (persistent or not) */
153 	if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
154 		assert(obj->uuid);
155 		/* Try twice otherwise panic! */
156 		if (unregister_persistent_object(session->token, obj->uuid) &&
157 		    unregister_persistent_object(session->token, obj->uuid))
158 			TEE_Panic(0);
159 
160 		handle_put(get_object_handle_db(session),
161 			   pkcs11_object2handle(obj, session));
162 		cleanup_persistent_object(obj, session->token);
163 	} else {
164 		handle_put(get_object_handle_db(session),
165 			   pkcs11_object2handle(obj, session));
166 		cleanup_volatile_obj_ref(obj);
167 	}
168 }
169 
create_obj_instance(struct obj_attrs * head,struct ck_token * token)170 static struct pkcs11_object *create_obj_instance(struct obj_attrs *head,
171 						 struct ck_token *token)
172 {
173 	struct pkcs11_object *obj = NULL;
174 
175 	obj = TEE_Malloc(sizeof(struct pkcs11_object), TEE_MALLOC_FILL_ZERO);
176 	if (!obj)
177 		return NULL;
178 
179 	obj->key_handle = TEE_HANDLE_NULL;
180 	obj->attribs_hdl = TEE_HANDLE_NULL;
181 	obj->attributes = head;
182 	obj->token = token;
183 
184 	return obj;
185 }
186 
create_token_object(struct obj_attrs * head,TEE_UUID * uuid,struct ck_token * token)187 struct pkcs11_object *create_token_object(struct obj_attrs *head,
188 					  TEE_UUID *uuid,
189 					  struct ck_token *token)
190 {
191 	struct pkcs11_object *obj = create_obj_instance(head, token);
192 
193 	if (obj)
194 		obj->uuid = uuid;
195 
196 	return obj;
197 }
198 
199 /*
200  * create_object - create an PKCS11 TA object from its attributes and value
201  *
202  * @sess - session requesting object creation
203  * @head - reference to serialized attributes
204  * @out_handle - generated handle for the created object
205  */
create_object(void * sess,struct obj_attrs * head,uint32_t * out_handle)206 enum pkcs11_rc create_object(void *sess, struct obj_attrs *head,
207 			     uint32_t *out_handle)
208 {
209 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
210 	struct pkcs11_object *obj = NULL;
211 	struct pkcs11_session *session = (struct pkcs11_session *)sess;
212 	uint32_t obj_handle = 0;
213 
214 #ifdef DEBUG
215 	trace_attributes("[create]", head);
216 #endif
217 
218 	/*
219 	 * We do not check the key attributes. At this point, key attributes
220 	 * are expected consistent and reliable.
221 	 */
222 
223 	obj = create_obj_instance(head, NULL);
224 	if (!obj)
225 		return PKCS11_CKR_DEVICE_MEMORY;
226 
227 	LIST_INSERT_HEAD(&temporary_object_list, obj, link);
228 
229 	/* Create a handle for the object in the session database */
230 	obj_handle = handle_get(get_object_handle_db(session), obj);
231 	if (!obj_handle) {
232 		rc = PKCS11_CKR_DEVICE_MEMORY;
233 		goto err;
234 	}
235 
236 	if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
237 		TEE_Result res = TEE_SUCCESS;
238 
239 		/*
240 		 * Get an ID for the persistent object
241 		 * Create the file
242 		 * Register the object in the persistent database
243 		 * (move the full sequence to persisent_db.c?)
244 		 */
245 		size_t size = sizeof(struct obj_attrs) +
246 			      obj->attributes->attrs_size;
247 		uint32_t tee_obj_flags = TEE_DATA_FLAG_ACCESS_READ |
248 					 TEE_DATA_FLAG_ACCESS_WRITE |
249 					 TEE_DATA_FLAG_ACCESS_WRITE_META;
250 
251 		rc = create_object_uuid(get_session_token(session), obj);
252 		if (rc)
253 			goto err;
254 
255 		res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
256 						 obj->uuid, sizeof(TEE_UUID),
257 						 tee_obj_flags,
258 						 TEE_HANDLE_NULL,
259 						 obj->attributes, size,
260 						 &obj->attribs_hdl);
261 		if (res) {
262 			rc = tee2pkcs_error(res);
263 			goto err;
264 		}
265 
266 		rc = register_persistent_object(get_session_token(session),
267 						obj->uuid);
268 		if (rc)
269 			goto err;
270 
271 		TEE_CloseObject(obj->attribs_hdl);
272 		obj->attribs_hdl = TEE_HANDLE_NULL;
273 
274 		/* Move object from temporary list to target token list */
275 		LIST_REMOVE(obj, link);
276 		LIST_INSERT_HEAD(&session->token->object_list, obj, link);
277 	} else {
278 		/* Move object from temporary list to target session list */
279 		LIST_REMOVE(obj, link);
280 		LIST_INSERT_HEAD(get_session_objects(session), obj, link);
281 	}
282 
283 	*out_handle = obj_handle;
284 
285 	return PKCS11_CKR_OK;
286 err:
287 	/* make sure that supplied "head" isn't freed */
288 	obj->attributes = NULL;
289 	handle_put(get_object_handle_db(session), obj_handle);
290 	if (get_bool(head, PKCS11_CKA_TOKEN))
291 		cleanup_persistent_object(obj, session->token);
292 	else
293 		cleanup_volatile_obj_ref(obj);
294 
295 	return rc;
296 }
297 
entry_create_object(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)298 enum pkcs11_rc entry_create_object(struct pkcs11_client *client,
299 				   uint32_t ptypes, TEE_Param *params)
300 {
301 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
302 						TEE_PARAM_TYPE_NONE,
303 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
304 						TEE_PARAM_TYPE_NONE);
305 	enum pkcs11_rc rc = PKCS11_CKR_OK;
306 	TEE_Param *ctrl = params;
307 	TEE_Param *out = params + 2;
308 	struct serialargs ctrlargs = { };
309 	struct pkcs11_session *session = NULL;
310 	struct obj_attrs *head = NULL;
311 	struct pkcs11_object_head *template = NULL;
312 	size_t template_size = 0;
313 	uint32_t obj_handle = 0;
314 
315 	/*
316 	 * Collect the arguments of the request
317 	 */
318 
319 	if (!client || ptypes != exp_pt ||
320 	    out->memref.size != sizeof(obj_handle))
321 		return PKCS11_CKR_ARGUMENTS_BAD;
322 
323 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
324 
325 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
326 	if (rc)
327 		return rc;
328 
329 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
330 	if (rc)
331 		return rc;
332 
333 	if (serialargs_remaining_bytes(&ctrlargs)) {
334 		rc = PKCS11_CKR_ARGUMENTS_BAD;
335 		goto out;
336 	}
337 
338 	template_size = sizeof(*template) + template->attrs_size;
339 
340 	/*
341 	 * Prepare a clean initial state for the requested object attributes.
342 	 * Free temporary template once done.
343 	 */
344 	rc = create_attributes_from_template(&head, template, template_size,
345 					     NULL, PKCS11_FUNCTION_IMPORT,
346 					     PKCS11_PROCESSING_IMPORT,
347 					     PKCS11_CKO_UNDEFINED_ID);
348 	TEE_Free(template);
349 	template = NULL;
350 	if (rc)
351 		goto out;
352 
353 	/*
354 	 * Check target object attributes match target processing
355 	 * Check target object attributes match token state
356 	 */
357 	rc = check_created_attrs_against_processing(PKCS11_PROCESSING_IMPORT,
358 						    head);
359 	if (rc)
360 		goto out;
361 
362 	rc = check_created_attrs_against_token(session, head);
363 	if (rc)
364 		goto out;
365 
366 	rc = check_access_attrs_against_token(session, head);
367 	if (rc)
368 		goto out;
369 
370 	/*
371 	 * At this stage the object is almost created: all its attributes are
372 	 * referenced in @head, including the key value and are assumed
373 	 * reliable. Now need to register it and get a handle for it.
374 	 */
375 	rc = create_object(session, head, &obj_handle);
376 	if (rc)
377 		goto out;
378 
379 	/*
380 	 * Now obj_handle (through the related struct pkcs11_object
381 	 * instance) owns the serialized buffer that holds the object
382 	 * attributes. We clear reference in head to NULL as the serializer
383 	 * object is now referred from obj_handle. This allows smooth pass
384 	 * through free at function exit.
385 	 */
386 	head = NULL;
387 
388 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
389 	out->memref.size = sizeof(obj_handle);
390 
391 	DMSG("PKCS11 session %"PRIu32": import object %#"PRIx32,
392 	     session->handle, obj_handle);
393 
394 out:
395 	TEE_Free(template);
396 	TEE_Free(head);
397 
398 	return rc;
399 }
400 
entry_destroy_object(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)401 enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client,
402 				    uint32_t ptypes, TEE_Param *params)
403 {
404 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
405 						TEE_PARAM_TYPE_NONE,
406 						TEE_PARAM_TYPE_NONE,
407 						TEE_PARAM_TYPE_NONE);
408 	enum pkcs11_rc rc = PKCS11_CKR_OK;
409 	TEE_Param *ctrl = params;
410 	struct serialargs ctrlargs = { };
411 	uint32_t object_handle = 0;
412 	struct pkcs11_session *session = NULL;
413 	struct pkcs11_object *object = NULL;
414 
415 	if (!client || ptypes != exp_pt)
416 		return PKCS11_CKR_ARGUMENTS_BAD;
417 
418 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
419 
420 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
421 	if (rc)
422 		return rc;
423 
424 	rc = serialargs_get_u32(&ctrlargs, &object_handle);
425 	if (rc)
426 		return rc;
427 
428 	if (serialargs_remaining_bytes(&ctrlargs))
429 		return PKCS11_CKR_ARGUMENTS_BAD;
430 
431 	object = pkcs11_handle2object(object_handle, session);
432 	if (!object)
433 		return PKCS11_CKR_OBJECT_HANDLE_INVALID;
434 
435 	/* Only session objects can be destroyed during a read-only session */
436 	if (get_bool(object->attributes, PKCS11_CKA_TOKEN) &&
437 	    !pkcs11_session_is_read_write(session)) {
438 		DMSG("Can't destroy persistent object");
439 		return PKCS11_CKR_SESSION_READ_ONLY;
440 	}
441 
442 	/*
443 	 * Only public objects can be destroyed unless normal user is logged in
444 	 */
445 	rc = check_access_attrs_against_token(session, object->attributes);
446 	if (rc)
447 		return PKCS11_CKR_USER_NOT_LOGGED_IN;
448 
449 	/* Objects with PKCS11_CKA_DESTROYABLE as false aren't destroyable */
450 	if (!get_bool(object->attributes, PKCS11_CKA_DESTROYABLE))
451 		return PKCS11_CKR_ACTION_PROHIBITED;
452 
453 	destroy_object(session, object, false);
454 
455 	DMSG("PKCS11 session %"PRIu32": destroy object %#"PRIx32,
456 	     session->handle, object_handle);
457 
458 	return rc;
459 }
460 
release_find_obj_context(struct pkcs11_find_objects * find_ctx)461 static void release_find_obj_context(struct pkcs11_find_objects *find_ctx)
462 {
463 	if (!find_ctx)
464 		return;
465 
466 	TEE_Free(find_ctx->attributes);
467 	TEE_Free(find_ctx->handles);
468 	TEE_Free(find_ctx);
469 }
470 
find_ctx_add(struct pkcs11_find_objects * find_ctx,uint32_t handle)471 static enum pkcs11_rc find_ctx_add(struct pkcs11_find_objects *find_ctx,
472 				   uint32_t handle)
473 {
474 	uint32_t *hdls = TEE_Realloc(find_ctx->handles,
475 				     (find_ctx->count + 1) * sizeof(*hdls));
476 
477 	if (!hdls)
478 		return PKCS11_CKR_DEVICE_MEMORY;
479 
480 	find_ctx->handles = hdls;
481 
482 	*(find_ctx->handles + find_ctx->count) = handle;
483 	find_ctx->count++;
484 
485 	return PKCS11_CKR_OK;
486 }
487 
entry_find_objects_init(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)488 enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client,
489 				       uint32_t ptypes, TEE_Param *params)
490 {
491 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
492 						TEE_PARAM_TYPE_NONE,
493 						TEE_PARAM_TYPE_NONE,
494 						TEE_PARAM_TYPE_NONE);
495 	TEE_Param *ctrl = params;
496 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
497 	struct serialargs ctrlargs = { };
498 	struct pkcs11_session *session = NULL;
499 	struct pkcs11_session *sess = NULL;
500 	struct pkcs11_object_head *template = NULL;
501 	struct obj_attrs *req_attrs = NULL;
502 	struct pkcs11_object *obj = NULL;
503 	struct pkcs11_find_objects *find_ctx = NULL;
504 	struct handle_db *object_db = NULL;
505 
506 	if (!client || ptypes != exp_pt)
507 		return PKCS11_CKR_ARGUMENTS_BAD;
508 
509 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
510 
511 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
512 	if (rc)
513 		return rc;
514 
515 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
516 	if (rc)
517 		return rc;
518 
519 	if (serialargs_remaining_bytes(&ctrlargs)) {
520 		rc = PKCS11_CKR_ARGUMENTS_BAD;
521 		goto out;
522 	}
523 
524 	/* Search objects only if no operation is on-going */
525 	if (session_is_active(session)) {
526 		rc = PKCS11_CKR_OPERATION_ACTIVE;
527 		goto out;
528 	}
529 
530 	if (session->find_ctx) {
531 		EMSG("Active object search already in progress");
532 		rc = PKCS11_CKR_FUNCTION_FAILED;
533 		goto out;
534 	}
535 
536 	rc = sanitize_client_object(&req_attrs, template,
537 				    sizeof(*template) + template->attrs_size,
538 				    PKCS11_UNDEFINED_ID, PKCS11_UNDEFINED_ID);
539 	if (rc)
540 		goto out;
541 
542 	/* Must zero init the structure */
543 	find_ctx = TEE_Malloc(sizeof(*find_ctx), TEE_MALLOC_FILL_ZERO);
544 	if (!find_ctx) {
545 		rc = PKCS11_CKR_DEVICE_MEMORY;
546 		goto out;
547 	}
548 
549 	TEE_Free(template);
550 	template = NULL;
551 
552 	switch (get_class(req_attrs)) {
553 	case PKCS11_CKO_UNDEFINED_ID:
554 	/* Unspecified class searches among data objects */
555 	case PKCS11_CKO_SECRET_KEY:
556 	case PKCS11_CKO_PUBLIC_KEY:
557 	case PKCS11_CKO_PRIVATE_KEY:
558 	case PKCS11_CKO_DATA:
559 	case PKCS11_CKO_CERTIFICATE:
560 		break;
561 	default:
562 		EMSG("Find object of class %s (%"PRIu32") is not supported",
563 		     id2str_class(get_class(req_attrs)),
564 		     get_class(req_attrs));
565 		rc = PKCS11_CKR_ARGUMENTS_BAD;
566 		goto out;
567 	}
568 
569 	/*
570 	 * Scan all objects (sessions and persistent ones) and set a list of
571 	 * candidates that match caller attributes.
572 	 */
573 
574 	/* Scan all session objects first */
575 	TAILQ_FOREACH(sess, get_session_list(session), link) {
576 		LIST_FOREACH(obj, &sess->object_list, link) {
577 			/*
578 			 * Skip all token objects as they could be from
579 			 * different token which the session does not have
580 			 * access
581 			 */
582 			if (obj->token)
583 				continue;
584 
585 			if (!attributes_match_reference(obj->attributes,
586 							req_attrs))
587 				continue;
588 
589 			rc = find_ctx_add(find_ctx,
590 					  pkcs11_object2handle(obj, session));
591 			if (rc)
592 				goto out;
593 		}
594 	}
595 
596 	object_db = get_object_handle_db(session);
597 
598 	/* Scan token objects */
599 	LIST_FOREACH(obj, &session->token->object_list, link) {
600 		uint32_t handle = 0;
601 		bool new_load = false;
602 
603 		if (!obj->attributes) {
604 			rc = load_persistent_object_attributes(obj);
605 			if (rc) {
606 				rc = PKCS11_CKR_GENERAL_ERROR;
607 				goto out;
608 			}
609 
610 			new_load = true;
611 		}
612 
613 		if (!obj->attributes ||
614 		    check_access_attrs_against_token(session,
615 						     obj->attributes) ||
616 		    !attributes_match_reference(obj->attributes, req_attrs)) {
617 			if (new_load)
618 				release_persistent_object_attributes(obj);
619 
620 			continue;
621 		}
622 
623 		/* Resolve object handle for object */
624 		handle = pkcs11_object2handle(obj, session);
625 		if (!handle) {
626 			handle = handle_get(object_db, obj);
627 			if (!handle) {
628 				rc = PKCS11_CKR_DEVICE_MEMORY;
629 				goto out;
630 			}
631 		}
632 
633 		rc = find_ctx_add(find_ctx, handle);
634 		if (rc)
635 			goto out;
636 	}
637 
638 	find_ctx->attributes = req_attrs;
639 	req_attrs = NULL;
640 	session->find_ctx = find_ctx;
641 	find_ctx = NULL;
642 	rc = PKCS11_CKR_OK;
643 
644 out:
645 	TEE_Free(req_attrs);
646 	TEE_Free(template);
647 	release_find_obj_context(find_ctx);
648 
649 	return rc;
650 }
651 
entry_find_objects(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)652 enum pkcs11_rc entry_find_objects(struct pkcs11_client *client,
653 				  uint32_t ptypes, TEE_Param *params)
654 {
655 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
656 						TEE_PARAM_TYPE_NONE,
657 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
658 						TEE_PARAM_TYPE_NONE);
659 	TEE_Param *ctrl = params;
660 	TEE_Param *out = params + 2;
661 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
662 	struct serialargs ctrlargs = { };
663 	struct pkcs11_session *session = NULL;
664 	struct pkcs11_find_objects *ctx = NULL;
665 	uint8_t *out_handles = NULL;
666 	size_t out_count = 0;
667 	size_t count = 0;
668 
669 	if (!client || ptypes != exp_pt)
670 		return PKCS11_CKR_ARGUMENTS_BAD;
671 
672 	out_count = out->memref.size / sizeof(uint32_t);
673 	out_handles = out->memref.buffer;
674 
675 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
676 
677 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
678 	if (rc)
679 		return rc;
680 
681 	if (serialargs_remaining_bytes(&ctrlargs))
682 		return PKCS11_CKR_ARGUMENTS_BAD;
683 
684 	ctx = session->find_ctx;
685 
686 	if (!ctx)
687 		return PKCS11_CKR_OPERATION_NOT_INITIALIZED;
688 
689 	for (count = 0; ctx->next < ctx->count && count < out_count;
690 	     ctx->next++, count++)
691 		TEE_MemMove(out_handles + count * sizeof(uint32_t),
692 			    ctx->handles + ctx->next, sizeof(uint32_t));
693 
694 	/* Update output buffer according the number of handles provided */
695 	out->memref.size = count * sizeof(uint32_t);
696 
697 	DMSG("PKCS11 session %"PRIu32": finding objects", session->handle);
698 
699 	return PKCS11_CKR_OK;
700 }
701 
release_session_find_obj_context(struct pkcs11_session * session)702 void release_session_find_obj_context(struct pkcs11_session *session)
703 {
704 	release_find_obj_context(session->find_ctx);
705 	session->find_ctx = NULL;
706 }
707 
entry_find_objects_final(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)708 enum pkcs11_rc entry_find_objects_final(struct pkcs11_client *client,
709 					uint32_t ptypes, TEE_Param *params)
710 {
711 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
712 						TEE_PARAM_TYPE_NONE,
713 						TEE_PARAM_TYPE_NONE,
714 						TEE_PARAM_TYPE_NONE);
715 	TEE_Param *ctrl = params;
716 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
717 	struct serialargs ctrlargs = { };
718 	struct pkcs11_session *session = NULL;
719 
720 	if (!client || ptypes != exp_pt)
721 		return PKCS11_CKR_ARGUMENTS_BAD;
722 
723 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
724 
725 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
726 	if (rc)
727 		return rc;
728 
729 	if (serialargs_remaining_bytes(&ctrlargs))
730 		return PKCS11_CKR_ARGUMENTS_BAD;
731 
732 	if (!session->find_ctx)
733 		return PKCS11_CKR_OPERATION_NOT_INITIALIZED;
734 
735 	release_session_find_obj_context(session);
736 
737 	return PKCS11_CKR_OK;
738 }
739 
entry_get_attribute_value(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)740 enum pkcs11_rc entry_get_attribute_value(struct pkcs11_client *client,
741 					 uint32_t ptypes, TEE_Param *params)
742 {
743 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
744 						TEE_PARAM_TYPE_NONE,
745 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
746 						TEE_PARAM_TYPE_NONE);
747 	TEE_Param *ctrl = params;
748 	TEE_Param *out = params + 2;
749 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
750 	struct serialargs ctrlargs = { };
751 	struct pkcs11_session *session = NULL;
752 	struct pkcs11_object_head *template = NULL;
753 	struct pkcs11_object *obj = NULL;
754 	uint32_t object_handle = 0;
755 	char *cur = NULL;
756 	size_t len = 0;
757 	char *end = NULL;
758 	bool attr_sensitive = 0;
759 	bool attr_type_invalid = 0;
760 	bool buffer_too_small = 0;
761 
762 	if (!client || ptypes != exp_pt)
763 		return PKCS11_CKR_ARGUMENTS_BAD;
764 
765 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
766 
767 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
768 	if (rc)
769 		return rc;
770 
771 	rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
772 	if (rc)
773 		return rc;
774 
775 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
776 	if (rc)
777 		return rc;
778 
779 	if (serialargs_remaining_bytes(&ctrlargs)) {
780 		rc = PKCS11_CKR_ARGUMENTS_BAD;
781 		goto out;
782 	}
783 
784 	obj = pkcs11_handle2object(object_handle, session);
785 	if (!obj) {
786 		rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
787 		goto out;
788 	}
789 
790 	rc = check_access_attrs_against_token(session, obj->attributes);
791 	if (rc) {
792 		rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
793 		goto out;
794 	}
795 
796 	/* Iterate over attributes and set their values */
797 	/*
798 	 * 1. If the specified attribute (i.e., the attribute specified by the
799 	 * type field) for the object cannot be revealed because the object is
800 	 * sensitive or unextractable, then the ulValueLen field in that triple
801 	 * is modified to hold the value PKCS11_CK_UNAVAILABLE_INFORMATION.
802 	 *
803 	 * 2. Otherwise, if the specified value for the object is invalid (the
804 	 * object does not possess such an attribute), then the ulValueLen field
805 	 * in that triple is modified to hold the value
806 	 * PKCS11_CK_UNAVAILABLE_INFORMATION.
807 	 *
808 	 * 3. Otherwise, if the pValue field has the value NULL_PTR, then the
809 	 * ulValueLen field is modified to hold the exact length of the
810 	 * specified attribute for the object.
811 	 *
812 	 * 4. Otherwise, if the length specified in ulValueLen is large enough
813 	 * to hold the value of the specified attribute for the object, then
814 	 * that attribute is copied into the buffer located at pValue, and the
815 	 * ulValueLen field is modified to hold the exact length of the
816 	 * attribute.
817 	 *
818 	 * 5. Otherwise, the ulValueLen field is modified to hold the value
819 	 * PKCS11_CK_UNAVAILABLE_INFORMATION.
820 	 */
821 	cur = (char *)template + sizeof(struct pkcs11_object_head);
822 	end = cur + template->attrs_size;
823 
824 	for (; cur < end; cur += len) {
825 		struct pkcs11_attribute_head *cli_ref = (void *)cur;
826 		struct pkcs11_attribute_head cli_head = { };
827 		void *data_ptr = NULL;
828 
829 		/* Make copy of header so that is aligned properly. */
830 		TEE_MemMove(&cli_head, cli_ref, sizeof(cli_head));
831 
832 		len = sizeof(*cli_ref) + cli_head.size;
833 
834 		/* We don't support getting value of indirect templates */
835 		if (pkcs11_attr_has_indirect_attributes(cli_head.id)) {
836 			attr_type_invalid = 1;
837 			continue;
838 		}
839 
840 		/* Check 1. */
841 		if (!attribute_is_exportable(&cli_head, obj)) {
842 			cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION;
843 			TEE_MemMove(&cli_ref->size, &cli_head.size,
844 				    sizeof(cli_head.size));
845 			attr_sensitive = 1;
846 			continue;
847 		}
848 
849 		/* Get real data pointer from template data */
850 		data_ptr = cli_head.size ? cli_ref->data : NULL;
851 
852 		/*
853 		 * We assume that if size is 0, pValue was NULL, so we return
854 		 * the size of the required buffer for it (3., 4.)
855 		 */
856 		rc = get_attribute(obj->attributes, cli_head.id, data_ptr,
857 				   &cli_head.size);
858 		/* Check 2. */
859 		switch (rc) {
860 		case PKCS11_CKR_OK:
861 			break;
862 		case PKCS11_RV_NOT_FOUND:
863 			cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION;
864 			attr_type_invalid = 1;
865 			break;
866 		case PKCS11_CKR_BUFFER_TOO_SMALL:
867 			if (data_ptr)
868 				buffer_too_small = 1;
869 			break;
870 		default:
871 			rc = PKCS11_CKR_GENERAL_ERROR;
872 			goto out;
873 		}
874 
875 		TEE_MemMove(&cli_ref->size, &cli_head.size,
876 			    sizeof(cli_head.size));
877 	}
878 
879 	/*
880 	 * If case 1 applies to any of the requested attributes, then the call
881 	 * should return the value CKR_ATTRIBUTE_SENSITIVE. If case 2 applies to
882 	 * any of the requested attributes, then the call should return the
883 	 * value CKR_ATTRIBUTE_TYPE_INVALID. If case 5 applies to any of the
884 	 * requested attributes, then the call should return the value
885 	 * CKR_BUFFER_TOO_SMALL. As usual, if more than one of these error codes
886 	 * is applicable, Cryptoki may return any of them. Only if none of them
887 	 * applies to any of the requested attributes will CKR_OK be returned.
888 	 */
889 
890 	rc = PKCS11_CKR_OK;
891 	if (attr_sensitive)
892 		rc = PKCS11_CKR_ATTRIBUTE_SENSITIVE;
893 	if (attr_type_invalid)
894 		rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
895 	if (buffer_too_small)
896 		rc = PKCS11_CKR_BUFFER_TOO_SMALL;
897 
898 	/* Move updated template to out buffer */
899 	TEE_MemMove(out->memref.buffer, template, out->memref.size);
900 
901 	DMSG("PKCS11 session %"PRIu32": get attributes %#"PRIx32,
902 	     session->handle, object_handle);
903 
904 out:
905 	TEE_Free(template);
906 
907 	return rc;
908 }
909 
entry_get_object_size(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)910 enum pkcs11_rc entry_get_object_size(struct pkcs11_client *client,
911 				     uint32_t ptypes, TEE_Param *params)
912 {
913 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
914 						TEE_PARAM_TYPE_NONE,
915 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
916 						TEE_PARAM_TYPE_NONE);
917 	TEE_Param *ctrl = params;
918 	TEE_Param *out = params + 2;
919 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
920 	struct serialargs ctrlargs = { };
921 	struct pkcs11_session *session = NULL;
922 	uint32_t object_handle = 0;
923 	struct pkcs11_object *obj = NULL;
924 	uint32_t obj_size = 0;
925 
926 	if (!client || ptypes != exp_pt)
927 		return PKCS11_CKR_ARGUMENTS_BAD;
928 
929 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
930 
931 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
932 	if (rc)
933 		return rc;
934 
935 	rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
936 	if (rc)
937 		return rc;
938 
939 	if (serialargs_remaining_bytes(&ctrlargs))
940 		return PKCS11_CKR_ARGUMENTS_BAD;
941 
942 	obj = pkcs11_handle2object(object_handle, session);
943 	if (!obj)
944 		return PKCS11_CKR_OBJECT_HANDLE_INVALID;
945 
946 	rc = check_access_attrs_against_token(session, obj->attributes);
947 	if (rc)
948 		return PKCS11_CKR_OBJECT_HANDLE_INVALID;
949 
950 	if (out->memref.size != sizeof(uint32_t))
951 		return PKCS11_CKR_ARGUMENTS_BAD;
952 
953 	obj_size = ((struct obj_attrs *)obj->attributes)->attrs_size +
954 		   sizeof(struct obj_attrs);
955 	TEE_MemMove(out->memref.buffer, &obj_size, sizeof(obj_size));
956 
957 	return PKCS11_CKR_OK;
958 }
959 
entry_set_attribute_value(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)960 enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client,
961 					 uint32_t ptypes, TEE_Param *params)
962 {
963 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
964 						TEE_PARAM_TYPE_NONE,
965 						TEE_PARAM_TYPE_NONE,
966 						TEE_PARAM_TYPE_NONE);
967 	TEE_Param *ctrl = params;
968 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
969 	struct serialargs ctrlargs = { };
970 	struct pkcs11_session *session = NULL;
971 	struct pkcs11_object_head *template = NULL;
972 	size_t template_size = 0;
973 	struct pkcs11_object *obj = NULL;
974 	struct obj_attrs *head = NULL;
975 	uint32_t object_handle = 0;
976 	enum processing_func function = PKCS11_FUNCTION_MODIFY;
977 
978 	if (!client || ptypes != exp_pt)
979 		return PKCS11_CKR_ARGUMENTS_BAD;
980 
981 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
982 
983 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
984 	if (rc)
985 		return rc;
986 
987 	rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
988 	if (rc)
989 		return rc;
990 
991 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
992 	if (rc)
993 		return rc;
994 
995 	if (serialargs_remaining_bytes(&ctrlargs)) {
996 		rc = PKCS11_CKR_ARGUMENTS_BAD;
997 		goto out;
998 	}
999 
1000 	obj = pkcs11_handle2object(object_handle, session);
1001 	if (!obj) {
1002 		rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
1003 		goto out;
1004 	}
1005 
1006 	/* Only session objects can be modified during a read-only session */
1007 	if (object_is_token(obj->attributes) &&
1008 	    !pkcs11_session_is_read_write(session)) {
1009 		DMSG("Can't modify persistent object in a RO session");
1010 		rc = PKCS11_CKR_SESSION_READ_ONLY;
1011 		goto out;
1012 	}
1013 
1014 	/*
1015 	 * Only public objects can be modified unless normal user is logged in
1016 	 */
1017 	rc = check_access_attrs_against_token(session, obj->attributes);
1018 	if (rc) {
1019 		rc = PKCS11_CKR_USER_NOT_LOGGED_IN;
1020 		goto out;
1021 	}
1022 
1023 	/* Objects with PKCS11_CKA_MODIFIABLE as false aren't modifiable */
1024 	if (!object_is_modifiable(obj->attributes)) {
1025 		rc = PKCS11_CKR_ACTION_PROHIBITED;
1026 		goto out;
1027 	}
1028 
1029 	template_size = sizeof(*template) + template->attrs_size;
1030 
1031 	/*
1032 	 * Prepare a clean initial state (@head) for the template. Helps in
1033 	 * removing any duplicates or inconsistent values from the
1034 	 * template.
1035 	 */
1036 	rc = create_attributes_from_template(&head, template, template_size,
1037 					     NULL, function,
1038 					     PKCS11_CKM_UNDEFINED_ID,
1039 					     PKCS11_CKO_UNDEFINED_ID);
1040 	if (rc)
1041 		goto out;
1042 
1043 	/* Check the attributes in @head to see if they are modifiable */
1044 	rc = check_attrs_against_modification(session, head, obj, function);
1045 	if (rc)
1046 		goto out;
1047 
1048 	/*
1049 	 * All checks complete. The attributes in @head have been checked and
1050 	 * can now be used to set/modify the object attributes.
1051 	 */
1052 	rc = modify_attributes_list(&obj->attributes, head);
1053 	if (rc)
1054 		goto out;
1055 
1056 	if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
1057 		rc = update_persistent_object_attributes(obj);
1058 		if (rc)
1059 			goto out;
1060 	}
1061 
1062 	DMSG("PKCS11 session %"PRIu32": set attributes %#"PRIx32,
1063 	     session->handle, object_handle);
1064 
1065 out:
1066 	TEE_Free(head);
1067 	TEE_Free(template);
1068 	return rc;
1069 }
1070 
entry_copy_object(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)1071 enum pkcs11_rc entry_copy_object(struct pkcs11_client *client, uint32_t ptypes,
1072 				 TEE_Param *params)
1073 {
1074 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1075 						TEE_PARAM_TYPE_NONE,
1076 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
1077 						TEE_PARAM_TYPE_NONE);
1078 	TEE_Param *ctrl = params;
1079 	TEE_Param *out = params + 2;
1080 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1081 	struct serialargs ctrlargs = { };
1082 	struct pkcs11_session *session = NULL;
1083 	struct pkcs11_object_head *template = NULL;
1084 	struct obj_attrs *head = NULL;
1085 	struct obj_attrs *head_new = NULL;
1086 	size_t template_size = 0;
1087 	struct pkcs11_object *obj = NULL;
1088 	uint32_t object_handle = 0;
1089 	uint32_t obj_handle = 0;
1090 	enum processing_func function = PKCS11_FUNCTION_COPY;
1091 	enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID;
1092 
1093 	if (!client || ptypes != exp_pt ||
1094 	    out->memref.size != sizeof(obj_handle))
1095 		return PKCS11_CKR_ARGUMENTS_BAD;
1096 
1097 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1098 
1099 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1100 	if (rc)
1101 		return rc;
1102 
1103 	rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
1104 	if (rc)
1105 		return rc;
1106 
1107 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
1108 	if (rc)
1109 		return rc;
1110 
1111 	if (serialargs_remaining_bytes(&ctrlargs)) {
1112 		rc = PKCS11_CKR_ARGUMENTS_BAD;
1113 		goto out;
1114 	}
1115 
1116 	obj = pkcs11_handle2object(object_handle, session);
1117 	if (!obj) {
1118 		rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
1119 		goto out;
1120 	}
1121 
1122 	/* Only session objects can be modified during a read-only session */
1123 	if (object_is_token(obj->attributes) &&
1124 	    !pkcs11_session_is_read_write(session)) {
1125 		DMSG("Can't modify persistent object in a RO session");
1126 		rc = PKCS11_CKR_SESSION_READ_ONLY;
1127 		goto out;
1128 	}
1129 
1130 	/*
1131 	 * Only public objects can be modified unless normal user is logged in
1132 	 */
1133 	rc = check_access_attrs_against_token(session, obj->attributes);
1134 	if (rc) {
1135 		rc = PKCS11_CKR_USER_NOT_LOGGED_IN;
1136 		goto out;
1137 	}
1138 
1139 	/* Objects with PKCS11_CKA_COPYABLE as false can't be copied */
1140 	if (!object_is_copyable(obj->attributes)) {
1141 		rc = PKCS11_CKR_ACTION_PROHIBITED;
1142 		goto out;
1143 	}
1144 
1145 	template_size = sizeof(*template) + template->attrs_size;
1146 
1147 	/*
1148 	 * Prepare a clean initial state (@head) for the template. Helps in
1149 	 * removing any duplicates or inconsistent values from the
1150 	 * template.
1151 	 */
1152 	rc = create_attributes_from_template(&head, template, template_size,
1153 					     NULL, function,
1154 					     PKCS11_CKM_UNDEFINED_ID,
1155 					     PKCS11_CKO_UNDEFINED_ID);
1156 	if (rc)
1157 		goto out;
1158 
1159 	/* Check the attributes in @head to see if they are modifiable */
1160 	rc = check_attrs_against_modification(session, head, obj, function);
1161 	if (rc)
1162 		goto out;
1163 
1164 	class = get_class(obj->attributes);
1165 
1166 	if (class == PKCS11_CKO_SECRET_KEY ||
1167 	    class == PKCS11_CKO_PRIVATE_KEY) {
1168 		/*
1169 		 * If CKA_EXTRACTABLE attribute in passed template (@head) is
1170 		 * modified to CKA_FALSE, CKA_NEVER_EXTRACTABLE should also
1171 		 * change to CKA_FALSE in copied obj. So, add it to the
1172 		 * passed template.
1173 		 */
1174 		uint8_t bbool = 0;
1175 		uint32_t size = sizeof(bbool);
1176 
1177 		rc = get_attribute(head, PKCS11_CKA_EXTRACTABLE, &bbool, &size);
1178 		if (!rc && !bbool) {
1179 			rc = add_attribute(&head, PKCS11_CKA_NEVER_EXTRACTABLE,
1180 					   &bbool, sizeof(uint8_t));
1181 			if (rc)
1182 				goto out;
1183 		}
1184 		rc = PKCS11_CKR_OK;
1185 	}
1186 
1187 	/*
1188 	 * All checks have passed. Create a copy of the serialized buffer which
1189 	 * holds the object attributes in @head_new for the new object
1190 	 */
1191 	template_size = sizeof(*obj->attributes) + obj->attributes->attrs_size;
1192 	head_new = TEE_Malloc(template_size, TEE_MALLOC_FILL_ZERO);
1193 	if (!head_new) {
1194 		rc = PKCS11_CKR_DEVICE_MEMORY;
1195 		goto out;
1196 	}
1197 
1198 	TEE_MemMove(head_new, obj->attributes, template_size);
1199 
1200 	/*
1201 	 * Modify the copied attribute @head_new based on the template @head
1202 	 * given by the callee
1203 	 */
1204 	rc = modify_attributes_list(&head_new, head);
1205 	if (rc)
1206 		goto out;
1207 
1208 	/*
1209 	 * At this stage the object is almost created: all its attributes are
1210 	 * referenced in @head_new, including the key value and are assumed
1211 	 * reliable. Now need to register it and get a handle for it.
1212 	 */
1213 	rc = create_object(session, head_new, &obj_handle);
1214 	if (rc)
1215 		goto out;
1216 
1217 	/*
1218 	 * Now obj_handle (through the related struct pkcs11_object
1219 	 * instance) owns the serialized buffer that holds the object
1220 	 * attributes. We clear reference in head to NULL as the serializer
1221 	 * object is now referred from obj_handle. This allows smooth pass
1222 	 * through free at function exit.
1223 	 */
1224 	head_new = NULL;
1225 
1226 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
1227 	out->memref.size = sizeof(obj_handle);
1228 
1229 	DMSG("PKCS11 session %"PRIu32": copy object %#"PRIx32,
1230 	     session->handle, obj_handle);
1231 
1232 out:
1233 	TEE_Free(head_new);
1234 	TEE_Free(head);
1235 	TEE_Free(template);
1236 	return rc;
1237 }
1238