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
2102dbcc7eSEtienne Carriere /*
2202dbcc7eSEtienne Carriere * Temporary list used to register allocated struct pkcs11_object instances
2302dbcc7eSEtienne Carriere * so that destroy_object() can unconditionally remove the object from its
2402dbcc7eSEtienne Carriere * list, being from an object destruction request or because object creation
2502dbcc7eSEtienne Carriere * failed before being completed. Objects are moved to their target list at
2602dbcc7eSEtienne Carriere * creation completion.
2702dbcc7eSEtienne Carriere */
2802dbcc7eSEtienne Carriere LIST_HEAD(temp_obj_list, pkcs11_object) temporary_object_list =
2902dbcc7eSEtienne Carriere LIST_HEAD_INITIALIZER(temp_obj_list);
3002dbcc7eSEtienne Carriere
31bc555ee0SVesa Jääskeläinen static struct ck_token *get_session_token(void *session);
32bc555ee0SVesa Jääskeläinen
pkcs11_handle2object(uint32_t handle,struct pkcs11_session * session)33b56b3d07SJens Wiklander struct pkcs11_object *pkcs11_handle2object(uint32_t handle,
34b56b3d07SJens Wiklander struct pkcs11_session *session)
35b56b3d07SJens Wiklander {
36bc555ee0SVesa Jääskeläinen struct pkcs11_object *object = NULL;
37bc555ee0SVesa Jääskeläinen
38bc555ee0SVesa Jääskeläinen object = handle_lookup(get_object_handle_db(session), handle);
39bc555ee0SVesa Jääskeläinen if (!object)
40bc555ee0SVesa Jääskeläinen return NULL;
41bc555ee0SVesa Jääskeläinen
42bc555ee0SVesa Jääskeläinen /*
43bc555ee0SVesa Jääskeläinen * If object is session only then no extra checks are needed as session
44bc555ee0SVesa Jääskeläinen * objects has flat access control space
45bc555ee0SVesa Jääskeläinen */
46bc555ee0SVesa Jääskeläinen if (!object->token)
47bc555ee0SVesa Jääskeläinen return object;
48bc555ee0SVesa Jääskeläinen
49bc555ee0SVesa Jääskeläinen /*
50bc555ee0SVesa Jääskeläinen * Only allow access to token object if session is associated with
51bc555ee0SVesa Jääskeläinen * the token
52bc555ee0SVesa Jääskeläinen */
53bc555ee0SVesa Jääskeläinen if (object->token != get_session_token(session))
54bc555ee0SVesa Jääskeläinen return NULL;
55bc555ee0SVesa Jääskeläinen
56bc555ee0SVesa Jääskeläinen return object;
57b56b3d07SJens Wiklander }
58b56b3d07SJens Wiklander
pkcs11_object2handle(struct pkcs11_object * obj,struct pkcs11_session * session)59b56b3d07SJens Wiklander uint32_t pkcs11_object2handle(struct pkcs11_object *obj,
60b56b3d07SJens Wiklander struct pkcs11_session *session)
61b56b3d07SJens Wiklander {
62bc555ee0SVesa Jääskeläinen return handle_lookup_handle(get_object_handle_db(session), obj);
63b56b3d07SJens Wiklander }
64b56b3d07SJens Wiklander
65b56b3d07SJens Wiklander /* Currently handle pkcs11 sessions and tokens */
66b56b3d07SJens Wiklander
get_session_objects(void * session)67b56b3d07SJens Wiklander static struct object_list *get_session_objects(void *session)
68b56b3d07SJens Wiklander {
69b56b3d07SJens Wiklander /* Currently supporting only pkcs11 session */
70b56b3d07SJens Wiklander struct pkcs11_session *ck_session = session;
71b56b3d07SJens Wiklander
72b56b3d07SJens Wiklander return pkcs11_get_session_objects(ck_session);
73b56b3d07SJens Wiklander }
74b56b3d07SJens Wiklander
get_session_token(void * session)75334316feSJens Wiklander static struct ck_token *get_session_token(void *session)
76334316feSJens Wiklander {
77334316feSJens Wiklander struct pkcs11_session *ck_session = session;
78334316feSJens Wiklander
79334316feSJens Wiklander return pkcs11_session2token(ck_session);
80334316feSJens Wiklander }
81334316feSJens Wiklander
82b56b3d07SJens Wiklander /* Release resources of a non-persistent object */
cleanup_volatile_obj_ref(struct pkcs11_object * obj)83b56b3d07SJens Wiklander static void cleanup_volatile_obj_ref(struct pkcs11_object *obj)
84b56b3d07SJens Wiklander {
85b56b3d07SJens Wiklander if (!obj)
86b56b3d07SJens Wiklander return;
87b56b3d07SJens Wiklander
8876948876SMengchi Cheng LIST_REMOVE(obj, link);
8976948876SMengchi Cheng
90b56b3d07SJens Wiklander if (obj->key_handle != TEE_HANDLE_NULL)
91b56b3d07SJens Wiklander TEE_FreeTransientObject(obj->key_handle);
92b56b3d07SJens Wiklander
93b56b3d07SJens Wiklander if (obj->attribs_hdl != TEE_HANDLE_NULL)
94b56b3d07SJens Wiklander TEE_CloseObject(obj->attribs_hdl);
95b56b3d07SJens Wiklander
96b56b3d07SJens Wiklander TEE_Free(obj->attributes);
97b56b3d07SJens Wiklander TEE_Free(obj->uuid);
98b56b3d07SJens Wiklander TEE_Free(obj);
99b56b3d07SJens Wiklander }
100b56b3d07SJens Wiklander
101b56b3d07SJens Wiklander /* Release resources of a persistent object including volatile resources */
cleanup_persistent_object(struct pkcs11_object * obj,struct ck_token * token)1027f12c782SRobin van der Gracht void cleanup_persistent_object(struct pkcs11_object *obj,
103334316feSJens Wiklander struct ck_token *token)
104b56b3d07SJens Wiklander {
105334316feSJens Wiklander TEE_Result res = TEE_SUCCESS;
106334316feSJens Wiklander
107334316feSJens Wiklander if (!obj)
108334316feSJens Wiklander return;
109334316feSJens Wiklander
110334316feSJens Wiklander /* Open handle with write properties to destroy the object */
111334316feSJens Wiklander if (obj->attribs_hdl != TEE_HANDLE_NULL)
112334316feSJens Wiklander TEE_CloseObject(obj->attribs_hdl);
113334316feSJens Wiklander
114334316feSJens Wiklander res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
115334316feSJens Wiklander obj->uuid, sizeof(TEE_UUID),
116334316feSJens Wiklander TEE_DATA_FLAG_ACCESS_WRITE_META,
117334316feSJens Wiklander &obj->attribs_hdl);
118334316feSJens Wiklander if (!res)
119334316feSJens Wiklander TEE_CloseAndDeletePersistentObject1(obj->attribs_hdl);
120334316feSJens Wiklander
121334316feSJens Wiklander obj->attribs_hdl = TEE_HANDLE_NULL;
122334316feSJens Wiklander destroy_object_uuid(token, obj);
123334316feSJens Wiklander
124334316feSJens Wiklander cleanup_volatile_obj_ref(obj);
125b56b3d07SJens Wiklander }
126b56b3d07SJens Wiklander
127b56b3d07SJens Wiklander /*
128b56b3d07SJens Wiklander * destroy_object - destroy an PKCS11 TA object
129b56b3d07SJens Wiklander *
130b56b3d07SJens Wiklander * @session - session requesting object destruction
131b56b3d07SJens Wiklander * @obj - reference to the PKCS11 TA object
132b56b3d07SJens Wiklander * @session_only - true if only session object shall be destroyed
133b56b3d07SJens Wiklander */
destroy_object(struct pkcs11_session * session,struct pkcs11_object * obj,bool session_only)134b56b3d07SJens Wiklander void destroy_object(struct pkcs11_session *session, struct pkcs11_object *obj,
135b56b3d07SJens Wiklander bool session_only)
136b56b3d07SJens Wiklander {
137b56b3d07SJens Wiklander #ifdef DEBUG
138b56b3d07SJens Wiklander trace_attributes("[destroy]", obj->attributes);
139b56b3d07SJens Wiklander if (obj->uuid)
140b56b3d07SJens Wiklander MSG_RAW("[destroy] obj uuid %pUl", (void *)obj->uuid);
141b56b3d07SJens Wiklander #endif
142b56b3d07SJens Wiklander
143b56b3d07SJens Wiklander if (session_only) {
144b56b3d07SJens Wiklander /* Destroy object due to session closure */
145bc555ee0SVesa Jääskeläinen handle_put(get_object_handle_db(session),
146b56b3d07SJens Wiklander pkcs11_object2handle(obj, session));
147b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj);
148b56b3d07SJens Wiklander
149b56b3d07SJens Wiklander return;
150b56b3d07SJens Wiklander }
151b56b3d07SJens Wiklander
152b56b3d07SJens Wiklander /* Destroy target object (persistent or not) */
153b56b3d07SJens Wiklander if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
154334316feSJens Wiklander assert(obj->uuid);
155334316feSJens Wiklander /* Try twice otherwise panic! */
156334316feSJens Wiklander if (unregister_persistent_object(session->token, obj->uuid) &&
157334316feSJens Wiklander unregister_persistent_object(session->token, obj->uuid))
158b56b3d07SJens Wiklander TEE_Panic(0);
159334316feSJens Wiklander
160bc555ee0SVesa Jääskeläinen handle_put(get_object_handle_db(session),
161334316feSJens Wiklander pkcs11_object2handle(obj, session));
162334316feSJens Wiklander cleanup_persistent_object(obj, session->token);
163bb5d1825SEtienne Carriere
164bb5d1825SEtienne Carriere token_invalidate_object_handles(obj);
165b56b3d07SJens Wiklander } else {
166bc555ee0SVesa Jääskeläinen handle_put(get_object_handle_db(session),
167b56b3d07SJens Wiklander pkcs11_object2handle(obj, session));
168b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj);
169b56b3d07SJens Wiklander }
170b56b3d07SJens Wiklander }
171b56b3d07SJens Wiklander
create_obj_instance(struct obj_attrs * head,struct ck_token * token)172bc555ee0SVesa Jääskeläinen static struct pkcs11_object *create_obj_instance(struct obj_attrs *head,
173bc555ee0SVesa Jääskeläinen struct ck_token *token)
174b56b3d07SJens Wiklander {
175b56b3d07SJens Wiklander struct pkcs11_object *obj = NULL;
176b56b3d07SJens Wiklander
177b56b3d07SJens Wiklander obj = TEE_Malloc(sizeof(struct pkcs11_object), TEE_MALLOC_FILL_ZERO);
178b56b3d07SJens Wiklander if (!obj)
179b56b3d07SJens Wiklander return NULL;
180b56b3d07SJens Wiklander
181b56b3d07SJens Wiklander obj->key_handle = TEE_HANDLE_NULL;
182b56b3d07SJens Wiklander obj->attribs_hdl = TEE_HANDLE_NULL;
183b56b3d07SJens Wiklander obj->attributes = head;
184bc555ee0SVesa Jääskeläinen obj->token = token;
185b56b3d07SJens Wiklander
186b56b3d07SJens Wiklander return obj;
187b56b3d07SJens Wiklander }
188b56b3d07SJens Wiklander
create_token_object(struct obj_attrs * head,TEE_UUID * uuid,struct ck_token * token)189334316feSJens Wiklander struct pkcs11_object *create_token_object(struct obj_attrs *head,
190bc555ee0SVesa Jääskeläinen TEE_UUID *uuid,
191bc555ee0SVesa Jääskeläinen struct ck_token *token)
192334316feSJens Wiklander {
193bc555ee0SVesa Jääskeläinen struct pkcs11_object *obj = create_obj_instance(head, token);
194334316feSJens Wiklander
195334316feSJens Wiklander if (obj)
196334316feSJens Wiklander obj->uuid = uuid;
197334316feSJens Wiklander
198334316feSJens Wiklander return obj;
199334316feSJens Wiklander }
200334316feSJens Wiklander
201b56b3d07SJens Wiklander /*
202b56b3d07SJens Wiklander * create_object - create an PKCS11 TA object from its attributes and value
203b56b3d07SJens Wiklander *
204b56b3d07SJens Wiklander * @sess - session requesting object creation
205b56b3d07SJens Wiklander * @head - reference to serialized attributes
206b56b3d07SJens Wiklander * @out_handle - generated handle for the created object
207b56b3d07SJens Wiklander */
create_object(void * sess,struct obj_attrs * head,uint32_t * out_handle)208b56b3d07SJens Wiklander enum pkcs11_rc create_object(void *sess, struct obj_attrs *head,
209b56b3d07SJens Wiklander uint32_t *out_handle)
210b56b3d07SJens Wiklander {
211fde67b24SEtienne Carriere enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
212b56b3d07SJens Wiklander struct pkcs11_object *obj = NULL;
213b56b3d07SJens Wiklander struct pkcs11_session *session = (struct pkcs11_session *)sess;
214b56b3d07SJens Wiklander uint32_t obj_handle = 0;
215b56b3d07SJens Wiklander
216b56b3d07SJens Wiklander #ifdef DEBUG
217b56b3d07SJens Wiklander trace_attributes("[create]", head);
218b56b3d07SJens Wiklander #endif
219b56b3d07SJens Wiklander
220b56b3d07SJens Wiklander /*
221b56b3d07SJens Wiklander * We do not check the key attributes. At this point, key attributes
222b56b3d07SJens Wiklander * are expected consistent and reliable.
223b56b3d07SJens Wiklander */
224b56b3d07SJens Wiklander
225bc555ee0SVesa Jääskeläinen obj = create_obj_instance(head, NULL);
226b56b3d07SJens Wiklander if (!obj)
227b56b3d07SJens Wiklander return PKCS11_CKR_DEVICE_MEMORY;
228b56b3d07SJens Wiklander
22902dbcc7eSEtienne Carriere LIST_INSERT_HEAD(&temporary_object_list, obj, link);
23002dbcc7eSEtienne Carriere
231b56b3d07SJens Wiklander /* Create a handle for the object in the session database */
232bc555ee0SVesa Jääskeläinen obj_handle = handle_get(get_object_handle_db(session), obj);
233b56b3d07SJens Wiklander if (!obj_handle) {
234b56b3d07SJens Wiklander rc = PKCS11_CKR_DEVICE_MEMORY;
235b56b3d07SJens Wiklander goto err;
236b56b3d07SJens Wiklander }
237b56b3d07SJens Wiklander
238b56b3d07SJens Wiklander if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
239334316feSJens Wiklander TEE_Result res = TEE_SUCCESS;
240334316feSJens Wiklander
241334316feSJens Wiklander /*
242334316feSJens Wiklander * Get an ID for the persistent object
243334316feSJens Wiklander * Create the file
244334316feSJens Wiklander * Register the object in the persistent database
245334316feSJens Wiklander * (move the full sequence to persisent_db.c?)
246334316feSJens Wiklander */
247334316feSJens Wiklander size_t size = sizeof(struct obj_attrs) +
248334316feSJens Wiklander obj->attributes->attrs_size;
249334316feSJens Wiklander uint32_t tee_obj_flags = TEE_DATA_FLAG_ACCESS_READ |
250334316feSJens Wiklander TEE_DATA_FLAG_ACCESS_WRITE |
251334316feSJens Wiklander TEE_DATA_FLAG_ACCESS_WRITE_META;
252334316feSJens Wiklander
253334316feSJens Wiklander rc = create_object_uuid(get_session_token(session), obj);
254334316feSJens Wiklander if (rc)
255334316feSJens Wiklander goto err;
256334316feSJens Wiklander
257334316feSJens Wiklander res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
258334316feSJens Wiklander obj->uuid, sizeof(TEE_UUID),
259334316feSJens Wiklander tee_obj_flags,
260334316feSJens Wiklander TEE_HANDLE_NULL,
261334316feSJens Wiklander obj->attributes, size,
262334316feSJens Wiklander &obj->attribs_hdl);
263334316feSJens Wiklander if (res) {
264334316feSJens Wiklander rc = tee2pkcs_error(res);
265334316feSJens Wiklander goto err;
266334316feSJens Wiklander }
267334316feSJens Wiklander
268334316feSJens Wiklander rc = register_persistent_object(get_session_token(session),
269334316feSJens Wiklander obj->uuid);
270334316feSJens Wiklander if (rc)
271334316feSJens Wiklander goto err;
272334316feSJens Wiklander
2730fafe5c7SVesa Jääskeläinen TEE_CloseObject(obj->attribs_hdl);
2740fafe5c7SVesa Jääskeläinen obj->attribs_hdl = TEE_HANDLE_NULL;
2750fafe5c7SVesa Jääskeläinen
27602dbcc7eSEtienne Carriere /* Move object from temporary list to target token list */
27702dbcc7eSEtienne Carriere LIST_REMOVE(obj, link);
278334316feSJens Wiklander LIST_INSERT_HEAD(&session->token->object_list, obj, link);
279b56b3d07SJens Wiklander } else {
28002dbcc7eSEtienne Carriere /* Move object from temporary list to target session list */
28102dbcc7eSEtienne Carriere LIST_REMOVE(obj, link);
282b56b3d07SJens Wiklander LIST_INSERT_HEAD(get_session_objects(session), obj, link);
283b56b3d07SJens Wiklander }
284b56b3d07SJens Wiklander
285b56b3d07SJens Wiklander *out_handle = obj_handle;
286b56b3d07SJens Wiklander
287b56b3d07SJens Wiklander return PKCS11_CKR_OK;
288b56b3d07SJens Wiklander err:
289b56b3d07SJens Wiklander /* make sure that supplied "head" isn't freed */
290b56b3d07SJens Wiklander obj->attributes = NULL;
291bc555ee0SVesa Jääskeläinen handle_put(get_object_handle_db(session), obj_handle);
292b56b3d07SJens Wiklander if (get_bool(head, PKCS11_CKA_TOKEN))
293b56b3d07SJens Wiklander cleanup_persistent_object(obj, session->token);
294b56b3d07SJens Wiklander else
295b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj);
296b56b3d07SJens Wiklander
297b56b3d07SJens Wiklander return rc;
298b56b3d07SJens Wiklander }
299b56b3d07SJens Wiklander
entry_create_object(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)300b56b3d07SJens Wiklander enum pkcs11_rc entry_create_object(struct pkcs11_client *client,
301b56b3d07SJens Wiklander uint32_t ptypes, TEE_Param *params)
302b56b3d07SJens Wiklander {
303b56b3d07SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
304b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE,
305b56b3d07SJens Wiklander TEE_PARAM_TYPE_MEMREF_OUTPUT,
306b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE);
307b56b3d07SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
308b56b3d07SJens Wiklander TEE_Param *ctrl = params;
309b56b3d07SJens Wiklander TEE_Param *out = params + 2;
310b56b3d07SJens Wiklander struct serialargs ctrlargs = { };
311b56b3d07SJens Wiklander struct pkcs11_session *session = NULL;
312b56b3d07SJens Wiklander struct obj_attrs *head = NULL;
313b56b3d07SJens Wiklander struct pkcs11_object_head *template = NULL;
314b56b3d07SJens Wiklander size_t template_size = 0;
315b56b3d07SJens Wiklander uint32_t obj_handle = 0;
316b56b3d07SJens Wiklander
317b56b3d07SJens Wiklander /*
318b56b3d07SJens Wiklander * Collect the arguments of the request
319b56b3d07SJens Wiklander */
320b56b3d07SJens Wiklander
321b56b3d07SJens Wiklander if (!client || ptypes != exp_pt ||
322b56b3d07SJens Wiklander out->memref.size != sizeof(obj_handle))
323b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
324b56b3d07SJens Wiklander
325b56b3d07SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
326b56b3d07SJens Wiklander
32759a5257eSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
328b56b3d07SJens Wiklander if (rc)
329b56b3d07SJens Wiklander return rc;
330b56b3d07SJens Wiklander
331b56b3d07SJens Wiklander rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
332b56b3d07SJens Wiklander if (rc)
333b56b3d07SJens Wiklander return rc;
334b56b3d07SJens Wiklander
335b56b3d07SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) {
336b56b3d07SJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD;
337b56b3d07SJens Wiklander goto out;
338b56b3d07SJens Wiklander }
339b56b3d07SJens Wiklander
340b56b3d07SJens Wiklander template_size = sizeof(*template) + template->attrs_size;
341b56b3d07SJens Wiklander
342b56b3d07SJens Wiklander /*
343b56b3d07SJens Wiklander * Prepare a clean initial state for the requested object attributes.
344b56b3d07SJens Wiklander * Free temporary template once done.
345b56b3d07SJens Wiklander */
346b56b3d07SJens Wiklander rc = create_attributes_from_template(&head, template, template_size,
347b56b3d07SJens Wiklander NULL, PKCS11_FUNCTION_IMPORT,
3484cfce748SRuchika Gupta PKCS11_PROCESSING_IMPORT,
3494cfce748SRuchika Gupta PKCS11_CKO_UNDEFINED_ID);
350b56b3d07SJens Wiklander TEE_Free(template);
351b56b3d07SJens Wiklander template = NULL;
352b56b3d07SJens Wiklander if (rc)
353b56b3d07SJens Wiklander goto out;
354b56b3d07SJens Wiklander
355bcac2127SMarouene Boubakri /* Set key check value attribute */
356bcac2127SMarouene Boubakri rc = set_check_value_attr(&head);
357bcac2127SMarouene Boubakri if (rc)
358bcac2127SMarouene Boubakri goto out;
359bcac2127SMarouene Boubakri
360b56b3d07SJens Wiklander /*
361b56b3d07SJens Wiklander * Check target object attributes match target processing
362b56b3d07SJens Wiklander * Check target object attributes match token state
363b56b3d07SJens Wiklander */
364b56b3d07SJens Wiklander rc = check_created_attrs_against_processing(PKCS11_PROCESSING_IMPORT,
365b56b3d07SJens Wiklander head);
366b56b3d07SJens Wiklander if (rc)
367b56b3d07SJens Wiklander goto out;
368b56b3d07SJens Wiklander
369b56b3d07SJens Wiklander rc = check_created_attrs_against_token(session, head);
370b56b3d07SJens Wiklander if (rc)
371b56b3d07SJens Wiklander goto out;
372b56b3d07SJens Wiklander
373b68aca61SRuchika Gupta rc = check_access_attrs_against_token(session, head);
374b68aca61SRuchika Gupta if (rc)
375b68aca61SRuchika Gupta goto out;
376b68aca61SRuchika Gupta
377b56b3d07SJens Wiklander /*
378b56b3d07SJens Wiklander * At this stage the object is almost created: all its attributes are
379b56b3d07SJens Wiklander * referenced in @head, including the key value and are assumed
380b56b3d07SJens Wiklander * reliable. Now need to register it and get a handle for it.
381b56b3d07SJens Wiklander */
382b56b3d07SJens Wiklander rc = create_object(session, head, &obj_handle);
383b56b3d07SJens Wiklander if (rc)
384b56b3d07SJens Wiklander goto out;
385b56b3d07SJens Wiklander
386b56b3d07SJens Wiklander /*
387b56b3d07SJens Wiklander * Now obj_handle (through the related struct pkcs11_object
388e3737878SRuchika Gupta * instance) owns the serialized buffer that holds the object
389b56b3d07SJens Wiklander * attributes. We clear reference in head to NULL as the serializer
390b56b3d07SJens Wiklander * object is now referred from obj_handle. This allows smooth pass
391b56b3d07SJens Wiklander * through free at function exit.
392b56b3d07SJens Wiklander */
393b56b3d07SJens Wiklander head = NULL;
394b56b3d07SJens Wiklander
395b56b3d07SJens Wiklander TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
396b56b3d07SJens Wiklander out->memref.size = sizeof(obj_handle);
397b56b3d07SJens Wiklander
398b56b3d07SJens Wiklander DMSG("PKCS11 session %"PRIu32": import object %#"PRIx32,
399b56b3d07SJens Wiklander session->handle, obj_handle);
400b56b3d07SJens Wiklander
401b56b3d07SJens Wiklander out:
402b56b3d07SJens Wiklander TEE_Free(template);
403b56b3d07SJens Wiklander TEE_Free(head);
404b56b3d07SJens Wiklander
405b56b3d07SJens Wiklander return rc;
406b56b3d07SJens Wiklander }
407b56b3d07SJens Wiklander
entry_destroy_object(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)408b56b3d07SJens Wiklander enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client,
409b56b3d07SJens Wiklander uint32_t ptypes, TEE_Param *params)
410b56b3d07SJens Wiklander {
411b56b3d07SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
412b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE,
413b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE,
414b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE);
415b56b3d07SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
416b56b3d07SJens Wiklander TEE_Param *ctrl = params;
417b56b3d07SJens Wiklander struct serialargs ctrlargs = { };
418b56b3d07SJens Wiklander uint32_t object_handle = 0;
419b56b3d07SJens Wiklander struct pkcs11_session *session = NULL;
420b56b3d07SJens Wiklander struct pkcs11_object *object = NULL;
421b56b3d07SJens Wiklander
422b56b3d07SJens Wiklander if (!client || ptypes != exp_pt)
423b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
424b56b3d07SJens Wiklander
425b56b3d07SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
426b56b3d07SJens Wiklander
42759a5257eSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
428b56b3d07SJens Wiklander if (rc)
429b56b3d07SJens Wiklander return rc;
430b56b3d07SJens Wiklander
431b56b3d07SJens Wiklander rc = serialargs_get_u32(&ctrlargs, &object_handle);
432b56b3d07SJens Wiklander if (rc)
433b56b3d07SJens Wiklander return rc;
434b56b3d07SJens Wiklander
435b56b3d07SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs))
436b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
437b56b3d07SJens Wiklander
438b56b3d07SJens Wiklander object = pkcs11_handle2object(object_handle, session);
439b56b3d07SJens Wiklander if (!object)
440b56b3d07SJens Wiklander return PKCS11_CKR_OBJECT_HANDLE_INVALID;
441b56b3d07SJens Wiklander
442fab91492SRuchika Gupta /* Only session objects can be destroyed during a read-only session */
443fab91492SRuchika Gupta if (get_bool(object->attributes, PKCS11_CKA_TOKEN) &&
444fab91492SRuchika Gupta !pkcs11_session_is_read_write(session)) {
445fab91492SRuchika Gupta DMSG("Can't destroy persistent object");
446fab91492SRuchika Gupta return PKCS11_CKR_SESSION_READ_ONLY;
447fab91492SRuchika Gupta }
448fab91492SRuchika Gupta
449fab91492SRuchika Gupta /*
450fab91492SRuchika Gupta * Only public objects can be destroyed unless normal user is logged in
451fab91492SRuchika Gupta */
452fab91492SRuchika Gupta rc = check_access_attrs_against_token(session, object->attributes);
453fab91492SRuchika Gupta if (rc)
454fab91492SRuchika Gupta return PKCS11_CKR_USER_NOT_LOGGED_IN;
455fab91492SRuchika Gupta
456fab91492SRuchika Gupta /* Objects with PKCS11_CKA_DESTROYABLE as false aren't destroyable */
457fab91492SRuchika Gupta if (!get_bool(object->attributes, PKCS11_CKA_DESTROYABLE))
458fab91492SRuchika Gupta return PKCS11_CKR_ACTION_PROHIBITED;
459fab91492SRuchika Gupta
460b56b3d07SJens Wiklander destroy_object(session, object, false);
461b56b3d07SJens Wiklander
462b56b3d07SJens Wiklander DMSG("PKCS11 session %"PRIu32": destroy object %#"PRIx32,
463b56b3d07SJens Wiklander session->handle, object_handle);
464b56b3d07SJens Wiklander
465b56b3d07SJens Wiklander return rc;
466b56b3d07SJens Wiklander }
467dc99b202SRuchika Gupta
release_find_obj_context(struct pkcs11_find_objects * find_ctx)468dc99b202SRuchika Gupta static void release_find_obj_context(struct pkcs11_find_objects *find_ctx)
469dc99b202SRuchika Gupta {
470dc99b202SRuchika Gupta if (!find_ctx)
471dc99b202SRuchika Gupta return;
472dc99b202SRuchika Gupta
473dc99b202SRuchika Gupta TEE_Free(find_ctx->attributes);
474dc99b202SRuchika Gupta TEE_Free(find_ctx->handles);
475dc99b202SRuchika Gupta TEE_Free(find_ctx);
476dc99b202SRuchika Gupta }
477dc99b202SRuchika Gupta
find_ctx_add(struct pkcs11_find_objects * find_ctx,uint32_t handle)478dc99b202SRuchika Gupta static enum pkcs11_rc find_ctx_add(struct pkcs11_find_objects *find_ctx,
479dc99b202SRuchika Gupta uint32_t handle)
480dc99b202SRuchika Gupta {
481dc99b202SRuchika Gupta uint32_t *hdls = TEE_Realloc(find_ctx->handles,
482dc99b202SRuchika Gupta (find_ctx->count + 1) * sizeof(*hdls));
483dc99b202SRuchika Gupta
484dc99b202SRuchika Gupta if (!hdls)
485dc99b202SRuchika Gupta return PKCS11_CKR_DEVICE_MEMORY;
486dc99b202SRuchika Gupta
487dc99b202SRuchika Gupta find_ctx->handles = hdls;
488dc99b202SRuchika Gupta
489dc99b202SRuchika Gupta *(find_ctx->handles + find_ctx->count) = handle;
490dc99b202SRuchika Gupta find_ctx->count++;
491dc99b202SRuchika Gupta
492dc99b202SRuchika Gupta return PKCS11_CKR_OK;
493dc99b202SRuchika Gupta }
494dc99b202SRuchika Gupta
entry_find_objects_init(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)495dc99b202SRuchika Gupta enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client,
496dc99b202SRuchika Gupta uint32_t ptypes, TEE_Param *params)
497dc99b202SRuchika Gupta {
498dc99b202SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
499dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE,
500dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE,
501dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE);
502dc99b202SRuchika Gupta TEE_Param *ctrl = params;
503dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
504dc99b202SRuchika Gupta struct serialargs ctrlargs = { };
505dc99b202SRuchika Gupta struct pkcs11_session *session = NULL;
506bc555ee0SVesa Jääskeläinen struct pkcs11_session *sess = NULL;
507dc99b202SRuchika Gupta struct pkcs11_object_head *template = NULL;
508dc99b202SRuchika Gupta struct obj_attrs *req_attrs = NULL;
509dc99b202SRuchika Gupta struct pkcs11_object *obj = NULL;
510dc99b202SRuchika Gupta struct pkcs11_find_objects *find_ctx = NULL;
511bc555ee0SVesa Jääskeläinen struct handle_db *object_db = NULL;
512dc99b202SRuchika Gupta
513dc99b202SRuchika Gupta if (!client || ptypes != exp_pt)
514dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
515dc99b202SRuchika Gupta
516dc99b202SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
517dc99b202SRuchika Gupta
518dc99b202SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
519dc99b202SRuchika Gupta if (rc)
520dc99b202SRuchika Gupta return rc;
521dc99b202SRuchika Gupta
522dc99b202SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
523dc99b202SRuchika Gupta if (rc)
524dc99b202SRuchika Gupta return rc;
525dc99b202SRuchika Gupta
526dc99b202SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) {
527dc99b202SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD;
528dc99b202SRuchika Gupta goto out;
529dc99b202SRuchika Gupta }
530dc99b202SRuchika Gupta
531dc99b202SRuchika Gupta /* Search objects only if no operation is on-going */
532dc99b202SRuchika Gupta if (session_is_active(session)) {
533dc99b202SRuchika Gupta rc = PKCS11_CKR_OPERATION_ACTIVE;
534dc99b202SRuchika Gupta goto out;
535dc99b202SRuchika Gupta }
536dc99b202SRuchika Gupta
537dc99b202SRuchika Gupta if (session->find_ctx) {
538dc99b202SRuchika Gupta EMSG("Active object search already in progress");
539dc99b202SRuchika Gupta rc = PKCS11_CKR_FUNCTION_FAILED;
540dc99b202SRuchika Gupta goto out;
541dc99b202SRuchika Gupta }
542dc99b202SRuchika Gupta
543dc99b202SRuchika Gupta rc = sanitize_client_object(&req_attrs, template,
544dc99b202SRuchika Gupta sizeof(*template) + template->attrs_size,
545dc99b202SRuchika Gupta PKCS11_UNDEFINED_ID, PKCS11_UNDEFINED_ID);
546dc99b202SRuchika Gupta if (rc)
547dc99b202SRuchika Gupta goto out;
548dc99b202SRuchika Gupta
549dc99b202SRuchika Gupta /* Must zero init the structure */
550dc99b202SRuchika Gupta find_ctx = TEE_Malloc(sizeof(*find_ctx), TEE_MALLOC_FILL_ZERO);
551dc99b202SRuchika Gupta if (!find_ctx) {
552dc99b202SRuchika Gupta rc = PKCS11_CKR_DEVICE_MEMORY;
553dc99b202SRuchika Gupta goto out;
554dc99b202SRuchika Gupta }
555dc99b202SRuchika Gupta
556dc99b202SRuchika Gupta TEE_Free(template);
557dc99b202SRuchika Gupta template = NULL;
558dc99b202SRuchika Gupta
559dc99b202SRuchika Gupta switch (get_class(req_attrs)) {
560dc99b202SRuchika Gupta case PKCS11_CKO_UNDEFINED_ID:
561dc99b202SRuchika Gupta /* Unspecified class searches among data objects */
562dc99b202SRuchika Gupta case PKCS11_CKO_SECRET_KEY:
563dc99b202SRuchika Gupta case PKCS11_CKO_PUBLIC_KEY:
564dc99b202SRuchika Gupta case PKCS11_CKO_PRIVATE_KEY:
565dc99b202SRuchika Gupta case PKCS11_CKO_DATA:
5664137952dSVesa Jääskeläinen case PKCS11_CKO_CERTIFICATE:
567dc99b202SRuchika Gupta break;
568dc99b202SRuchika Gupta default:
569dc99b202SRuchika Gupta EMSG("Find object of class %s (%"PRIu32") is not supported",
570dc99b202SRuchika Gupta id2str_class(get_class(req_attrs)),
571dc99b202SRuchika Gupta get_class(req_attrs));
572dc99b202SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD;
573dc99b202SRuchika Gupta goto out;
574dc99b202SRuchika Gupta }
575dc99b202SRuchika Gupta
576dc99b202SRuchika Gupta /*
577dc99b202SRuchika Gupta * Scan all objects (sessions and persistent ones) and set a list of
578dc99b202SRuchika Gupta * candidates that match caller attributes.
579dc99b202SRuchika Gupta */
580dc99b202SRuchika Gupta
581bc555ee0SVesa Jääskeläinen /* Scan all session objects first */
582bc555ee0SVesa Jääskeläinen TAILQ_FOREACH(sess, get_session_list(session), link) {
583bc555ee0SVesa Jääskeläinen LIST_FOREACH(obj, &sess->object_list, link) {
584bc555ee0SVesa Jääskeläinen /*
585bc555ee0SVesa Jääskeläinen * Skip all token objects as they could be from
586bc555ee0SVesa Jääskeläinen * different token which the session does not have
587bc555ee0SVesa Jääskeläinen * access
588bc555ee0SVesa Jääskeläinen */
589bc555ee0SVesa Jääskeläinen if (obj->token)
590dc99b202SRuchika Gupta continue;
591dc99b202SRuchika Gupta
592bc555ee0SVesa Jääskeläinen if (!attributes_match_reference(obj->attributes,
593bc555ee0SVesa Jääskeläinen req_attrs))
594dc99b202SRuchika Gupta continue;
595dc99b202SRuchika Gupta
596bc555ee0SVesa Jääskeläinen rc = find_ctx_add(find_ctx,
597bc555ee0SVesa Jääskeläinen pkcs11_object2handle(obj, session));
598dc99b202SRuchika Gupta if (rc)
599dc99b202SRuchika Gupta goto out;
600dc99b202SRuchika Gupta }
601bc555ee0SVesa Jääskeläinen }
602dc99b202SRuchika Gupta
603bc555ee0SVesa Jääskeläinen object_db = get_object_handle_db(session);
604bc555ee0SVesa Jääskeläinen
605bc555ee0SVesa Jääskeläinen /* Scan token objects */
606dc99b202SRuchika Gupta LIST_FOREACH(obj, &session->token->object_list, link) {
607dc99b202SRuchika Gupta uint32_t handle = 0;
608fa1ac767SRobin van der Gracht bool new_load = false;
609dc99b202SRuchika Gupta
610fa1ac767SRobin van der Gracht if (!obj->attributes) {
611fa1ac767SRobin van der Gracht rc = load_persistent_object_attributes(obj);
612b7964037SElvira Khabirova if (rc) {
613b7964037SElvira Khabirova rc = PKCS11_CKR_GENERAL_ERROR;
614b7964037SElvira Khabirova goto out;
615b7964037SElvira Khabirova }
616dc99b202SRuchika Gupta
617fa1ac767SRobin van der Gracht new_load = true;
618fa1ac767SRobin van der Gracht }
619fa1ac767SRobin van der Gracht
620fa1ac767SRobin van der Gracht if (!obj->attributes ||
621fa1ac767SRobin van der Gracht check_access_attrs_against_token(session,
622fa1ac767SRobin van der Gracht obj->attributes) ||
623fa1ac767SRobin van der Gracht !attributes_match_reference(obj->attributes, req_attrs)) {
624fa1ac767SRobin van der Gracht if (new_load)
625fa1ac767SRobin van der Gracht release_persistent_object_attributes(obj);
626fa1ac767SRobin van der Gracht
627dc99b202SRuchika Gupta continue;
628dc99b202SRuchika Gupta }
629dc99b202SRuchika Gupta
630bc555ee0SVesa Jääskeläinen /* Resolve object handle for object */
631dc99b202SRuchika Gupta handle = pkcs11_object2handle(obj, session);
632dc99b202SRuchika Gupta if (!handle) {
633bc555ee0SVesa Jääskeläinen handle = handle_get(object_db, obj);
634dc99b202SRuchika Gupta if (!handle) {
635dc99b202SRuchika Gupta rc = PKCS11_CKR_DEVICE_MEMORY;
636dc99b202SRuchika Gupta goto out;
637dc99b202SRuchika Gupta }
638dc99b202SRuchika Gupta }
639dc99b202SRuchika Gupta
640dc99b202SRuchika Gupta rc = find_ctx_add(find_ctx, handle);
641dc99b202SRuchika Gupta if (rc)
642dc99b202SRuchika Gupta goto out;
643dc99b202SRuchika Gupta }
644dc99b202SRuchika Gupta
645dc99b202SRuchika Gupta find_ctx->attributes = req_attrs;
646dc99b202SRuchika Gupta req_attrs = NULL;
647dc99b202SRuchika Gupta session->find_ctx = find_ctx;
648dc99b202SRuchika Gupta find_ctx = NULL;
649dc99b202SRuchika Gupta rc = PKCS11_CKR_OK;
650dc99b202SRuchika Gupta
651dc99b202SRuchika Gupta out:
652dc99b202SRuchika Gupta TEE_Free(req_attrs);
653dc99b202SRuchika Gupta TEE_Free(template);
654dc99b202SRuchika Gupta release_find_obj_context(find_ctx);
655dc99b202SRuchika Gupta
656dc99b202SRuchika Gupta return rc;
657dc99b202SRuchika Gupta }
658dc99b202SRuchika Gupta
entry_find_objects(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)659dc99b202SRuchika Gupta enum pkcs11_rc entry_find_objects(struct pkcs11_client *client,
660dc99b202SRuchika Gupta uint32_t ptypes, TEE_Param *params)
661dc99b202SRuchika Gupta {
662dc99b202SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
663dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE,
664dc99b202SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT,
665dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE);
666dc99b202SRuchika Gupta TEE_Param *ctrl = params;
667dc99b202SRuchika Gupta TEE_Param *out = params + 2;
668dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
669dc99b202SRuchika Gupta struct serialargs ctrlargs = { };
670dc99b202SRuchika Gupta struct pkcs11_session *session = NULL;
671dc99b202SRuchika Gupta struct pkcs11_find_objects *ctx = NULL;
672dc99b202SRuchika Gupta uint8_t *out_handles = NULL;
673dc99b202SRuchika Gupta size_t out_count = 0;
674dc99b202SRuchika Gupta size_t count = 0;
675dc99b202SRuchika Gupta
676dc99b202SRuchika Gupta if (!client || ptypes != exp_pt)
677dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
678dc99b202SRuchika Gupta
679dc99b202SRuchika Gupta out_count = out->memref.size / sizeof(uint32_t);
680dc99b202SRuchika Gupta out_handles = out->memref.buffer;
681dc99b202SRuchika Gupta
682dc99b202SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
683dc99b202SRuchika Gupta
684dc99b202SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
685dc99b202SRuchika Gupta if (rc)
686dc99b202SRuchika Gupta return rc;
687dc99b202SRuchika Gupta
688dc99b202SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs))
689dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
690dc99b202SRuchika Gupta
691dc99b202SRuchika Gupta ctx = session->find_ctx;
692dc99b202SRuchika Gupta
693dc99b202SRuchika Gupta if (!ctx)
694dc99b202SRuchika Gupta return PKCS11_CKR_OPERATION_NOT_INITIALIZED;
695dc99b202SRuchika Gupta
696dc99b202SRuchika Gupta for (count = 0; ctx->next < ctx->count && count < out_count;
697dc99b202SRuchika Gupta ctx->next++, count++)
698dc99b202SRuchika Gupta TEE_MemMove(out_handles + count * sizeof(uint32_t),
699dc99b202SRuchika Gupta ctx->handles + ctx->next, sizeof(uint32_t));
700dc99b202SRuchika Gupta
701dc99b202SRuchika Gupta /* Update output buffer according the number of handles provided */
702dc99b202SRuchika Gupta out->memref.size = count * sizeof(uint32_t);
703dc99b202SRuchika Gupta
704dc99b202SRuchika Gupta DMSG("PKCS11 session %"PRIu32": finding objects", session->handle);
705dc99b202SRuchika Gupta
706dc99b202SRuchika Gupta return PKCS11_CKR_OK;
707dc99b202SRuchika Gupta }
708dc99b202SRuchika Gupta
release_session_find_obj_context(struct pkcs11_session * session)709dc99b202SRuchika Gupta void release_session_find_obj_context(struct pkcs11_session *session)
710dc99b202SRuchika Gupta {
711dc99b202SRuchika Gupta release_find_obj_context(session->find_ctx);
712dc99b202SRuchika Gupta session->find_ctx = NULL;
713dc99b202SRuchika Gupta }
714dc99b202SRuchika Gupta
entry_find_objects_final(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)715e3737878SRuchika Gupta enum pkcs11_rc entry_find_objects_final(struct pkcs11_client *client,
716dc99b202SRuchika Gupta uint32_t ptypes, TEE_Param *params)
717dc99b202SRuchika Gupta {
718dc99b202SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
719dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE,
720dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE,
721dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE);
722dc99b202SRuchika Gupta TEE_Param *ctrl = params;
723dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
724dc99b202SRuchika Gupta struct serialargs ctrlargs = { };
725dc99b202SRuchika Gupta struct pkcs11_session *session = NULL;
726dc99b202SRuchika Gupta
727dc99b202SRuchika Gupta if (!client || ptypes != exp_pt)
728dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
729dc99b202SRuchika Gupta
730dc99b202SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
731dc99b202SRuchika Gupta
732dc99b202SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
733dc99b202SRuchika Gupta if (rc)
734dc99b202SRuchika Gupta return rc;
735dc99b202SRuchika Gupta
736dc99b202SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs))
737dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
738dc99b202SRuchika Gupta
739dc99b202SRuchika Gupta if (!session->find_ctx)
740dc99b202SRuchika Gupta return PKCS11_CKR_OPERATION_NOT_INITIALIZED;
741dc99b202SRuchika Gupta
742dc99b202SRuchika Gupta release_session_find_obj_context(session);
743dc99b202SRuchika Gupta
744dc99b202SRuchika Gupta return PKCS11_CKR_OK;
745dc99b202SRuchika Gupta }
746783c1515SRuchika Gupta
entry_get_attribute_value(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)747e3737878SRuchika Gupta enum pkcs11_rc entry_get_attribute_value(struct pkcs11_client *client,
748783c1515SRuchika Gupta uint32_t ptypes, TEE_Param *params)
749783c1515SRuchika Gupta {
750783c1515SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
751783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE,
752783c1515SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT,
753783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE);
754783c1515SRuchika Gupta TEE_Param *ctrl = params;
755783c1515SRuchika Gupta TEE_Param *out = params + 2;
756783c1515SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
757783c1515SRuchika Gupta struct serialargs ctrlargs = { };
758783c1515SRuchika Gupta struct pkcs11_session *session = NULL;
759783c1515SRuchika Gupta struct pkcs11_object_head *template = NULL;
760783c1515SRuchika Gupta struct pkcs11_object *obj = NULL;
761783c1515SRuchika Gupta uint32_t object_handle = 0;
762783c1515SRuchika Gupta char *cur = NULL;
763783c1515SRuchika Gupta size_t len = 0;
764783c1515SRuchika Gupta char *end = NULL;
765783c1515SRuchika Gupta bool attr_sensitive = 0;
766783c1515SRuchika Gupta bool attr_type_invalid = 0;
767783c1515SRuchika Gupta bool buffer_too_small = 0;
768783c1515SRuchika Gupta
769783c1515SRuchika Gupta if (!client || ptypes != exp_pt)
770783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
771783c1515SRuchika Gupta
772783c1515SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
773783c1515SRuchika Gupta
774783c1515SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
775783c1515SRuchika Gupta if (rc)
776783c1515SRuchika Gupta return rc;
777783c1515SRuchika Gupta
778783c1515SRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
779783c1515SRuchika Gupta if (rc)
780783c1515SRuchika Gupta return rc;
781783c1515SRuchika Gupta
782783c1515SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
783783c1515SRuchika Gupta if (rc)
784783c1515SRuchika Gupta return rc;
785783c1515SRuchika Gupta
786783c1515SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) {
787783c1515SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD;
788783c1515SRuchika Gupta goto out;
789783c1515SRuchika Gupta }
790783c1515SRuchika Gupta
791783c1515SRuchika Gupta obj = pkcs11_handle2object(object_handle, session);
792783c1515SRuchika Gupta if (!obj) {
793783c1515SRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
794783c1515SRuchika Gupta goto out;
795783c1515SRuchika Gupta }
796783c1515SRuchika Gupta
797783c1515SRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes);
798783c1515SRuchika Gupta if (rc) {
799783c1515SRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
800783c1515SRuchika Gupta goto out;
801783c1515SRuchika Gupta }
802783c1515SRuchika Gupta
803783c1515SRuchika Gupta /* Iterate over attributes and set their values */
804783c1515SRuchika Gupta /*
805783c1515SRuchika Gupta * 1. If the specified attribute (i.e., the attribute specified by the
806783c1515SRuchika Gupta * type field) for the object cannot be revealed because the object is
807783c1515SRuchika Gupta * sensitive or unextractable, then the ulValueLen field in that triple
808783c1515SRuchika Gupta * is modified to hold the value PKCS11_CK_UNAVAILABLE_INFORMATION.
809783c1515SRuchika Gupta *
810783c1515SRuchika Gupta * 2. Otherwise, if the specified value for the object is invalid (the
811783c1515SRuchika Gupta * object does not possess such an attribute), then the ulValueLen field
812783c1515SRuchika Gupta * in that triple is modified to hold the value
813783c1515SRuchika Gupta * PKCS11_CK_UNAVAILABLE_INFORMATION.
814783c1515SRuchika Gupta *
815783c1515SRuchika Gupta * 3. Otherwise, if the pValue field has the value NULL_PTR, then the
816783c1515SRuchika Gupta * ulValueLen field is modified to hold the exact length of the
817783c1515SRuchika Gupta * specified attribute for the object.
818783c1515SRuchika Gupta *
819783c1515SRuchika Gupta * 4. Otherwise, if the length specified in ulValueLen is large enough
820783c1515SRuchika Gupta * to hold the value of the specified attribute for the object, then
821783c1515SRuchika Gupta * that attribute is copied into the buffer located at pValue, and the
822783c1515SRuchika Gupta * ulValueLen field is modified to hold the exact length of the
823783c1515SRuchika Gupta * attribute.
824783c1515SRuchika Gupta *
825783c1515SRuchika Gupta * 5. Otherwise, the ulValueLen field is modified to hold the value
826783c1515SRuchika Gupta * PKCS11_CK_UNAVAILABLE_INFORMATION.
827783c1515SRuchika Gupta */
828783c1515SRuchika Gupta cur = (char *)template + sizeof(struct pkcs11_object_head);
829783c1515SRuchika Gupta end = cur + template->attrs_size;
830783c1515SRuchika Gupta
831783c1515SRuchika Gupta for (; cur < end; cur += len) {
832783c1515SRuchika Gupta struct pkcs11_attribute_head *cli_ref = (void *)cur;
83318cbc7a2SVesa Jääskeläinen struct pkcs11_attribute_head cli_head = { };
83418cbc7a2SVesa Jääskeläinen void *data_ptr = NULL;
835783c1515SRuchika Gupta
83618cbc7a2SVesa Jääskeläinen /* Make copy of header so that is aligned properly. */
83718cbc7a2SVesa Jääskeläinen TEE_MemMove(&cli_head, cli_ref, sizeof(cli_head));
83818cbc7a2SVesa Jääskeläinen
83918cbc7a2SVesa Jääskeläinen len = sizeof(*cli_ref) + cli_head.size;
840783c1515SRuchika Gupta
841981966bcSVesa Jääskeläinen /* Treat hidden attributes as missing attributes */
842981966bcSVesa Jääskeläinen if (attribute_is_hidden(&cli_head)) {
843981966bcSVesa Jääskeläinen cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION;
844981966bcSVesa Jääskeläinen TEE_MemMove(&cli_ref->size, &cli_head.size,
845981966bcSVesa Jääskeläinen sizeof(cli_head.size));
846981966bcSVesa Jääskeläinen attr_type_invalid = 1;
847981966bcSVesa Jääskeläinen continue;
848981966bcSVesa Jääskeläinen }
849981966bcSVesa Jääskeläinen
850372064dcSRuchika Gupta /* We don't support getting value of indirect templates */
851372064dcSRuchika Gupta if (pkcs11_attr_has_indirect_attributes(cli_head.id)) {
852372064dcSRuchika Gupta attr_type_invalid = 1;
853372064dcSRuchika Gupta continue;
854372064dcSRuchika Gupta }
855372064dcSRuchika Gupta
856783c1515SRuchika Gupta /* Check 1. */
85718cbc7a2SVesa Jääskeläinen if (!attribute_is_exportable(&cli_head, obj)) {
85818cbc7a2SVesa Jääskeläinen cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION;
85918cbc7a2SVesa Jääskeläinen TEE_MemMove(&cli_ref->size, &cli_head.size,
86018cbc7a2SVesa Jääskeläinen sizeof(cli_head.size));
861783c1515SRuchika Gupta attr_sensitive = 1;
862783c1515SRuchika Gupta continue;
863783c1515SRuchika Gupta }
864783c1515SRuchika Gupta
86518cbc7a2SVesa Jääskeläinen /* Get real data pointer from template data */
866f3178382SVesa Jääskeläinen data_ptr = cli_head.size ? cli_ref->data : NULL;
86718cbc7a2SVesa Jääskeläinen
868783c1515SRuchika Gupta /*
869783c1515SRuchika Gupta * We assume that if size is 0, pValue was NULL, so we return
870783c1515SRuchika Gupta * the size of the required buffer for it (3., 4.)
871783c1515SRuchika Gupta */
872f3178382SVesa Jääskeläinen rc = get_attribute(obj->attributes, cli_head.id, data_ptr,
87318cbc7a2SVesa Jääskeläinen &cli_head.size);
874783c1515SRuchika Gupta /* Check 2. */
875783c1515SRuchika Gupta switch (rc) {
876783c1515SRuchika Gupta case PKCS11_CKR_OK:
877783c1515SRuchika Gupta break;
878783c1515SRuchika Gupta case PKCS11_RV_NOT_FOUND:
87918cbc7a2SVesa Jääskeläinen cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION;
880783c1515SRuchika Gupta attr_type_invalid = 1;
881783c1515SRuchika Gupta break;
882783c1515SRuchika Gupta case PKCS11_CKR_BUFFER_TOO_SMALL:
883f3178382SVesa Jääskeläinen if (data_ptr)
884783c1515SRuchika Gupta buffer_too_small = 1;
885783c1515SRuchika Gupta break;
886783c1515SRuchika Gupta default:
887783c1515SRuchika Gupta rc = PKCS11_CKR_GENERAL_ERROR;
888783c1515SRuchika Gupta goto out;
889783c1515SRuchika Gupta }
89018cbc7a2SVesa Jääskeläinen
89118cbc7a2SVesa Jääskeläinen TEE_MemMove(&cli_ref->size, &cli_head.size,
89218cbc7a2SVesa Jääskeläinen sizeof(cli_head.size));
893783c1515SRuchika Gupta }
894783c1515SRuchika Gupta
895783c1515SRuchika Gupta /*
896783c1515SRuchika Gupta * If case 1 applies to any of the requested attributes, then the call
897783c1515SRuchika Gupta * should return the value CKR_ATTRIBUTE_SENSITIVE. If case 2 applies to
898783c1515SRuchika Gupta * any of the requested attributes, then the call should return the
899783c1515SRuchika Gupta * value CKR_ATTRIBUTE_TYPE_INVALID. If case 5 applies to any of the
900783c1515SRuchika Gupta * requested attributes, then the call should return the value
901783c1515SRuchika Gupta * CKR_BUFFER_TOO_SMALL. As usual, if more than one of these error codes
902783c1515SRuchika Gupta * is applicable, Cryptoki may return any of them. Only if none of them
903783c1515SRuchika Gupta * applies to any of the requested attributes will CKR_OK be returned.
904783c1515SRuchika Gupta */
905783c1515SRuchika Gupta
906783c1515SRuchika Gupta rc = PKCS11_CKR_OK;
907783c1515SRuchika Gupta if (attr_sensitive)
908783c1515SRuchika Gupta rc = PKCS11_CKR_ATTRIBUTE_SENSITIVE;
909783c1515SRuchika Gupta if (attr_type_invalid)
910783c1515SRuchika Gupta rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
911783c1515SRuchika Gupta if (buffer_too_small)
912783c1515SRuchika Gupta rc = PKCS11_CKR_BUFFER_TOO_SMALL;
913783c1515SRuchika Gupta
914783c1515SRuchika Gupta /* Move updated template to out buffer */
915783c1515SRuchika Gupta TEE_MemMove(out->memref.buffer, template, out->memref.size);
916783c1515SRuchika Gupta
917783c1515SRuchika Gupta DMSG("PKCS11 session %"PRIu32": get attributes %#"PRIx32,
918783c1515SRuchika Gupta session->handle, object_handle);
919783c1515SRuchika Gupta
920783c1515SRuchika Gupta out:
921783c1515SRuchika Gupta TEE_Free(template);
922783c1515SRuchika Gupta
923783c1515SRuchika Gupta return rc;
924783c1515SRuchika Gupta }
925783c1515SRuchika Gupta
entry_get_object_size(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)926e3737878SRuchika Gupta enum pkcs11_rc entry_get_object_size(struct pkcs11_client *client,
927783c1515SRuchika Gupta uint32_t ptypes, TEE_Param *params)
928783c1515SRuchika Gupta {
929783c1515SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
930783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE,
931783c1515SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT,
932783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE);
933783c1515SRuchika Gupta TEE_Param *ctrl = params;
934783c1515SRuchika Gupta TEE_Param *out = params + 2;
935783c1515SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
936783c1515SRuchika Gupta struct serialargs ctrlargs = { };
937783c1515SRuchika Gupta struct pkcs11_session *session = NULL;
938783c1515SRuchika Gupta uint32_t object_handle = 0;
939783c1515SRuchika Gupta struct pkcs11_object *obj = NULL;
940783c1515SRuchika Gupta uint32_t obj_size = 0;
941783c1515SRuchika Gupta
942783c1515SRuchika Gupta if (!client || ptypes != exp_pt)
943783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
944783c1515SRuchika Gupta
945783c1515SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
946783c1515SRuchika Gupta
947783c1515SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
948783c1515SRuchika Gupta if (rc)
949783c1515SRuchika Gupta return rc;
950783c1515SRuchika Gupta
951783c1515SRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
952783c1515SRuchika Gupta if (rc)
953783c1515SRuchika Gupta return rc;
954783c1515SRuchika Gupta
955783c1515SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs))
956783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
957783c1515SRuchika Gupta
958783c1515SRuchika Gupta obj = pkcs11_handle2object(object_handle, session);
959783c1515SRuchika Gupta if (!obj)
960783c1515SRuchika Gupta return PKCS11_CKR_OBJECT_HANDLE_INVALID;
961783c1515SRuchika Gupta
962783c1515SRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes);
963783c1515SRuchika Gupta if (rc)
964783c1515SRuchika Gupta return PKCS11_CKR_OBJECT_HANDLE_INVALID;
965783c1515SRuchika Gupta
966783c1515SRuchika Gupta if (out->memref.size != sizeof(uint32_t))
967783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
968783c1515SRuchika Gupta
969783c1515SRuchika Gupta obj_size = ((struct obj_attrs *)obj->attributes)->attrs_size +
970783c1515SRuchika Gupta sizeof(struct obj_attrs);
971783c1515SRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_size, sizeof(obj_size));
972783c1515SRuchika Gupta
973783c1515SRuchika Gupta return PKCS11_CKR_OK;
974783c1515SRuchika Gupta }
9752d25a9bcSRuchika Gupta
entry_set_attribute_value(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)9762d25a9bcSRuchika Gupta enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client,
9772d25a9bcSRuchika Gupta uint32_t ptypes, TEE_Param *params)
9782d25a9bcSRuchika Gupta {
9792d25a9bcSRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
9802d25a9bcSRuchika Gupta TEE_PARAM_TYPE_NONE,
9812d25a9bcSRuchika Gupta TEE_PARAM_TYPE_NONE,
9822d25a9bcSRuchika Gupta TEE_PARAM_TYPE_NONE);
9832d25a9bcSRuchika Gupta TEE_Param *ctrl = params;
9842d25a9bcSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
9852d25a9bcSRuchika Gupta struct serialargs ctrlargs = { };
9862d25a9bcSRuchika Gupta struct pkcs11_session *session = NULL;
9872d25a9bcSRuchika Gupta struct pkcs11_object_head *template = NULL;
9882d25a9bcSRuchika Gupta size_t template_size = 0;
9892d25a9bcSRuchika Gupta struct pkcs11_object *obj = NULL;
9902d25a9bcSRuchika Gupta struct obj_attrs *head = NULL;
9916959626eSEtienne Carriere struct obj_attrs *head_new = NULL;
9926959626eSEtienne Carriere struct obj_attrs *head_old = NULL;
9932d25a9bcSRuchika Gupta uint32_t object_handle = 0;
9942d25a9bcSRuchika Gupta enum processing_func function = PKCS11_FUNCTION_MODIFY;
9952d25a9bcSRuchika Gupta
9962d25a9bcSRuchika Gupta if (!client || ptypes != exp_pt)
9972d25a9bcSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
9982d25a9bcSRuchika Gupta
9992d25a9bcSRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
10002d25a9bcSRuchika Gupta
10012d25a9bcSRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
10022d25a9bcSRuchika Gupta if (rc)
10032d25a9bcSRuchika Gupta return rc;
10042d25a9bcSRuchika Gupta
10052d25a9bcSRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
10062d25a9bcSRuchika Gupta if (rc)
10072d25a9bcSRuchika Gupta return rc;
10082d25a9bcSRuchika Gupta
10092d25a9bcSRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
10102d25a9bcSRuchika Gupta if (rc)
10112d25a9bcSRuchika Gupta return rc;
10122d25a9bcSRuchika Gupta
10132d25a9bcSRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) {
10142d25a9bcSRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD;
10152d25a9bcSRuchika Gupta goto out;
10162d25a9bcSRuchika Gupta }
10172d25a9bcSRuchika Gupta
10182d25a9bcSRuchika Gupta obj = pkcs11_handle2object(object_handle, session);
10192d25a9bcSRuchika Gupta if (!obj) {
10202d25a9bcSRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
10212d25a9bcSRuchika Gupta goto out;
10222d25a9bcSRuchika Gupta }
10232d25a9bcSRuchika Gupta
10242d25a9bcSRuchika Gupta /* Only session objects can be modified during a read-only session */
10252d25a9bcSRuchika Gupta if (object_is_token(obj->attributes) &&
10262d25a9bcSRuchika Gupta !pkcs11_session_is_read_write(session)) {
10272d25a9bcSRuchika Gupta DMSG("Can't modify persistent object in a RO session");
10282d25a9bcSRuchika Gupta rc = PKCS11_CKR_SESSION_READ_ONLY;
10292d25a9bcSRuchika Gupta goto out;
10302d25a9bcSRuchika Gupta }
10312d25a9bcSRuchika Gupta
10322d25a9bcSRuchika Gupta /*
10332d25a9bcSRuchika Gupta * Only public objects can be modified unless normal user is logged in
10342d25a9bcSRuchika Gupta */
10352d25a9bcSRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes);
10362d25a9bcSRuchika Gupta if (rc) {
10372d25a9bcSRuchika Gupta rc = PKCS11_CKR_USER_NOT_LOGGED_IN;
10382d25a9bcSRuchika Gupta goto out;
10392d25a9bcSRuchika Gupta }
10402d25a9bcSRuchika Gupta
10412d25a9bcSRuchika Gupta /* Objects with PKCS11_CKA_MODIFIABLE as false aren't modifiable */
10422d25a9bcSRuchika Gupta if (!object_is_modifiable(obj->attributes)) {
10432d25a9bcSRuchika Gupta rc = PKCS11_CKR_ACTION_PROHIBITED;
10442d25a9bcSRuchika Gupta goto out;
10452d25a9bcSRuchika Gupta }
10462d25a9bcSRuchika Gupta
10472d25a9bcSRuchika Gupta template_size = sizeof(*template) + template->attrs_size;
10482d25a9bcSRuchika Gupta
10492d25a9bcSRuchika Gupta /*
10502d25a9bcSRuchika Gupta * Prepare a clean initial state (@head) for the template. Helps in
10512d25a9bcSRuchika Gupta * removing any duplicates or inconsistent values from the
10522d25a9bcSRuchika Gupta * template.
10532d25a9bcSRuchika Gupta */
10542d25a9bcSRuchika Gupta rc = create_attributes_from_template(&head, template, template_size,
10552d25a9bcSRuchika Gupta NULL, function,
10562d25a9bcSRuchika Gupta PKCS11_CKM_UNDEFINED_ID,
10572d25a9bcSRuchika Gupta PKCS11_CKO_UNDEFINED_ID);
10582d25a9bcSRuchika Gupta if (rc)
10592d25a9bcSRuchika Gupta goto out;
10602d25a9bcSRuchika Gupta
10612d25a9bcSRuchika Gupta /* Check the attributes in @head to see if they are modifiable */
10622d25a9bcSRuchika Gupta rc = check_attrs_against_modification(session, head, obj, function);
10632d25a9bcSRuchika Gupta if (rc)
10642d25a9bcSRuchika Gupta goto out;
10652d25a9bcSRuchika Gupta
10666959626eSEtienne Carriere /* Create new object attributes to modify */
10676959626eSEtienne Carriere template_size = sizeof(*obj->attributes) + obj->attributes->attrs_size;
10686959626eSEtienne Carriere head_new = TEE_Malloc(template_size, TEE_MALLOC_FILL_ZERO);
10696959626eSEtienne Carriere if (!head_new) {
10706959626eSEtienne Carriere rc = PKCS11_CKR_DEVICE_MEMORY;
10716959626eSEtienne Carriere goto out;
10726959626eSEtienne Carriere }
10736959626eSEtienne Carriere
10746959626eSEtienne Carriere TEE_MemMove(head_new, obj->attributes, template_size);
10756959626eSEtienne Carriere
10762d25a9bcSRuchika Gupta /*
10772d25a9bcSRuchika Gupta * All checks complete. The attributes in @head have been checked and
10782d25a9bcSRuchika Gupta * can now be used to set/modify the object attributes.
10792d25a9bcSRuchika Gupta */
10806959626eSEtienne Carriere rc = modify_attributes_list(&head_new, head);
10812d25a9bcSRuchika Gupta if (rc)
10822d25a9bcSRuchika Gupta goto out;
10832d25a9bcSRuchika Gupta
1084bcac2127SMarouene Boubakri /* Set key check value attribute */
10856959626eSEtienne Carriere rc = set_check_value_attr(&head_new);
1086bcac2127SMarouene Boubakri if (rc)
1087bcac2127SMarouene Boubakri goto out;
1088bcac2127SMarouene Boubakri
10896959626eSEtienne Carriere /* Update the object */
10906959626eSEtienne Carriere head_old = obj->attributes;
10916959626eSEtienne Carriere obj->attributes = head_new;
10926959626eSEtienne Carriere head_new = NULL;
10936959626eSEtienne Carriere
1094402d884aSRuchika Gupta if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
1095402d884aSRuchika Gupta rc = update_persistent_object_attributes(obj);
10966959626eSEtienne Carriere if (rc) {
1097*55a4d839SGeorges Savoundararadj TEE_Free(obj->attributes);
10986959626eSEtienne Carriere obj->attributes = head_old;
1099402d884aSRuchika Gupta goto out;
1100402d884aSRuchika Gupta }
11016959626eSEtienne Carriere }
11026959626eSEtienne Carriere
11036959626eSEtienne Carriere TEE_Free(head_old);
1104402d884aSRuchika Gupta
11052d25a9bcSRuchika Gupta DMSG("PKCS11 session %"PRIu32": set attributes %#"PRIx32,
11062d25a9bcSRuchika Gupta session->handle, object_handle);
11072d25a9bcSRuchika Gupta
11082d25a9bcSRuchika Gupta out:
11092d25a9bcSRuchika Gupta TEE_Free(head);
11106959626eSEtienne Carriere TEE_Free(head_new);
11112d25a9bcSRuchika Gupta TEE_Free(template);
11122d25a9bcSRuchika Gupta return rc;
11132d25a9bcSRuchika Gupta }
1114bc09507cSRuchika Gupta
entry_copy_object(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)1115bc09507cSRuchika Gupta enum pkcs11_rc entry_copy_object(struct pkcs11_client *client, uint32_t ptypes,
1116bc09507cSRuchika Gupta TEE_Param *params)
1117bc09507cSRuchika Gupta {
1118bc09507cSRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1119bc09507cSRuchika Gupta TEE_PARAM_TYPE_NONE,
1120bc09507cSRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT,
1121bc09507cSRuchika Gupta TEE_PARAM_TYPE_NONE);
1122bc09507cSRuchika Gupta TEE_Param *ctrl = params;
1123bc09507cSRuchika Gupta TEE_Param *out = params + 2;
1124bc09507cSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1125bc09507cSRuchika Gupta struct serialargs ctrlargs = { };
1126bc09507cSRuchika Gupta struct pkcs11_session *session = NULL;
1127bc09507cSRuchika Gupta struct pkcs11_object_head *template = NULL;
1128bc09507cSRuchika Gupta struct obj_attrs *head = NULL;
1129bc09507cSRuchika Gupta struct obj_attrs *head_new = NULL;
1130bc09507cSRuchika Gupta size_t template_size = 0;
1131bc09507cSRuchika Gupta struct pkcs11_object *obj = NULL;
1132bc09507cSRuchika Gupta uint32_t object_handle = 0;
1133bc09507cSRuchika Gupta uint32_t obj_handle = 0;
1134bc09507cSRuchika Gupta enum processing_func function = PKCS11_FUNCTION_COPY;
1135bc09507cSRuchika Gupta enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID;
1136bc09507cSRuchika Gupta
1137bc09507cSRuchika Gupta if (!client || ptypes != exp_pt ||
1138bc09507cSRuchika Gupta out->memref.size != sizeof(obj_handle))
1139bc09507cSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
1140bc09507cSRuchika Gupta
1141bc09507cSRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1142bc09507cSRuchika Gupta
1143bc09507cSRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1144bc09507cSRuchika Gupta if (rc)
1145bc09507cSRuchika Gupta return rc;
1146bc09507cSRuchika Gupta
1147bc09507cSRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
1148bc09507cSRuchika Gupta if (rc)
1149bc09507cSRuchika Gupta return rc;
1150bc09507cSRuchika Gupta
1151bc09507cSRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
1152bc09507cSRuchika Gupta if (rc)
1153bc09507cSRuchika Gupta return rc;
1154bc09507cSRuchika Gupta
1155bc09507cSRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) {
1156bc09507cSRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD;
1157bc09507cSRuchika Gupta goto out;
1158bc09507cSRuchika Gupta }
1159bc09507cSRuchika Gupta
1160bc09507cSRuchika Gupta obj = pkcs11_handle2object(object_handle, session);
1161bc09507cSRuchika Gupta if (!obj) {
1162bc09507cSRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
1163bc09507cSRuchika Gupta goto out;
1164bc09507cSRuchika Gupta }
1165bc09507cSRuchika Gupta
1166bc09507cSRuchika Gupta /* Only session objects can be modified during a read-only session */
1167bc09507cSRuchika Gupta if (object_is_token(obj->attributes) &&
1168bc09507cSRuchika Gupta !pkcs11_session_is_read_write(session)) {
1169bc09507cSRuchika Gupta DMSG("Can't modify persistent object in a RO session");
1170bc09507cSRuchika Gupta rc = PKCS11_CKR_SESSION_READ_ONLY;
1171bc09507cSRuchika Gupta goto out;
1172bc09507cSRuchika Gupta }
1173bc09507cSRuchika Gupta
1174bc09507cSRuchika Gupta /*
1175bc09507cSRuchika Gupta * Only public objects can be modified unless normal user is logged in
1176bc09507cSRuchika Gupta */
1177bc09507cSRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes);
1178bc09507cSRuchika Gupta if (rc) {
1179bc09507cSRuchika Gupta rc = PKCS11_CKR_USER_NOT_LOGGED_IN;
1180bc09507cSRuchika Gupta goto out;
1181bc09507cSRuchika Gupta }
1182bc09507cSRuchika Gupta
1183bc09507cSRuchika Gupta /* Objects with PKCS11_CKA_COPYABLE as false can't be copied */
1184bc09507cSRuchika Gupta if (!object_is_copyable(obj->attributes)) {
1185bc09507cSRuchika Gupta rc = PKCS11_CKR_ACTION_PROHIBITED;
1186bc09507cSRuchika Gupta goto out;
1187bc09507cSRuchika Gupta }
1188bc09507cSRuchika Gupta
1189bc09507cSRuchika Gupta template_size = sizeof(*template) + template->attrs_size;
1190bc09507cSRuchika Gupta
1191bc09507cSRuchika Gupta /*
1192bc09507cSRuchika Gupta * Prepare a clean initial state (@head) for the template. Helps in
1193bc09507cSRuchika Gupta * removing any duplicates or inconsistent values from the
1194bc09507cSRuchika Gupta * template.
1195bc09507cSRuchika Gupta */
1196bc09507cSRuchika Gupta rc = create_attributes_from_template(&head, template, template_size,
1197bc09507cSRuchika Gupta NULL, function,
1198bc09507cSRuchika Gupta PKCS11_CKM_UNDEFINED_ID,
1199bc09507cSRuchika Gupta PKCS11_CKO_UNDEFINED_ID);
1200bc09507cSRuchika Gupta if (rc)
1201bc09507cSRuchika Gupta goto out;
1202bc09507cSRuchika Gupta
1203bc09507cSRuchika Gupta /* Check the attributes in @head to see if they are modifiable */
1204bc09507cSRuchika Gupta rc = check_attrs_against_modification(session, head, obj, function);
1205bc09507cSRuchika Gupta if (rc)
1206bc09507cSRuchika Gupta goto out;
1207bc09507cSRuchika Gupta
1208bc09507cSRuchika Gupta class = get_class(obj->attributes);
1209bc09507cSRuchika Gupta
1210bc09507cSRuchika Gupta if (class == PKCS11_CKO_SECRET_KEY ||
1211bc09507cSRuchika Gupta class == PKCS11_CKO_PRIVATE_KEY) {
1212bc09507cSRuchika Gupta /*
1213bc09507cSRuchika Gupta * If CKA_EXTRACTABLE attribute in passed template (@head) is
1214bc09507cSRuchika Gupta * modified to CKA_FALSE, CKA_NEVER_EXTRACTABLE should also
1215bc09507cSRuchika Gupta * change to CKA_FALSE in copied obj. So, add it to the
1216bc09507cSRuchika Gupta * passed template.
1217bc09507cSRuchika Gupta */
1218bc09507cSRuchika Gupta uint8_t bbool = 0;
1219bc09507cSRuchika Gupta uint32_t size = sizeof(bbool);
1220bc09507cSRuchika Gupta
1221bc09507cSRuchika Gupta rc = get_attribute(head, PKCS11_CKA_EXTRACTABLE, &bbool, &size);
1222bc09507cSRuchika Gupta if (!rc && !bbool) {
1223bc09507cSRuchika Gupta rc = add_attribute(&head, PKCS11_CKA_NEVER_EXTRACTABLE,
1224bc09507cSRuchika Gupta &bbool, sizeof(uint8_t));
1225bc09507cSRuchika Gupta if (rc)
1226bc09507cSRuchika Gupta goto out;
1227bc09507cSRuchika Gupta }
1228bc09507cSRuchika Gupta rc = PKCS11_CKR_OK;
1229bc09507cSRuchika Gupta }
1230bc09507cSRuchika Gupta
1231bc09507cSRuchika Gupta /*
1232bc09507cSRuchika Gupta * All checks have passed. Create a copy of the serialized buffer which
1233bc09507cSRuchika Gupta * holds the object attributes in @head_new for the new object
1234bc09507cSRuchika Gupta */
1235bc09507cSRuchika Gupta template_size = sizeof(*obj->attributes) + obj->attributes->attrs_size;
1236bc09507cSRuchika Gupta head_new = TEE_Malloc(template_size, TEE_MALLOC_FILL_ZERO);
1237bc09507cSRuchika Gupta if (!head_new) {
1238bc09507cSRuchika Gupta rc = PKCS11_CKR_DEVICE_MEMORY;
1239bc09507cSRuchika Gupta goto out;
1240bc09507cSRuchika Gupta }
1241bc09507cSRuchika Gupta
1242bc09507cSRuchika Gupta TEE_MemMove(head_new, obj->attributes, template_size);
1243bc09507cSRuchika Gupta
1244bc09507cSRuchika Gupta /*
1245bc09507cSRuchika Gupta * Modify the copied attribute @head_new based on the template @head
1246bc09507cSRuchika Gupta * given by the callee
1247bc09507cSRuchika Gupta */
1248bc09507cSRuchika Gupta rc = modify_attributes_list(&head_new, head);
1249bc09507cSRuchika Gupta if (rc)
1250bc09507cSRuchika Gupta goto out;
1251bc09507cSRuchika Gupta
1252bcac2127SMarouene Boubakri /* Set key check value attribute */
1253bcac2127SMarouene Boubakri rc = set_check_value_attr(&head_new);
1254bcac2127SMarouene Boubakri if (rc)
1255bcac2127SMarouene Boubakri goto out;
1256bcac2127SMarouene Boubakri
1257bc09507cSRuchika Gupta /*
1258bc09507cSRuchika Gupta * At this stage the object is almost created: all its attributes are
1259bc09507cSRuchika Gupta * referenced in @head_new, including the key value and are assumed
1260bc09507cSRuchika Gupta * reliable. Now need to register it and get a handle for it.
1261bc09507cSRuchika Gupta */
1262bc09507cSRuchika Gupta rc = create_object(session, head_new, &obj_handle);
1263bc09507cSRuchika Gupta if (rc)
1264bc09507cSRuchika Gupta goto out;
1265bc09507cSRuchika Gupta
1266bc09507cSRuchika Gupta /*
1267bc09507cSRuchika Gupta * Now obj_handle (through the related struct pkcs11_object
1268e3737878SRuchika Gupta * instance) owns the serialized buffer that holds the object
1269bc09507cSRuchika Gupta * attributes. We clear reference in head to NULL as the serializer
1270bc09507cSRuchika Gupta * object is now referred from obj_handle. This allows smooth pass
1271bc09507cSRuchika Gupta * through free at function exit.
1272bc09507cSRuchika Gupta */
1273bc09507cSRuchika Gupta head_new = NULL;
1274bc09507cSRuchika Gupta
1275bc09507cSRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
1276bc09507cSRuchika Gupta out->memref.size = sizeof(obj_handle);
1277bc09507cSRuchika Gupta
1278bc09507cSRuchika Gupta DMSG("PKCS11 session %"PRIu32": copy object %#"PRIx32,
1279bc09507cSRuchika Gupta session->handle, obj_handle);
1280bc09507cSRuchika Gupta
1281bc09507cSRuchika Gupta out:
1282bc09507cSRuchika Gupta TEE_Free(head_new);
1283bc09507cSRuchika Gupta TEE_Free(head);
1284bc09507cSRuchika Gupta TEE_Free(template);
1285bc09507cSRuchika Gupta return rc;
1286bc09507cSRuchika Gupta }
1287