xref: /optee_os/ta/pkcs11/src/object.c (revision dc99b202f3997248adbe7508698c051f6d677cd0)
1b56b3d07SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2b56b3d07SJens Wiklander /*
3b56b3d07SJens Wiklander  * Copyright (c) 2017-2020, Linaro Limited
4b56b3d07SJens Wiklander  */
5b56b3d07SJens Wiklander 
6b56b3d07SJens Wiklander #include <assert.h>
7b56b3d07SJens Wiklander #include <inttypes.h>
8b56b3d07SJens Wiklander #include <string_ext.h>
9b56b3d07SJens Wiklander #include <tee_internal_api.h>
10b56b3d07SJens Wiklander #include <tee_internal_api_extensions.h>
11b56b3d07SJens Wiklander 
12b56b3d07SJens Wiklander #include "attributes.h"
13b56b3d07SJens Wiklander #include "handle.h"
14b56b3d07SJens Wiklander #include "object.h"
15b56b3d07SJens Wiklander #include "pkcs11_attributes.h"
16b56b3d07SJens Wiklander #include "pkcs11_helpers.h"
17b56b3d07SJens Wiklander #include "pkcs11_token.h"
18b56b3d07SJens Wiklander #include "sanitize_object.h"
19b56b3d07SJens Wiklander #include "serializer.h"
20b56b3d07SJens Wiklander 
21b56b3d07SJens Wiklander struct pkcs11_object *pkcs11_handle2object(uint32_t handle,
22b56b3d07SJens Wiklander 					   struct pkcs11_session *session)
23b56b3d07SJens Wiklander {
24b56b3d07SJens Wiklander 	return handle_lookup(&session->object_handle_db, handle);
25b56b3d07SJens Wiklander }
26b56b3d07SJens Wiklander 
27b56b3d07SJens Wiklander uint32_t pkcs11_object2handle(struct pkcs11_object *obj,
28b56b3d07SJens Wiklander 			      struct pkcs11_session *session)
29b56b3d07SJens Wiklander {
30b56b3d07SJens Wiklander 	return handle_lookup_handle(&session->object_handle_db, obj);
31b56b3d07SJens Wiklander }
32b56b3d07SJens Wiklander 
33b56b3d07SJens Wiklander /* Currently handle pkcs11 sessions and tokens */
34b56b3d07SJens Wiklander 
35b56b3d07SJens Wiklander static struct object_list *get_session_objects(void *session)
36b56b3d07SJens Wiklander {
37b56b3d07SJens Wiklander 	/* Currently supporting only pkcs11 session */
38b56b3d07SJens Wiklander 	struct pkcs11_session *ck_session = session;
39b56b3d07SJens Wiklander 
40b56b3d07SJens Wiklander 	return pkcs11_get_session_objects(ck_session);
41b56b3d07SJens Wiklander }
42b56b3d07SJens Wiklander 
43334316feSJens Wiklander static struct ck_token *get_session_token(void *session)
44334316feSJens Wiklander {
45334316feSJens Wiklander 	struct pkcs11_session *ck_session = session;
46334316feSJens Wiklander 
47334316feSJens Wiklander 	return pkcs11_session2token(ck_session);
48334316feSJens Wiklander }
49334316feSJens Wiklander 
50b56b3d07SJens Wiklander /* Release resources of a non-persistent object */
51b56b3d07SJens Wiklander static void cleanup_volatile_obj_ref(struct pkcs11_object *obj)
52b56b3d07SJens Wiklander {
53b56b3d07SJens Wiklander 	if (!obj)
54b56b3d07SJens Wiklander 		return;
55b56b3d07SJens Wiklander 
56b56b3d07SJens Wiklander 	if (obj->key_handle != TEE_HANDLE_NULL)
57b56b3d07SJens Wiklander 		TEE_FreeTransientObject(obj->key_handle);
58b56b3d07SJens Wiklander 
59b56b3d07SJens Wiklander 	if (obj->attribs_hdl != TEE_HANDLE_NULL)
60b56b3d07SJens Wiklander 		TEE_CloseObject(obj->attribs_hdl);
61b56b3d07SJens Wiklander 
62b56b3d07SJens Wiklander 	TEE_Free(obj->attributes);
63b56b3d07SJens Wiklander 	TEE_Free(obj->uuid);
64b56b3d07SJens Wiklander 	TEE_Free(obj);
65b56b3d07SJens Wiklander }
66b56b3d07SJens Wiklander 
67b56b3d07SJens Wiklander /* Release resources of a persistent object including volatile resources */
687f12c782SRobin van der Gracht void cleanup_persistent_object(struct pkcs11_object *obj,
69334316feSJens Wiklander 			       struct ck_token *token)
70b56b3d07SJens Wiklander {
71334316feSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
72334316feSJens Wiklander 
73334316feSJens Wiklander 	if (!obj)
74334316feSJens Wiklander 		return;
75334316feSJens Wiklander 
76334316feSJens Wiklander 	/* Open handle with write properties to destroy the object */
77334316feSJens Wiklander 	if (obj->attribs_hdl != TEE_HANDLE_NULL)
78334316feSJens Wiklander 		TEE_CloseObject(obj->attribs_hdl);
79334316feSJens Wiklander 
80334316feSJens Wiklander 	res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
81334316feSJens Wiklander 				       obj->uuid, sizeof(TEE_UUID),
82334316feSJens Wiklander 				       TEE_DATA_FLAG_ACCESS_WRITE_META,
83334316feSJens Wiklander 				       &obj->attribs_hdl);
84334316feSJens Wiklander 	if (!res)
85334316feSJens Wiklander 		TEE_CloseAndDeletePersistentObject1(obj->attribs_hdl);
86334316feSJens Wiklander 
87334316feSJens Wiklander 	obj->attribs_hdl = TEE_HANDLE_NULL;
88334316feSJens Wiklander 	destroy_object_uuid(token, obj);
89334316feSJens Wiklander 
90334316feSJens Wiklander 	LIST_REMOVE(obj, link);
91334316feSJens Wiklander 
92334316feSJens Wiklander 	cleanup_volatile_obj_ref(obj);
93b56b3d07SJens Wiklander }
94b56b3d07SJens Wiklander 
95b56b3d07SJens Wiklander /*
96b56b3d07SJens Wiklander  * destroy_object - destroy an PKCS11 TA object
97b56b3d07SJens Wiklander  *
98b56b3d07SJens Wiklander  * @session - session requesting object destruction
99b56b3d07SJens Wiklander  * @obj - reference to the PKCS11 TA object
100b56b3d07SJens Wiklander  * @session_only - true if only session object shall be destroyed
101b56b3d07SJens Wiklander  */
102b56b3d07SJens Wiklander void destroy_object(struct pkcs11_session *session, struct pkcs11_object *obj,
103b56b3d07SJens Wiklander 		    bool session_only)
104b56b3d07SJens Wiklander {
105b56b3d07SJens Wiklander #ifdef DEBUG
106b56b3d07SJens Wiklander 	trace_attributes("[destroy]", obj->attributes);
107b56b3d07SJens Wiklander 	if (obj->uuid)
108b56b3d07SJens Wiklander 		MSG_RAW("[destroy] obj uuid %pUl", (void *)obj->uuid);
109b56b3d07SJens Wiklander #endif
110b56b3d07SJens Wiklander 
111b56b3d07SJens Wiklander 	/*
112b56b3d07SJens Wiklander 	 * Remove from session list only if it was published.
113b56b3d07SJens Wiklander 	 *
114b56b3d07SJens Wiklander 	 * This depends on obj->link.le_prev always pointing on the
115b56b3d07SJens Wiklander 	 * link.le_next element in the previous object in the list even if
116b56b3d07SJens Wiklander 	 * there's only a single object in the list. In the first object in
117b56b3d07SJens Wiklander 	 * the list obj->link.le_prev instead points to lh_first in the
118b56b3d07SJens Wiklander 	 * list head. If list implementation is changed we need to revisit
119b56b3d07SJens Wiklander 	 * this.
120b56b3d07SJens Wiklander 	 */
121b56b3d07SJens Wiklander 	if (obj->link.le_next || obj->link.le_prev)
122b56b3d07SJens Wiklander 		LIST_REMOVE(obj, link);
123b56b3d07SJens Wiklander 
124b56b3d07SJens Wiklander 	if (session_only) {
125b56b3d07SJens Wiklander 		/* Destroy object due to session closure */
126b56b3d07SJens Wiklander 		handle_put(&session->object_handle_db,
127b56b3d07SJens Wiklander 			   pkcs11_object2handle(obj, session));
128b56b3d07SJens Wiklander 		cleanup_volatile_obj_ref(obj);
129b56b3d07SJens Wiklander 
130b56b3d07SJens Wiklander 		return;
131b56b3d07SJens Wiklander 	}
132b56b3d07SJens Wiklander 
133b56b3d07SJens Wiklander 	/* Destroy target object (persistent or not) */
134b56b3d07SJens Wiklander 	if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
135334316feSJens Wiklander 		assert(obj->uuid);
136334316feSJens Wiklander 		/* Try twice otherwise panic! */
137334316feSJens Wiklander 		if (unregister_persistent_object(session->token, obj->uuid) &&
138334316feSJens Wiklander 		    unregister_persistent_object(session->token, obj->uuid))
139b56b3d07SJens Wiklander 			TEE_Panic(0);
140334316feSJens Wiklander 
141334316feSJens Wiklander 		handle_put(&session->object_handle_db,
142334316feSJens Wiklander 			   pkcs11_object2handle(obj, session));
143334316feSJens Wiklander 		cleanup_persistent_object(obj, session->token);
144b56b3d07SJens Wiklander 	} else {
145b56b3d07SJens Wiklander 		handle_put(&session->object_handle_db,
146b56b3d07SJens Wiklander 			   pkcs11_object2handle(obj, session));
147b56b3d07SJens Wiklander 		cleanup_volatile_obj_ref(obj);
148b56b3d07SJens Wiklander 	}
149b56b3d07SJens Wiklander }
150b56b3d07SJens Wiklander 
151b56b3d07SJens Wiklander static struct pkcs11_object *create_obj_instance(struct obj_attrs *head)
152b56b3d07SJens Wiklander {
153b56b3d07SJens Wiklander 	struct pkcs11_object *obj = NULL;
154b56b3d07SJens Wiklander 
155b56b3d07SJens Wiklander 	obj = TEE_Malloc(sizeof(struct pkcs11_object), TEE_MALLOC_FILL_ZERO);
156b56b3d07SJens Wiklander 	if (!obj)
157b56b3d07SJens Wiklander 		return NULL;
158b56b3d07SJens Wiklander 
159b56b3d07SJens Wiklander 	obj->key_handle = TEE_HANDLE_NULL;
160b56b3d07SJens Wiklander 	obj->attribs_hdl = TEE_HANDLE_NULL;
161b56b3d07SJens Wiklander 	obj->attributes = head;
162b56b3d07SJens Wiklander 
163b56b3d07SJens Wiklander 	return obj;
164b56b3d07SJens Wiklander }
165b56b3d07SJens Wiklander 
166334316feSJens Wiklander struct pkcs11_object *create_token_object(struct obj_attrs *head,
167334316feSJens Wiklander 					  TEE_UUID *uuid)
168334316feSJens Wiklander {
169334316feSJens Wiklander 	struct pkcs11_object *obj = create_obj_instance(head);
170334316feSJens Wiklander 
171334316feSJens Wiklander 	if (obj)
172334316feSJens Wiklander 		obj->uuid = uuid;
173334316feSJens Wiklander 
174334316feSJens Wiklander 	return obj;
175334316feSJens Wiklander }
176334316feSJens Wiklander 
177b56b3d07SJens Wiklander /*
178b56b3d07SJens Wiklander  * create_object - create an PKCS11 TA object from its attributes and value
179b56b3d07SJens Wiklander  *
180b56b3d07SJens Wiklander  * @sess - session requesting object creation
181b56b3d07SJens Wiklander  * @head - reference to serialized attributes
182b56b3d07SJens Wiklander  * @out_handle - generated handle for the created object
183b56b3d07SJens Wiklander  */
184b56b3d07SJens Wiklander enum pkcs11_rc create_object(void *sess, struct obj_attrs *head,
185b56b3d07SJens Wiklander 			     uint32_t *out_handle)
186b56b3d07SJens Wiklander {
187fde67b24SEtienne Carriere 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
188b56b3d07SJens Wiklander 	struct pkcs11_object *obj = NULL;
189b56b3d07SJens Wiklander 	struct pkcs11_session *session = (struct pkcs11_session *)sess;
190b56b3d07SJens Wiklander 	uint32_t obj_handle = 0;
191b56b3d07SJens Wiklander 
192b56b3d07SJens Wiklander #ifdef DEBUG
193b56b3d07SJens Wiklander 	trace_attributes("[create]", head);
194b56b3d07SJens Wiklander #endif
195b56b3d07SJens Wiklander 
196b56b3d07SJens Wiklander 	/*
197b56b3d07SJens Wiklander 	 * We do not check the key attributes. At this point, key attributes
198b56b3d07SJens Wiklander 	 * are expected consistent and reliable.
199b56b3d07SJens Wiklander 	 */
200b56b3d07SJens Wiklander 
201b56b3d07SJens Wiklander 	obj = create_obj_instance(head);
202b56b3d07SJens Wiklander 	if (!obj)
203b56b3d07SJens Wiklander 		return PKCS11_CKR_DEVICE_MEMORY;
204b56b3d07SJens Wiklander 
205b56b3d07SJens Wiklander 	/* Create a handle for the object in the session database */
206b56b3d07SJens Wiklander 	obj_handle = handle_get(&session->object_handle_db, obj);
207b56b3d07SJens Wiklander 	if (!obj_handle) {
208b56b3d07SJens Wiklander 		rc = PKCS11_CKR_DEVICE_MEMORY;
209b56b3d07SJens Wiklander 		goto err;
210b56b3d07SJens Wiklander 	}
211b56b3d07SJens Wiklander 
212b56b3d07SJens Wiklander 	if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
213334316feSJens Wiklander 		TEE_Result res = TEE_SUCCESS;
214334316feSJens Wiklander 
215334316feSJens Wiklander 		/*
216334316feSJens Wiklander 		 * Get an ID for the persistent object
217334316feSJens Wiklander 		 * Create the file
218334316feSJens Wiklander 		 * Register the object in the persistent database
219334316feSJens Wiklander 		 * (move the full sequence to persisent_db.c?)
220334316feSJens Wiklander 		 */
221334316feSJens Wiklander 		size_t size = sizeof(struct obj_attrs) +
222334316feSJens Wiklander 			      obj->attributes->attrs_size;
223334316feSJens Wiklander 		uint32_t tee_obj_flags = TEE_DATA_FLAG_ACCESS_READ |
224334316feSJens Wiklander 					 TEE_DATA_FLAG_ACCESS_WRITE |
225334316feSJens Wiklander 					 TEE_DATA_FLAG_ACCESS_WRITE_META;
226334316feSJens Wiklander 
227334316feSJens Wiklander 		rc = create_object_uuid(get_session_token(session), obj);
228334316feSJens Wiklander 		if (rc)
229334316feSJens Wiklander 			goto err;
230334316feSJens Wiklander 
231334316feSJens Wiklander 		res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
232334316feSJens Wiklander 						 obj->uuid, sizeof(TEE_UUID),
233334316feSJens Wiklander 						 tee_obj_flags,
234334316feSJens Wiklander 						 TEE_HANDLE_NULL,
235334316feSJens Wiklander 						 obj->attributes, size,
236334316feSJens Wiklander 						 &obj->attribs_hdl);
237334316feSJens Wiklander 		if (res) {
238334316feSJens Wiklander 			rc = tee2pkcs_error(res);
239334316feSJens Wiklander 			goto err;
240334316feSJens Wiklander 		}
241334316feSJens Wiklander 
242334316feSJens Wiklander 		rc = register_persistent_object(get_session_token(session),
243334316feSJens Wiklander 						obj->uuid);
244334316feSJens Wiklander 		if (rc)
245334316feSJens Wiklander 			goto err;
246334316feSJens Wiklander 
247334316feSJens Wiklander 		LIST_INSERT_HEAD(&session->token->object_list, obj, link);
248b56b3d07SJens Wiklander 	} else {
249b56b3d07SJens Wiklander 		rc = PKCS11_CKR_OK;
250b56b3d07SJens Wiklander 		LIST_INSERT_HEAD(get_session_objects(session), obj, link);
251b56b3d07SJens Wiklander 	}
252b56b3d07SJens Wiklander 
253b56b3d07SJens Wiklander 	*out_handle = obj_handle;
254b56b3d07SJens Wiklander 
255b56b3d07SJens Wiklander 	return PKCS11_CKR_OK;
256b56b3d07SJens Wiklander err:
257b56b3d07SJens Wiklander 	/* make sure that supplied "head" isn't freed */
258b56b3d07SJens Wiklander 	obj->attributes = NULL;
259b56b3d07SJens Wiklander 	handle_put(&session->object_handle_db, obj_handle);
260b56b3d07SJens Wiklander 	if (get_bool(head, PKCS11_CKA_TOKEN))
261b56b3d07SJens Wiklander 		cleanup_persistent_object(obj, session->token);
262b56b3d07SJens Wiklander 	else
263b56b3d07SJens Wiklander 		cleanup_volatile_obj_ref(obj);
264b56b3d07SJens Wiklander 
265b56b3d07SJens Wiklander 	return rc;
266b56b3d07SJens Wiklander }
267b56b3d07SJens Wiklander 
268b56b3d07SJens Wiklander enum pkcs11_rc entry_create_object(struct pkcs11_client *client,
269b56b3d07SJens Wiklander 				   uint32_t ptypes, TEE_Param *params)
270b56b3d07SJens Wiklander {
271b56b3d07SJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
272b56b3d07SJens Wiklander 						TEE_PARAM_TYPE_NONE,
273b56b3d07SJens Wiklander 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
274b56b3d07SJens Wiklander 						TEE_PARAM_TYPE_NONE);
275b56b3d07SJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
276b56b3d07SJens Wiklander 	TEE_Param *ctrl = params;
277b56b3d07SJens Wiklander 	TEE_Param *out = params + 2;
278b56b3d07SJens Wiklander 	struct serialargs ctrlargs = { };
279b56b3d07SJens Wiklander 	struct pkcs11_session *session = NULL;
280b56b3d07SJens Wiklander 	struct obj_attrs *head = NULL;
281b56b3d07SJens Wiklander 	struct pkcs11_object_head *template = NULL;
282b56b3d07SJens Wiklander 	size_t template_size = 0;
283b56b3d07SJens Wiklander 	uint32_t obj_handle = 0;
284b56b3d07SJens Wiklander 
285b56b3d07SJens Wiklander 	/*
286b56b3d07SJens Wiklander 	 * Collect the arguments of the request
287b56b3d07SJens Wiklander 	 */
288b56b3d07SJens Wiklander 
289b56b3d07SJens Wiklander 	if (!client || ptypes != exp_pt ||
290b56b3d07SJens Wiklander 	    out->memref.size != sizeof(obj_handle))
291b56b3d07SJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
292b56b3d07SJens Wiklander 
293b56b3d07SJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
294b56b3d07SJens Wiklander 
29559a5257eSEtienne Carriere 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
296b56b3d07SJens Wiklander 	if (rc)
297b56b3d07SJens Wiklander 		return rc;
298b56b3d07SJens Wiklander 
299b56b3d07SJens Wiklander 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
300b56b3d07SJens Wiklander 	if (rc)
301b56b3d07SJens Wiklander 		return rc;
302b56b3d07SJens Wiklander 
303b56b3d07SJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs)) {
304b56b3d07SJens Wiklander 		rc = PKCS11_CKR_ARGUMENTS_BAD;
305b56b3d07SJens Wiklander 		goto out;
306b56b3d07SJens Wiklander 	}
307b56b3d07SJens Wiklander 
308b56b3d07SJens Wiklander 	template_size = sizeof(*template) + template->attrs_size;
309b56b3d07SJens Wiklander 
310b56b3d07SJens Wiklander 	/*
311b56b3d07SJens Wiklander 	 * Prepare a clean initial state for the requested object attributes.
312b56b3d07SJens Wiklander 	 * Free temporary template once done.
313b56b3d07SJens Wiklander 	 */
314b56b3d07SJens Wiklander 	rc = create_attributes_from_template(&head, template, template_size,
315b56b3d07SJens Wiklander 					     NULL, PKCS11_FUNCTION_IMPORT,
3164cfce748SRuchika Gupta 					     PKCS11_PROCESSING_IMPORT,
3174cfce748SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
318b56b3d07SJens Wiklander 	TEE_Free(template);
319b56b3d07SJens Wiklander 	template = NULL;
320b56b3d07SJens Wiklander 	if (rc)
321b56b3d07SJens Wiklander 		goto out;
322b56b3d07SJens Wiklander 
323b56b3d07SJens Wiklander 	/*
324b56b3d07SJens Wiklander 	 * Check target object attributes match target processing
325b56b3d07SJens Wiklander 	 * Check target object attributes match token state
326b56b3d07SJens Wiklander 	 */
327b56b3d07SJens Wiklander 	rc = check_created_attrs_against_processing(PKCS11_PROCESSING_IMPORT,
328b56b3d07SJens Wiklander 						    head);
329b56b3d07SJens Wiklander 	if (rc)
330b56b3d07SJens Wiklander 		goto out;
331b56b3d07SJens Wiklander 
332b56b3d07SJens Wiklander 	rc = check_created_attrs_against_token(session, head);
333b56b3d07SJens Wiklander 	if (rc)
334b56b3d07SJens Wiklander 		goto out;
335b56b3d07SJens Wiklander 
336b68aca61SRuchika Gupta 	rc = check_access_attrs_against_token(session, head);
337b68aca61SRuchika Gupta 	if (rc)
338b68aca61SRuchika Gupta 		goto out;
339b68aca61SRuchika Gupta 
340b56b3d07SJens Wiklander 	/*
341b56b3d07SJens Wiklander 	 * At this stage the object is almost created: all its attributes are
342b56b3d07SJens Wiklander 	 * referenced in @head, including the key value and are assumed
343b56b3d07SJens Wiklander 	 * reliable. Now need to register it and get a handle for it.
344b56b3d07SJens Wiklander 	 */
345b56b3d07SJens Wiklander 	rc = create_object(session, head, &obj_handle);
346b56b3d07SJens Wiklander 	if (rc)
347b56b3d07SJens Wiklander 		goto out;
348b56b3d07SJens Wiklander 
349b56b3d07SJens Wiklander 	/*
350b56b3d07SJens Wiklander 	 * Now obj_handle (through the related struct pkcs11_object
351b56b3d07SJens Wiklander 	 * instance) owns the serialised buffer that holds the object
352b56b3d07SJens Wiklander 	 * attributes. We clear reference in head to NULL as the serializer
353b56b3d07SJens Wiklander 	 * object is now referred from obj_handle. This allows smooth pass
354b56b3d07SJens Wiklander 	 * through free at function exit.
355b56b3d07SJens Wiklander 	 */
356b56b3d07SJens Wiklander 	head = NULL;
357b56b3d07SJens Wiklander 
358b56b3d07SJens Wiklander 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
359b56b3d07SJens Wiklander 	out->memref.size = sizeof(obj_handle);
360b56b3d07SJens Wiklander 
361b56b3d07SJens Wiklander 	DMSG("PKCS11 session %"PRIu32": import object %#"PRIx32,
362b56b3d07SJens Wiklander 	     session->handle, obj_handle);
363b56b3d07SJens Wiklander 
364b56b3d07SJens Wiklander out:
365b56b3d07SJens Wiklander 	TEE_Free(template);
366b56b3d07SJens Wiklander 	TEE_Free(head);
367b56b3d07SJens Wiklander 
368b56b3d07SJens Wiklander 	return rc;
369b56b3d07SJens Wiklander }
370b56b3d07SJens Wiklander 
371b56b3d07SJens Wiklander enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client,
372b56b3d07SJens Wiklander 				    uint32_t ptypes, TEE_Param *params)
373b56b3d07SJens Wiklander {
374b56b3d07SJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
375b56b3d07SJens Wiklander 						TEE_PARAM_TYPE_NONE,
376b56b3d07SJens Wiklander 						TEE_PARAM_TYPE_NONE,
377b56b3d07SJens Wiklander 						TEE_PARAM_TYPE_NONE);
378b56b3d07SJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
379b56b3d07SJens Wiklander 	TEE_Param *ctrl = params;
380b56b3d07SJens Wiklander 	struct serialargs ctrlargs = { };
381b56b3d07SJens Wiklander 	uint32_t object_handle = 0;
382b56b3d07SJens Wiklander 	struct pkcs11_session *session = NULL;
383b56b3d07SJens Wiklander 	struct pkcs11_object *object = NULL;
384b56b3d07SJens Wiklander 
385b56b3d07SJens Wiklander 	if (!client || ptypes != exp_pt)
386b56b3d07SJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
387b56b3d07SJens Wiklander 
388b56b3d07SJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
389b56b3d07SJens Wiklander 
39059a5257eSEtienne Carriere 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
391b56b3d07SJens Wiklander 	if (rc)
392b56b3d07SJens Wiklander 		return rc;
393b56b3d07SJens Wiklander 
394b56b3d07SJens Wiklander 	rc = serialargs_get_u32(&ctrlargs, &object_handle);
395b56b3d07SJens Wiklander 	if (rc)
396b56b3d07SJens Wiklander 		return rc;
397b56b3d07SJens Wiklander 
398b56b3d07SJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs))
399b56b3d07SJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
400b56b3d07SJens Wiklander 
401b56b3d07SJens Wiklander 	object = pkcs11_handle2object(object_handle, session);
402b56b3d07SJens Wiklander 	if (!object)
403b56b3d07SJens Wiklander 		return PKCS11_CKR_OBJECT_HANDLE_INVALID;
404b56b3d07SJens Wiklander 
405fab91492SRuchika Gupta 	/* Only session objects can be destroyed during a read-only session */
406fab91492SRuchika Gupta 	if (get_bool(object->attributes, PKCS11_CKA_TOKEN) &&
407fab91492SRuchika Gupta 	    !pkcs11_session_is_read_write(session)) {
408fab91492SRuchika Gupta 		DMSG("Can't destroy persistent object");
409fab91492SRuchika Gupta 		return PKCS11_CKR_SESSION_READ_ONLY;
410fab91492SRuchika Gupta 	}
411fab91492SRuchika Gupta 
412fab91492SRuchika Gupta 	/*
413fab91492SRuchika Gupta 	 * Only public objects can be destroyed unless normal user is logged in
414fab91492SRuchika Gupta 	 */
415fab91492SRuchika Gupta 	rc = check_access_attrs_against_token(session, object->attributes);
416fab91492SRuchika Gupta 	if (rc)
417fab91492SRuchika Gupta 		return PKCS11_CKR_USER_NOT_LOGGED_IN;
418fab91492SRuchika Gupta 
419fab91492SRuchika Gupta 	/* Objects with PKCS11_CKA_DESTROYABLE as false aren't destroyable */
420fab91492SRuchika Gupta 	if (!get_bool(object->attributes, PKCS11_CKA_DESTROYABLE))
421fab91492SRuchika Gupta 		return PKCS11_CKR_ACTION_PROHIBITED;
422fab91492SRuchika Gupta 
423b56b3d07SJens Wiklander 	destroy_object(session, object, false);
424b56b3d07SJens Wiklander 
425b56b3d07SJens Wiklander 	DMSG("PKCS11 session %"PRIu32": destroy object %#"PRIx32,
426b56b3d07SJens Wiklander 	     session->handle, object_handle);
427b56b3d07SJens Wiklander 
428b56b3d07SJens Wiklander 	return rc;
429b56b3d07SJens Wiklander }
430*dc99b202SRuchika Gupta 
431*dc99b202SRuchika Gupta static enum pkcs11_rc token_obj_matches_ref(struct obj_attrs *req_attrs,
432*dc99b202SRuchika Gupta 					    struct pkcs11_object *obj)
433*dc99b202SRuchika Gupta {
434*dc99b202SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
435*dc99b202SRuchika Gupta 	TEE_Result res = TEE_ERROR_GENERIC;
436*dc99b202SRuchika Gupta 	TEE_ObjectHandle hdl = obj->attribs_hdl;
437*dc99b202SRuchika Gupta 	TEE_ObjectInfo info = { };
438*dc99b202SRuchika Gupta 	struct obj_attrs *attr = NULL;
439*dc99b202SRuchika Gupta 	uint32_t read_bytes = 0;
440*dc99b202SRuchika Gupta 
441*dc99b202SRuchika Gupta 	if (obj->attributes) {
442*dc99b202SRuchika Gupta 		if (!attributes_match_reference(obj->attributes, req_attrs))
443*dc99b202SRuchika Gupta 			return PKCS11_RV_NOT_FOUND;
444*dc99b202SRuchika Gupta 
445*dc99b202SRuchika Gupta 		return PKCS11_CKR_OK;
446*dc99b202SRuchika Gupta 	}
447*dc99b202SRuchika Gupta 
448*dc99b202SRuchika Gupta 	if (hdl == TEE_HANDLE_NULL) {
449*dc99b202SRuchika Gupta 		res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
450*dc99b202SRuchika Gupta 					       obj->uuid, sizeof(*obj->uuid),
451*dc99b202SRuchika Gupta 					       TEE_DATA_FLAG_ACCESS_READ,
452*dc99b202SRuchika Gupta 					       &hdl);
453*dc99b202SRuchika Gupta 		if (res) {
454*dc99b202SRuchika Gupta 			EMSG("OpenPersistent failed %#"PRIx32, res);
455*dc99b202SRuchika Gupta 			return tee2pkcs_error(res);
456*dc99b202SRuchika Gupta 		}
457*dc99b202SRuchika Gupta 	}
458*dc99b202SRuchika Gupta 
459*dc99b202SRuchika Gupta 	res = TEE_GetObjectInfo1(hdl, &info);
460*dc99b202SRuchika Gupta 	if (res) {
461*dc99b202SRuchika Gupta 		EMSG("GetObjectInfo failed %#"PRIx32, res);
462*dc99b202SRuchika Gupta 		rc = tee2pkcs_error(res);
463*dc99b202SRuchika Gupta 		goto out;
464*dc99b202SRuchika Gupta 	}
465*dc99b202SRuchika Gupta 
466*dc99b202SRuchika Gupta 	attr = TEE_Malloc(info.dataSize, TEE_MALLOC_FILL_ZERO);
467*dc99b202SRuchika Gupta 	if (!attr) {
468*dc99b202SRuchika Gupta 		rc = PKCS11_CKR_DEVICE_MEMORY;
469*dc99b202SRuchika Gupta 		goto out;
470*dc99b202SRuchika Gupta 	}
471*dc99b202SRuchika Gupta 
472*dc99b202SRuchika Gupta 	res = TEE_ReadObjectData(hdl, attr, info.dataSize, &read_bytes);
473*dc99b202SRuchika Gupta 	if (!res) {
474*dc99b202SRuchika Gupta 		res = TEE_SeekObjectData(hdl, 0, TEE_DATA_SEEK_SET);
475*dc99b202SRuchika Gupta 		if (res)
476*dc99b202SRuchika Gupta 			EMSG("Seek to 0 failed with %#"PRIx32, res);
477*dc99b202SRuchika Gupta 	}
478*dc99b202SRuchika Gupta 
479*dc99b202SRuchika Gupta 	if (res) {
480*dc99b202SRuchika Gupta 		rc = tee2pkcs_error(res);
481*dc99b202SRuchika Gupta 		EMSG("Read %"PRIu32" bytes, failed %#"PRIx32,
482*dc99b202SRuchika Gupta 		     read_bytes, res);
483*dc99b202SRuchika Gupta 		goto out;
484*dc99b202SRuchika Gupta 	}
485*dc99b202SRuchika Gupta 
486*dc99b202SRuchika Gupta 	if (read_bytes != info.dataSize) {
487*dc99b202SRuchika Gupta 		EMSG("Read %"PRIu32" bytes, expected %"PRIu32,
488*dc99b202SRuchika Gupta 		     read_bytes, info.dataSize);
489*dc99b202SRuchika Gupta 		rc = PKCS11_CKR_GENERAL_ERROR;
490*dc99b202SRuchika Gupta 		goto out;
491*dc99b202SRuchika Gupta 	}
492*dc99b202SRuchika Gupta 
493*dc99b202SRuchika Gupta 	if (!attributes_match_reference(attr, req_attrs)) {
494*dc99b202SRuchika Gupta 		rc = PKCS11_RV_NOT_FOUND;
495*dc99b202SRuchika Gupta 		goto out;
496*dc99b202SRuchika Gupta 	}
497*dc99b202SRuchika Gupta 
498*dc99b202SRuchika Gupta 	obj->attributes = attr;
499*dc99b202SRuchika Gupta 	attr = NULL;
500*dc99b202SRuchika Gupta 	obj->attribs_hdl = hdl;
501*dc99b202SRuchika Gupta 	hdl = TEE_HANDLE_NULL;
502*dc99b202SRuchika Gupta 
503*dc99b202SRuchika Gupta 	rc = PKCS11_CKR_OK;
504*dc99b202SRuchika Gupta 
505*dc99b202SRuchika Gupta out:
506*dc99b202SRuchika Gupta 	TEE_Free(attr);
507*dc99b202SRuchika Gupta 	if (obj->attribs_hdl == TEE_HANDLE_NULL)
508*dc99b202SRuchika Gupta 		TEE_CloseObject(hdl);
509*dc99b202SRuchika Gupta 
510*dc99b202SRuchika Gupta 	return rc;
511*dc99b202SRuchika Gupta }
512*dc99b202SRuchika Gupta 
513*dc99b202SRuchika Gupta static void release_find_obj_context(struct pkcs11_find_objects *find_ctx)
514*dc99b202SRuchika Gupta {
515*dc99b202SRuchika Gupta 	if (!find_ctx)
516*dc99b202SRuchika Gupta 		return;
517*dc99b202SRuchika Gupta 
518*dc99b202SRuchika Gupta 	TEE_Free(find_ctx->attributes);
519*dc99b202SRuchika Gupta 	TEE_Free(find_ctx->handles);
520*dc99b202SRuchika Gupta 	TEE_Free(find_ctx);
521*dc99b202SRuchika Gupta }
522*dc99b202SRuchika Gupta 
523*dc99b202SRuchika Gupta static enum pkcs11_rc find_ctx_add(struct pkcs11_find_objects *find_ctx,
524*dc99b202SRuchika Gupta 				   uint32_t handle)
525*dc99b202SRuchika Gupta {
526*dc99b202SRuchika Gupta 	uint32_t *hdls = TEE_Realloc(find_ctx->handles,
527*dc99b202SRuchika Gupta 				     (find_ctx->count + 1) * sizeof(*hdls));
528*dc99b202SRuchika Gupta 
529*dc99b202SRuchika Gupta 	if (!hdls)
530*dc99b202SRuchika Gupta 		return PKCS11_CKR_DEVICE_MEMORY;
531*dc99b202SRuchika Gupta 
532*dc99b202SRuchika Gupta 	find_ctx->handles = hdls;
533*dc99b202SRuchika Gupta 
534*dc99b202SRuchika Gupta 	*(find_ctx->handles + find_ctx->count) = handle;
535*dc99b202SRuchika Gupta 	find_ctx->count++;
536*dc99b202SRuchika Gupta 
537*dc99b202SRuchika Gupta 	return PKCS11_CKR_OK;
538*dc99b202SRuchika Gupta }
539*dc99b202SRuchika Gupta 
540*dc99b202SRuchika Gupta enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client,
541*dc99b202SRuchika Gupta 				       uint32_t ptypes, TEE_Param *params)
542*dc99b202SRuchika Gupta {
543*dc99b202SRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
544*dc99b202SRuchika Gupta 						TEE_PARAM_TYPE_NONE,
545*dc99b202SRuchika Gupta 						TEE_PARAM_TYPE_NONE,
546*dc99b202SRuchika Gupta 						TEE_PARAM_TYPE_NONE);
547*dc99b202SRuchika Gupta 	TEE_Param *ctrl = params;
548*dc99b202SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
549*dc99b202SRuchika Gupta 	struct serialargs ctrlargs = { };
550*dc99b202SRuchika Gupta 	struct pkcs11_session *session = NULL;
551*dc99b202SRuchika Gupta 	struct pkcs11_object_head *template = NULL;
552*dc99b202SRuchika Gupta 	struct obj_attrs *req_attrs = NULL;
553*dc99b202SRuchika Gupta 	struct pkcs11_object *obj = NULL;
554*dc99b202SRuchika Gupta 	struct pkcs11_find_objects *find_ctx = NULL;
555*dc99b202SRuchika Gupta 
556*dc99b202SRuchika Gupta 	if (!client || ptypes != exp_pt)
557*dc99b202SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
558*dc99b202SRuchika Gupta 
559*dc99b202SRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
560*dc99b202SRuchika Gupta 
561*dc99b202SRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
562*dc99b202SRuchika Gupta 	if (rc)
563*dc99b202SRuchika Gupta 		return rc;
564*dc99b202SRuchika Gupta 
565*dc99b202SRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
566*dc99b202SRuchika Gupta 	if (rc)
567*dc99b202SRuchika Gupta 		return rc;
568*dc99b202SRuchika Gupta 
569*dc99b202SRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
570*dc99b202SRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
571*dc99b202SRuchika Gupta 		goto out;
572*dc99b202SRuchika Gupta 	}
573*dc99b202SRuchika Gupta 
574*dc99b202SRuchika Gupta 	/* Search objects only if no operation is on-going */
575*dc99b202SRuchika Gupta 	if (session_is_active(session)) {
576*dc99b202SRuchika Gupta 		rc = PKCS11_CKR_OPERATION_ACTIVE;
577*dc99b202SRuchika Gupta 		goto out;
578*dc99b202SRuchika Gupta 	}
579*dc99b202SRuchika Gupta 
580*dc99b202SRuchika Gupta 	if (session->find_ctx) {
581*dc99b202SRuchika Gupta 		EMSG("Active object search already in progress");
582*dc99b202SRuchika Gupta 		rc = PKCS11_CKR_FUNCTION_FAILED;
583*dc99b202SRuchika Gupta 		goto out;
584*dc99b202SRuchika Gupta 	}
585*dc99b202SRuchika Gupta 
586*dc99b202SRuchika Gupta 	rc = sanitize_client_object(&req_attrs, template,
587*dc99b202SRuchika Gupta 				    sizeof(*template) + template->attrs_size,
588*dc99b202SRuchika Gupta 				    PKCS11_UNDEFINED_ID, PKCS11_UNDEFINED_ID);
589*dc99b202SRuchika Gupta 	if (rc)
590*dc99b202SRuchika Gupta 		goto out;
591*dc99b202SRuchika Gupta 
592*dc99b202SRuchika Gupta 	/* Must zero init the structure */
593*dc99b202SRuchika Gupta 	find_ctx = TEE_Malloc(sizeof(*find_ctx), TEE_MALLOC_FILL_ZERO);
594*dc99b202SRuchika Gupta 	if (!find_ctx) {
595*dc99b202SRuchika Gupta 		rc = PKCS11_CKR_DEVICE_MEMORY;
596*dc99b202SRuchika Gupta 		goto out;
597*dc99b202SRuchika Gupta 	}
598*dc99b202SRuchika Gupta 
599*dc99b202SRuchika Gupta 	TEE_Free(template);
600*dc99b202SRuchika Gupta 	template = NULL;
601*dc99b202SRuchika Gupta 
602*dc99b202SRuchika Gupta 	switch (get_class(req_attrs)) {
603*dc99b202SRuchika Gupta 	case PKCS11_CKO_UNDEFINED_ID:
604*dc99b202SRuchika Gupta 	/* Unspecified class searches among data objects */
605*dc99b202SRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
606*dc99b202SRuchika Gupta 	case PKCS11_CKO_PUBLIC_KEY:
607*dc99b202SRuchika Gupta 	case PKCS11_CKO_PRIVATE_KEY:
608*dc99b202SRuchika Gupta 	case PKCS11_CKO_DATA:
609*dc99b202SRuchika Gupta 		break;
610*dc99b202SRuchika Gupta 	default:
611*dc99b202SRuchika Gupta 		EMSG("Find object of class %s (%"PRIu32") is not supported",
612*dc99b202SRuchika Gupta 		     id2str_class(get_class(req_attrs)),
613*dc99b202SRuchika Gupta 		     get_class(req_attrs));
614*dc99b202SRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
615*dc99b202SRuchika Gupta 		goto out;
616*dc99b202SRuchika Gupta 	}
617*dc99b202SRuchika Gupta 
618*dc99b202SRuchika Gupta 	/*
619*dc99b202SRuchika Gupta 	 * Scan all objects (sessions and persistent ones) and set a list of
620*dc99b202SRuchika Gupta 	 * candidates that match caller attributes.
621*dc99b202SRuchika Gupta 	 */
622*dc99b202SRuchika Gupta 
623*dc99b202SRuchika Gupta 	LIST_FOREACH(obj, &session->object_list, link) {
624*dc99b202SRuchika Gupta 		if (check_access_attrs_against_token(session, obj->attributes))
625*dc99b202SRuchika Gupta 			continue;
626*dc99b202SRuchika Gupta 
627*dc99b202SRuchika Gupta 		if (req_attrs->attrs_count &&
628*dc99b202SRuchika Gupta 		    !attributes_match_reference(obj->attributes, req_attrs))
629*dc99b202SRuchika Gupta 			continue;
630*dc99b202SRuchika Gupta 
631*dc99b202SRuchika Gupta 		rc = find_ctx_add(find_ctx, pkcs11_object2handle(obj, session));
632*dc99b202SRuchika Gupta 		if (rc)
633*dc99b202SRuchika Gupta 			goto out;
634*dc99b202SRuchika Gupta 	}
635*dc99b202SRuchika Gupta 
636*dc99b202SRuchika Gupta 	LIST_FOREACH(obj, &session->token->object_list, link) {
637*dc99b202SRuchika Gupta 		uint32_t handle = 0;
638*dc99b202SRuchika Gupta 
639*dc99b202SRuchika Gupta 		if (check_access_attrs_against_token(session, obj->attributes))
640*dc99b202SRuchika Gupta 			continue;
641*dc99b202SRuchika Gupta 
642*dc99b202SRuchika Gupta 		if (req_attrs->attrs_count) {
643*dc99b202SRuchika Gupta 			rc = token_obj_matches_ref(req_attrs, obj);
644*dc99b202SRuchika Gupta 			if (rc == PKCS11_RV_NOT_FOUND)
645*dc99b202SRuchika Gupta 				continue;
646*dc99b202SRuchika Gupta 			if (rc != PKCS11_CKR_OK)
647*dc99b202SRuchika Gupta 				goto out;
648*dc99b202SRuchika Gupta 		}
649*dc99b202SRuchika Gupta 
650*dc99b202SRuchika Gupta 		/* Object may not yet be published in the session */
651*dc99b202SRuchika Gupta 		handle = pkcs11_object2handle(obj, session);
652*dc99b202SRuchika Gupta 		if (!handle) {
653*dc99b202SRuchika Gupta 			handle = handle_get(&session->object_handle_db, obj);
654*dc99b202SRuchika Gupta 			if (!handle) {
655*dc99b202SRuchika Gupta 				rc = PKCS11_CKR_DEVICE_MEMORY;
656*dc99b202SRuchika Gupta 				goto out;
657*dc99b202SRuchika Gupta 			}
658*dc99b202SRuchika Gupta 		}
659*dc99b202SRuchika Gupta 
660*dc99b202SRuchika Gupta 		rc = find_ctx_add(find_ctx, handle);
661*dc99b202SRuchika Gupta 		if (rc)
662*dc99b202SRuchika Gupta 			goto out;
663*dc99b202SRuchika Gupta 	}
664*dc99b202SRuchika Gupta 
665*dc99b202SRuchika Gupta 	find_ctx->attributes = req_attrs;
666*dc99b202SRuchika Gupta 	req_attrs = NULL;
667*dc99b202SRuchika Gupta 	session->find_ctx = find_ctx;
668*dc99b202SRuchika Gupta 	find_ctx = NULL;
669*dc99b202SRuchika Gupta 	rc = PKCS11_CKR_OK;
670*dc99b202SRuchika Gupta 
671*dc99b202SRuchika Gupta out:
672*dc99b202SRuchika Gupta 	TEE_Free(req_attrs);
673*dc99b202SRuchika Gupta 	TEE_Free(template);
674*dc99b202SRuchika Gupta 	release_find_obj_context(find_ctx);
675*dc99b202SRuchika Gupta 
676*dc99b202SRuchika Gupta 	return rc;
677*dc99b202SRuchika Gupta }
678*dc99b202SRuchika Gupta 
679*dc99b202SRuchika Gupta enum pkcs11_rc entry_find_objects(struct pkcs11_client *client,
680*dc99b202SRuchika Gupta 				  uint32_t ptypes, TEE_Param *params)
681*dc99b202SRuchika Gupta {
682*dc99b202SRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
683*dc99b202SRuchika Gupta 						TEE_PARAM_TYPE_NONE,
684*dc99b202SRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
685*dc99b202SRuchika Gupta 						TEE_PARAM_TYPE_NONE);
686*dc99b202SRuchika Gupta 	TEE_Param *ctrl = params;
687*dc99b202SRuchika Gupta 	TEE_Param *out = params + 2;
688*dc99b202SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
689*dc99b202SRuchika Gupta 	struct serialargs ctrlargs = { };
690*dc99b202SRuchika Gupta 	struct pkcs11_session *session = NULL;
691*dc99b202SRuchika Gupta 	struct pkcs11_find_objects *ctx = NULL;
692*dc99b202SRuchika Gupta 	uint8_t *out_handles = NULL;
693*dc99b202SRuchika Gupta 	size_t out_count = 0;
694*dc99b202SRuchika Gupta 	size_t count = 0;
695*dc99b202SRuchika Gupta 
696*dc99b202SRuchika Gupta 	if (!client || ptypes != exp_pt)
697*dc99b202SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
698*dc99b202SRuchika Gupta 
699*dc99b202SRuchika Gupta 	out_count = out->memref.size / sizeof(uint32_t);
700*dc99b202SRuchika Gupta 	out_handles = out->memref.buffer;
701*dc99b202SRuchika Gupta 
702*dc99b202SRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
703*dc99b202SRuchika Gupta 
704*dc99b202SRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
705*dc99b202SRuchika Gupta 	if (rc)
706*dc99b202SRuchika Gupta 		return rc;
707*dc99b202SRuchika Gupta 
708*dc99b202SRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs))
709*dc99b202SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
710*dc99b202SRuchika Gupta 
711*dc99b202SRuchika Gupta 	ctx = session->find_ctx;
712*dc99b202SRuchika Gupta 
713*dc99b202SRuchika Gupta 	if (!ctx)
714*dc99b202SRuchika Gupta 		return PKCS11_CKR_OPERATION_NOT_INITIALIZED;
715*dc99b202SRuchika Gupta 
716*dc99b202SRuchika Gupta 	for (count = 0; ctx->next < ctx->count && count < out_count;
717*dc99b202SRuchika Gupta 	     ctx->next++, count++)
718*dc99b202SRuchika Gupta 		TEE_MemMove(out_handles + count * sizeof(uint32_t),
719*dc99b202SRuchika Gupta 			    ctx->handles + ctx->next, sizeof(uint32_t));
720*dc99b202SRuchika Gupta 
721*dc99b202SRuchika Gupta 	/* Update output buffer according the number of handles provided */
722*dc99b202SRuchika Gupta 	out->memref.size = count * sizeof(uint32_t);
723*dc99b202SRuchika Gupta 
724*dc99b202SRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": finding objects", session->handle);
725*dc99b202SRuchika Gupta 
726*dc99b202SRuchika Gupta 	return PKCS11_CKR_OK;
727*dc99b202SRuchika Gupta }
728*dc99b202SRuchika Gupta 
729*dc99b202SRuchika Gupta void release_session_find_obj_context(struct pkcs11_session *session)
730*dc99b202SRuchika Gupta {
731*dc99b202SRuchika Gupta 	release_find_obj_context(session->find_ctx);
732*dc99b202SRuchika Gupta 	session->find_ctx = NULL;
733*dc99b202SRuchika Gupta }
734*dc99b202SRuchika Gupta 
735*dc99b202SRuchika Gupta uint32_t entry_find_objects_final(struct pkcs11_client *client,
736*dc99b202SRuchika Gupta 				  uint32_t ptypes, TEE_Param *params)
737*dc99b202SRuchika Gupta {
738*dc99b202SRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
739*dc99b202SRuchika Gupta 						TEE_PARAM_TYPE_NONE,
740*dc99b202SRuchika Gupta 						TEE_PARAM_TYPE_NONE,
741*dc99b202SRuchika Gupta 						TEE_PARAM_TYPE_NONE);
742*dc99b202SRuchika Gupta 	TEE_Param *ctrl = params;
743*dc99b202SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
744*dc99b202SRuchika Gupta 	struct serialargs ctrlargs = { };
745*dc99b202SRuchika Gupta 	struct pkcs11_session *session = NULL;
746*dc99b202SRuchika Gupta 
747*dc99b202SRuchika Gupta 	if (!client || ptypes != exp_pt)
748*dc99b202SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
749*dc99b202SRuchika Gupta 
750*dc99b202SRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
751*dc99b202SRuchika Gupta 
752*dc99b202SRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
753*dc99b202SRuchika Gupta 	if (rc)
754*dc99b202SRuchika Gupta 		return rc;
755*dc99b202SRuchika Gupta 
756*dc99b202SRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs))
757*dc99b202SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
758*dc99b202SRuchika Gupta 
759*dc99b202SRuchika Gupta 	if (!session->find_ctx)
760*dc99b202SRuchika Gupta 		return PKCS11_CKR_OPERATION_NOT_INITIALIZED;
761*dc99b202SRuchika Gupta 
762*dc99b202SRuchika Gupta 	release_session_find_obj_context(session);
763*dc99b202SRuchika Gupta 
764*dc99b202SRuchika Gupta 	return PKCS11_CKR_OK;
765*dc99b202SRuchika Gupta }
766