xref: /optee_os/ta/pkcs11/src/object.c (revision b56b3d071d79537f0b9c86d26c033d9ed5c0206a)
1*b56b3d07SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*b56b3d07SJens Wiklander /*
3*b56b3d07SJens Wiklander  * Copyright (c) 2017-2020, Linaro Limited
4*b56b3d07SJens Wiklander  */
5*b56b3d07SJens Wiklander 
6*b56b3d07SJens Wiklander #include <assert.h>
7*b56b3d07SJens Wiklander #include <inttypes.h>
8*b56b3d07SJens Wiklander #include <string_ext.h>
9*b56b3d07SJens Wiklander #include <tee_internal_api.h>
10*b56b3d07SJens Wiklander #include <tee_internal_api_extensions.h>
11*b56b3d07SJens Wiklander 
12*b56b3d07SJens Wiklander #include "attributes.h"
13*b56b3d07SJens Wiklander #include "handle.h"
14*b56b3d07SJens Wiklander #include "object.h"
15*b56b3d07SJens Wiklander #include "pkcs11_attributes.h"
16*b56b3d07SJens Wiklander #include "pkcs11_helpers.h"
17*b56b3d07SJens Wiklander #include "pkcs11_token.h"
18*b56b3d07SJens Wiklander #include "sanitize_object.h"
19*b56b3d07SJens Wiklander #include "serializer.h"
20*b56b3d07SJens Wiklander 
21*b56b3d07SJens Wiklander struct pkcs11_object *pkcs11_handle2object(uint32_t handle,
22*b56b3d07SJens Wiklander 					   struct pkcs11_session *session)
23*b56b3d07SJens Wiklander {
24*b56b3d07SJens Wiklander 	return handle_lookup(&session->object_handle_db, handle);
25*b56b3d07SJens Wiklander }
26*b56b3d07SJens Wiklander 
27*b56b3d07SJens Wiklander uint32_t pkcs11_object2handle(struct pkcs11_object *obj,
28*b56b3d07SJens Wiklander 			      struct pkcs11_session *session)
29*b56b3d07SJens Wiklander {
30*b56b3d07SJens Wiklander 	return handle_lookup_handle(&session->object_handle_db, obj);
31*b56b3d07SJens Wiklander }
32*b56b3d07SJens Wiklander 
33*b56b3d07SJens Wiklander /* Currently handle pkcs11 sessions and tokens */
34*b56b3d07SJens Wiklander 
35*b56b3d07SJens Wiklander static struct object_list *get_session_objects(void *session)
36*b56b3d07SJens Wiklander {
37*b56b3d07SJens Wiklander 	/* Currently supporting only pkcs11 session */
38*b56b3d07SJens Wiklander 	struct pkcs11_session *ck_session = session;
39*b56b3d07SJens Wiklander 
40*b56b3d07SJens Wiklander 	return pkcs11_get_session_objects(ck_session);
41*b56b3d07SJens Wiklander }
42*b56b3d07SJens Wiklander 
43*b56b3d07SJens Wiklander /* Release resources of a non-persistent object */
44*b56b3d07SJens Wiklander static void cleanup_volatile_obj_ref(struct pkcs11_object *obj)
45*b56b3d07SJens Wiklander {
46*b56b3d07SJens Wiklander 	if (!obj)
47*b56b3d07SJens Wiklander 		return;
48*b56b3d07SJens Wiklander 
49*b56b3d07SJens Wiklander 	if (obj->key_handle != TEE_HANDLE_NULL)
50*b56b3d07SJens Wiklander 		TEE_FreeTransientObject(obj->key_handle);
51*b56b3d07SJens Wiklander 
52*b56b3d07SJens Wiklander 	if (obj->attribs_hdl != TEE_HANDLE_NULL)
53*b56b3d07SJens Wiklander 		TEE_CloseObject(obj->attribs_hdl);
54*b56b3d07SJens Wiklander 
55*b56b3d07SJens Wiklander 	TEE_Free(obj->attributes);
56*b56b3d07SJens Wiklander 	TEE_Free(obj->uuid);
57*b56b3d07SJens Wiklander 	TEE_Free(obj);
58*b56b3d07SJens Wiklander }
59*b56b3d07SJens Wiklander 
60*b56b3d07SJens Wiklander /* Release resources of a persistent object including volatile resources */
61*b56b3d07SJens Wiklander static void cleanup_persistent_object(struct pkcs11_object *obj __unused,
62*b56b3d07SJens Wiklander 				      struct ck_token *token __unused)
63*b56b3d07SJens Wiklander {
64*b56b3d07SJens Wiklander 	EMSG("Persistent object not yet supported, panic!");
65*b56b3d07SJens Wiklander 	TEE_Panic(0);
66*b56b3d07SJens Wiklander }
67*b56b3d07SJens Wiklander 
68*b56b3d07SJens Wiklander /*
69*b56b3d07SJens Wiklander  * destroy_object - destroy an PKCS11 TA object
70*b56b3d07SJens Wiklander  *
71*b56b3d07SJens Wiklander  * @session - session requesting object destruction
72*b56b3d07SJens Wiklander  * @obj - reference to the PKCS11 TA object
73*b56b3d07SJens Wiklander  * @session_only - true if only session object shall be destroyed
74*b56b3d07SJens Wiklander  */
75*b56b3d07SJens Wiklander void destroy_object(struct pkcs11_session *session, struct pkcs11_object *obj,
76*b56b3d07SJens Wiklander 		    bool session_only)
77*b56b3d07SJens Wiklander {
78*b56b3d07SJens Wiklander #ifdef DEBUG
79*b56b3d07SJens Wiklander 	trace_attributes("[destroy]", obj->attributes);
80*b56b3d07SJens Wiklander 	if (obj->uuid)
81*b56b3d07SJens Wiklander 		MSG_RAW("[destroy] obj uuid %pUl", (void *)obj->uuid);
82*b56b3d07SJens Wiklander #endif
83*b56b3d07SJens Wiklander 
84*b56b3d07SJens Wiklander 	/*
85*b56b3d07SJens Wiklander 	 * Remove from session list only if it was published.
86*b56b3d07SJens Wiklander 	 *
87*b56b3d07SJens Wiklander 	 * This depends on obj->link.le_prev always pointing on the
88*b56b3d07SJens Wiklander 	 * link.le_next element in the previous object in the list even if
89*b56b3d07SJens Wiklander 	 * there's only a single object in the list. In the first object in
90*b56b3d07SJens Wiklander 	 * the list obj->link.le_prev instead points to lh_first in the
91*b56b3d07SJens Wiklander 	 * list head. If list implementation is changed we need to revisit
92*b56b3d07SJens Wiklander 	 * this.
93*b56b3d07SJens Wiklander 	 */
94*b56b3d07SJens Wiklander 	if (obj->link.le_next || obj->link.le_prev)
95*b56b3d07SJens Wiklander 		LIST_REMOVE(obj, link);
96*b56b3d07SJens Wiklander 
97*b56b3d07SJens Wiklander 	if (session_only) {
98*b56b3d07SJens Wiklander 		/* Destroy object due to session closure */
99*b56b3d07SJens Wiklander 		handle_put(&session->object_handle_db,
100*b56b3d07SJens Wiklander 			   pkcs11_object2handle(obj, session));
101*b56b3d07SJens Wiklander 		cleanup_volatile_obj_ref(obj);
102*b56b3d07SJens Wiklander 
103*b56b3d07SJens Wiklander 		return;
104*b56b3d07SJens Wiklander 	}
105*b56b3d07SJens Wiklander 
106*b56b3d07SJens Wiklander 	/* Destroy target object (persistent or not) */
107*b56b3d07SJens Wiklander 	if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
108*b56b3d07SJens Wiklander 		EMSG("Persistent object not yet supported, panic!");
109*b56b3d07SJens Wiklander 		TEE_Panic(0);
110*b56b3d07SJens Wiklander 	} else {
111*b56b3d07SJens Wiklander 		handle_put(&session->object_handle_db,
112*b56b3d07SJens Wiklander 			   pkcs11_object2handle(obj, session));
113*b56b3d07SJens Wiklander 		cleanup_volatile_obj_ref(obj);
114*b56b3d07SJens Wiklander 	}
115*b56b3d07SJens Wiklander }
116*b56b3d07SJens Wiklander 
117*b56b3d07SJens Wiklander static struct pkcs11_object *create_obj_instance(struct obj_attrs *head)
118*b56b3d07SJens Wiklander {
119*b56b3d07SJens Wiklander 	struct pkcs11_object *obj = NULL;
120*b56b3d07SJens Wiklander 
121*b56b3d07SJens Wiklander 	obj = TEE_Malloc(sizeof(struct pkcs11_object), TEE_MALLOC_FILL_ZERO);
122*b56b3d07SJens Wiklander 	if (!obj)
123*b56b3d07SJens Wiklander 		return NULL;
124*b56b3d07SJens Wiklander 
125*b56b3d07SJens Wiklander 	obj->key_handle = TEE_HANDLE_NULL;
126*b56b3d07SJens Wiklander 	obj->attribs_hdl = TEE_HANDLE_NULL;
127*b56b3d07SJens Wiklander 	obj->attributes = head;
128*b56b3d07SJens Wiklander 
129*b56b3d07SJens Wiklander 	return obj;
130*b56b3d07SJens Wiklander }
131*b56b3d07SJens Wiklander 
132*b56b3d07SJens Wiklander /*
133*b56b3d07SJens Wiklander  * create_object - create an PKCS11 TA object from its attributes and value
134*b56b3d07SJens Wiklander  *
135*b56b3d07SJens Wiklander  * @sess - session requesting object creation
136*b56b3d07SJens Wiklander  * @head - reference to serialized attributes
137*b56b3d07SJens Wiklander  * @out_handle - generated handle for the created object
138*b56b3d07SJens Wiklander  */
139*b56b3d07SJens Wiklander enum pkcs11_rc create_object(void *sess, struct obj_attrs *head,
140*b56b3d07SJens Wiklander 			     uint32_t *out_handle)
141*b56b3d07SJens Wiklander {
142*b56b3d07SJens Wiklander 	enum pkcs11_rc rc = 0;
143*b56b3d07SJens Wiklander 	struct pkcs11_object *obj = NULL;
144*b56b3d07SJens Wiklander 	struct pkcs11_session *session = (struct pkcs11_session *)sess;
145*b56b3d07SJens Wiklander 	uint32_t obj_handle = 0;
146*b56b3d07SJens Wiklander 
147*b56b3d07SJens Wiklander #ifdef DEBUG
148*b56b3d07SJens Wiklander 	trace_attributes("[create]", head);
149*b56b3d07SJens Wiklander #endif
150*b56b3d07SJens Wiklander 
151*b56b3d07SJens Wiklander 	/*
152*b56b3d07SJens Wiklander 	 * We do not check the key attributes. At this point, key attributes
153*b56b3d07SJens Wiklander 	 * are expected consistent and reliable.
154*b56b3d07SJens Wiklander 	 */
155*b56b3d07SJens Wiklander 
156*b56b3d07SJens Wiklander 	obj = create_obj_instance(head);
157*b56b3d07SJens Wiklander 	if (!obj)
158*b56b3d07SJens Wiklander 		return PKCS11_CKR_DEVICE_MEMORY;
159*b56b3d07SJens Wiklander 
160*b56b3d07SJens Wiklander 	/* Create a handle for the object in the session database */
161*b56b3d07SJens Wiklander 	obj_handle = handle_get(&session->object_handle_db, obj);
162*b56b3d07SJens Wiklander 	if (!obj_handle) {
163*b56b3d07SJens Wiklander 		rc = PKCS11_CKR_DEVICE_MEMORY;
164*b56b3d07SJens Wiklander 		goto err;
165*b56b3d07SJens Wiklander 	}
166*b56b3d07SJens Wiklander 
167*b56b3d07SJens Wiklander 	if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
168*b56b3d07SJens Wiklander 		EMSG("Persistent object not yet supported, panic!");
169*b56b3d07SJens Wiklander 		TEE_Panic(0);
170*b56b3d07SJens Wiklander 	} else {
171*b56b3d07SJens Wiklander 		rc = PKCS11_CKR_OK;
172*b56b3d07SJens Wiklander 		LIST_INSERT_HEAD(get_session_objects(session), obj, link);
173*b56b3d07SJens Wiklander 	}
174*b56b3d07SJens Wiklander 
175*b56b3d07SJens Wiklander 	*out_handle = obj_handle;
176*b56b3d07SJens Wiklander 
177*b56b3d07SJens Wiklander 	return PKCS11_CKR_OK;
178*b56b3d07SJens Wiklander err:
179*b56b3d07SJens Wiklander 	/* make sure that supplied "head" isn't freed */
180*b56b3d07SJens Wiklander 	obj->attributes = NULL;
181*b56b3d07SJens Wiklander 	handle_put(&session->object_handle_db, obj_handle);
182*b56b3d07SJens Wiklander 	if (get_bool(head, PKCS11_CKA_TOKEN))
183*b56b3d07SJens Wiklander 		cleanup_persistent_object(obj, session->token);
184*b56b3d07SJens Wiklander 	else
185*b56b3d07SJens Wiklander 		cleanup_volatile_obj_ref(obj);
186*b56b3d07SJens Wiklander 
187*b56b3d07SJens Wiklander 	return rc;
188*b56b3d07SJens Wiklander }
189*b56b3d07SJens Wiklander 
190*b56b3d07SJens Wiklander enum pkcs11_rc entry_create_object(struct pkcs11_client *client,
191*b56b3d07SJens Wiklander 				   uint32_t ptypes, TEE_Param *params)
192*b56b3d07SJens Wiklander {
193*b56b3d07SJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
194*b56b3d07SJens Wiklander 						TEE_PARAM_TYPE_NONE,
195*b56b3d07SJens Wiklander 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
196*b56b3d07SJens Wiklander 						TEE_PARAM_TYPE_NONE);
197*b56b3d07SJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
198*b56b3d07SJens Wiklander 	TEE_Param *ctrl = params;
199*b56b3d07SJens Wiklander 	TEE_Param *out = params + 2;
200*b56b3d07SJens Wiklander 	struct serialargs ctrlargs = { };
201*b56b3d07SJens Wiklander 	struct pkcs11_session *session = NULL;
202*b56b3d07SJens Wiklander 	struct obj_attrs *head = NULL;
203*b56b3d07SJens Wiklander 	struct pkcs11_object_head *template = NULL;
204*b56b3d07SJens Wiklander 	uint32_t session_handle = 0;
205*b56b3d07SJens Wiklander 	size_t template_size = 0;
206*b56b3d07SJens Wiklander 	uint32_t obj_handle = 0;
207*b56b3d07SJens Wiklander 
208*b56b3d07SJens Wiklander 	/*
209*b56b3d07SJens Wiklander 	 * Collect the arguments of the request
210*b56b3d07SJens Wiklander 	 */
211*b56b3d07SJens Wiklander 
212*b56b3d07SJens Wiklander 	if (!client || ptypes != exp_pt ||
213*b56b3d07SJens Wiklander 	    out->memref.size != sizeof(obj_handle))
214*b56b3d07SJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
215*b56b3d07SJens Wiklander 
216*b56b3d07SJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
217*b56b3d07SJens Wiklander 
218*b56b3d07SJens Wiklander 	rc = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
219*b56b3d07SJens Wiklander 	if (rc)
220*b56b3d07SJens Wiklander 		return rc;
221*b56b3d07SJens Wiklander 
222*b56b3d07SJens Wiklander 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
223*b56b3d07SJens Wiklander 	if (rc)
224*b56b3d07SJens Wiklander 		return rc;
225*b56b3d07SJens Wiklander 
226*b56b3d07SJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs)) {
227*b56b3d07SJens Wiklander 		rc = PKCS11_CKR_ARGUMENTS_BAD;
228*b56b3d07SJens Wiklander 		goto out;
229*b56b3d07SJens Wiklander 	}
230*b56b3d07SJens Wiklander 
231*b56b3d07SJens Wiklander 	session = pkcs11_handle2session(session_handle, client);
232*b56b3d07SJens Wiklander 	if (!session) {
233*b56b3d07SJens Wiklander 		rc = PKCS11_CKR_SESSION_HANDLE_INVALID;
234*b56b3d07SJens Wiklander 		goto out;
235*b56b3d07SJens Wiklander 	}
236*b56b3d07SJens Wiklander 
237*b56b3d07SJens Wiklander 	template_size = sizeof(*template) + template->attrs_size;
238*b56b3d07SJens Wiklander 
239*b56b3d07SJens Wiklander 	/*
240*b56b3d07SJens Wiklander 	 * Prepare a clean initial state for the requested object attributes.
241*b56b3d07SJens Wiklander 	 * Free temporary template once done.
242*b56b3d07SJens Wiklander 	 */
243*b56b3d07SJens Wiklander 	rc = create_attributes_from_template(&head, template, template_size,
244*b56b3d07SJens Wiklander 					     NULL, PKCS11_FUNCTION_IMPORT,
245*b56b3d07SJens Wiklander 					     PKCS11_PROCESSING_IMPORT);
246*b56b3d07SJens Wiklander 	TEE_Free(template);
247*b56b3d07SJens Wiklander 	template = NULL;
248*b56b3d07SJens Wiklander 	if (rc)
249*b56b3d07SJens Wiklander 		goto out;
250*b56b3d07SJens Wiklander 
251*b56b3d07SJens Wiklander 	/*
252*b56b3d07SJens Wiklander 	 * Check target object attributes match target processing
253*b56b3d07SJens Wiklander 	 * Check target object attributes match token state
254*b56b3d07SJens Wiklander 	 */
255*b56b3d07SJens Wiklander 	rc = check_created_attrs_against_processing(PKCS11_PROCESSING_IMPORT,
256*b56b3d07SJens Wiklander 						    head);
257*b56b3d07SJens Wiklander 	if (rc)
258*b56b3d07SJens Wiklander 		goto out;
259*b56b3d07SJens Wiklander 
260*b56b3d07SJens Wiklander 	rc = check_created_attrs_against_token(session, head);
261*b56b3d07SJens Wiklander 	if (rc)
262*b56b3d07SJens Wiklander 		goto out;
263*b56b3d07SJens Wiklander 
264*b56b3d07SJens Wiklander 	/*
265*b56b3d07SJens Wiklander 	 * At this stage the object is almost created: all its attributes are
266*b56b3d07SJens Wiklander 	 * referenced in @head, including the key value and are assumed
267*b56b3d07SJens Wiklander 	 * reliable. Now need to register it and get a handle for it.
268*b56b3d07SJens Wiklander 	 */
269*b56b3d07SJens Wiklander 	rc = create_object(session, head, &obj_handle);
270*b56b3d07SJens Wiklander 	if (rc)
271*b56b3d07SJens Wiklander 		goto out;
272*b56b3d07SJens Wiklander 
273*b56b3d07SJens Wiklander 	/*
274*b56b3d07SJens Wiklander 	 * Now obj_handle (through the related struct pkcs11_object
275*b56b3d07SJens Wiklander 	 * instance) owns the serialised buffer that holds the object
276*b56b3d07SJens Wiklander 	 * attributes. We clear reference in head to NULL as the serializer
277*b56b3d07SJens Wiklander 	 * object is now referred from obj_handle. This allows smooth pass
278*b56b3d07SJens Wiklander 	 * through free at function exit.
279*b56b3d07SJens Wiklander 	 */
280*b56b3d07SJens Wiklander 	head = NULL;
281*b56b3d07SJens Wiklander 
282*b56b3d07SJens Wiklander 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
283*b56b3d07SJens Wiklander 	out->memref.size = sizeof(obj_handle);
284*b56b3d07SJens Wiklander 
285*b56b3d07SJens Wiklander 	DMSG("PKCS11 session %"PRIu32": import object %#"PRIx32,
286*b56b3d07SJens Wiklander 	     session->handle, obj_handle);
287*b56b3d07SJens Wiklander 
288*b56b3d07SJens Wiklander out:
289*b56b3d07SJens Wiklander 	TEE_Free(template);
290*b56b3d07SJens Wiklander 	TEE_Free(head);
291*b56b3d07SJens Wiklander 
292*b56b3d07SJens Wiklander 	return rc;
293*b56b3d07SJens Wiklander }
294*b56b3d07SJens Wiklander 
295*b56b3d07SJens Wiklander enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client,
296*b56b3d07SJens Wiklander 				    uint32_t ptypes, TEE_Param *params)
297*b56b3d07SJens Wiklander {
298*b56b3d07SJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
299*b56b3d07SJens Wiklander 						TEE_PARAM_TYPE_NONE,
300*b56b3d07SJens Wiklander 						TEE_PARAM_TYPE_NONE,
301*b56b3d07SJens Wiklander 						TEE_PARAM_TYPE_NONE);
302*b56b3d07SJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
303*b56b3d07SJens Wiklander 	TEE_Param *ctrl = params;
304*b56b3d07SJens Wiklander 	struct serialargs ctrlargs = { };
305*b56b3d07SJens Wiklander 	uint32_t object_handle = 0;
306*b56b3d07SJens Wiklander 	struct pkcs11_session *session = NULL;
307*b56b3d07SJens Wiklander 	struct pkcs11_object *object = NULL;
308*b56b3d07SJens Wiklander 	uint32_t session_handle = 0;
309*b56b3d07SJens Wiklander 
310*b56b3d07SJens Wiklander 	if (!client || ptypes != exp_pt)
311*b56b3d07SJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
312*b56b3d07SJens Wiklander 
313*b56b3d07SJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
314*b56b3d07SJens Wiklander 
315*b56b3d07SJens Wiklander 	rc = serialargs_get_u32(&ctrlargs, &session_handle);
316*b56b3d07SJens Wiklander 	if (rc)
317*b56b3d07SJens Wiklander 		return rc;
318*b56b3d07SJens Wiklander 
319*b56b3d07SJens Wiklander 	rc = serialargs_get_u32(&ctrlargs, &object_handle);
320*b56b3d07SJens Wiklander 	if (rc)
321*b56b3d07SJens Wiklander 		return rc;
322*b56b3d07SJens Wiklander 
323*b56b3d07SJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs))
324*b56b3d07SJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
325*b56b3d07SJens Wiklander 
326*b56b3d07SJens Wiklander 	session = pkcs11_handle2session(session_handle, client);
327*b56b3d07SJens Wiklander 	if (!session)
328*b56b3d07SJens Wiklander 		return PKCS11_CKR_SESSION_HANDLE_INVALID;
329*b56b3d07SJens Wiklander 
330*b56b3d07SJens Wiklander 	object = pkcs11_handle2object(object_handle, session);
331*b56b3d07SJens Wiklander 	if (!object)
332*b56b3d07SJens Wiklander 		return PKCS11_CKR_OBJECT_HANDLE_INVALID;
333*b56b3d07SJens Wiklander 
334*b56b3d07SJens Wiklander 	destroy_object(session, object, false);
335*b56b3d07SJens Wiklander 
336*b56b3d07SJens Wiklander 	DMSG("PKCS11 session %"PRIu32": destroy object %#"PRIx32,
337*b56b3d07SJens Wiklander 	     session->handle, object_handle);
338*b56b3d07SJens Wiklander 
339*b56b3d07SJens Wiklander 	return rc;
340*b56b3d07SJens Wiklander }
341