xref: /optee_os/ta/pkcs11/src/pkcs11_token.c (revision 6e4f8f17cb8f98d75ea4b565bb1a0603646da993)
1c84ccd0aSEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause
2c84ccd0aSEtienne Carriere /*
3c84ccd0aSEtienne Carriere  * Copyright (c) 2017-2020, Linaro Limited
4c84ccd0aSEtienne Carriere  */
5c84ccd0aSEtienne Carriere 
6c84ccd0aSEtienne Carriere #include <assert.h>
7d38f9635SEtienne Carriere #include <confine_array_index.h>
8c84ccd0aSEtienne Carriere #include <pkcs11_ta.h>
9c84ccd0aSEtienne Carriere #include <string.h>
10c84ccd0aSEtienne Carriere #include <string_ext.h>
11c84ccd0aSEtienne Carriere #include <sys/queue.h>
12c84ccd0aSEtienne Carriere #include <tee_api_types.h>
13c84ccd0aSEtienne Carriere #include <tee_internal_api_extensions.h>
14c84ccd0aSEtienne Carriere #include <util.h>
15c84ccd0aSEtienne Carriere 
16c84ccd0aSEtienne Carriere #include "pkcs11_token.h"
17c84ccd0aSEtienne Carriere #include "pkcs11_helpers.h"
1822ac6984SEtienne Carriere #include "serializer.h"
19c84ccd0aSEtienne Carriere 
20c84ccd0aSEtienne Carriere /* Provide 3 slots/tokens, ID is token index */
21c84ccd0aSEtienne Carriere #ifndef CFG_PKCS11_TA_TOKEN_COUNT
22c84ccd0aSEtienne Carriere #define TOKEN_COUNT		3
23c84ccd0aSEtienne Carriere #else
24c84ccd0aSEtienne Carriere #define TOKEN_COUNT		CFG_PKCS11_TA_TOKEN_COUNT
25c84ccd0aSEtienne Carriere #endif
26c84ccd0aSEtienne Carriere 
27e084583eSEtienne Carriere /*
28e084583eSEtienne Carriere  * Structure tracking client applications
29e084583eSEtienne Carriere  *
30e084583eSEtienne Carriere  * @link - chained list of registered client applications
31e084583eSEtienne Carriere  * @sessions - list of the PKCS11 sessions opened by the client application
32e084583eSEtienne Carriere  */
33e084583eSEtienne Carriere struct pkcs11_client {
34e084583eSEtienne Carriere 	TAILQ_ENTRY(pkcs11_client) link;
35e084583eSEtienne Carriere 	struct session_list session_list;
36e084583eSEtienne Carriere 	struct handle_db session_handle_db;
37e084583eSEtienne Carriere };
38e084583eSEtienne Carriere 
39c84ccd0aSEtienne Carriere /* Static allocation of tokens runtime instances (reset to 0 at load) */
40c84ccd0aSEtienne Carriere struct ck_token ck_token[TOKEN_COUNT];
41c84ccd0aSEtienne Carriere 
42e084583eSEtienne Carriere static struct client_list pkcs11_client_list =
43e084583eSEtienne Carriere 	TAILQ_HEAD_INITIALIZER(pkcs11_client_list);
44e084583eSEtienne Carriere 
45*6e4f8f17SEtienne Carriere static void close_ck_session(struct pkcs11_session *session);
46*6e4f8f17SEtienne Carriere 
47c84ccd0aSEtienne Carriere struct ck_token *get_token(unsigned int token_id)
48c84ccd0aSEtienne Carriere {
49d38f9635SEtienne Carriere 	if (token_id < TOKEN_COUNT)
50d38f9635SEtienne Carriere 		return &ck_token[confine_array_index(token_id, TOKEN_COUNT)];
51c84ccd0aSEtienne Carriere 
52d38f9635SEtienne Carriere 	return NULL;
53c84ccd0aSEtienne Carriere }
54c84ccd0aSEtienne Carriere 
55c84ccd0aSEtienne Carriere unsigned int get_token_id(struct ck_token *token)
56c84ccd0aSEtienne Carriere {
57c84ccd0aSEtienne Carriere 	ptrdiff_t id = token - ck_token;
58c84ccd0aSEtienne Carriere 
59c84ccd0aSEtienne Carriere 	assert(id >= 0 && id < TOKEN_COUNT);
60c84ccd0aSEtienne Carriere 	return id;
61c84ccd0aSEtienne Carriere }
62c84ccd0aSEtienne Carriere 
63e084583eSEtienne Carriere struct pkcs11_client *tee_session2client(void *tee_session)
64e084583eSEtienne Carriere {
65e084583eSEtienne Carriere 	struct pkcs11_client *client = NULL;
66e084583eSEtienne Carriere 
67e084583eSEtienne Carriere 	TAILQ_FOREACH(client, &pkcs11_client_list, link)
68e084583eSEtienne Carriere 		if (client == tee_session)
69e084583eSEtienne Carriere 			break;
70e084583eSEtienne Carriere 
71e084583eSEtienne Carriere 	return client;
72e084583eSEtienne Carriere }
73e084583eSEtienne Carriere 
74*6e4f8f17SEtienne Carriere struct pkcs11_session *pkcs11_handle2session(uint32_t handle,
75*6e4f8f17SEtienne Carriere 					     struct pkcs11_client *client)
76*6e4f8f17SEtienne Carriere {
77*6e4f8f17SEtienne Carriere 	return handle_lookup(&client->session_handle_db, handle);
78*6e4f8f17SEtienne Carriere }
79*6e4f8f17SEtienne Carriere 
80e084583eSEtienne Carriere struct pkcs11_client *register_client(void)
81e084583eSEtienne Carriere {
82e084583eSEtienne Carriere 	struct pkcs11_client *client = NULL;
83e084583eSEtienne Carriere 
84e084583eSEtienne Carriere 	client = TEE_Malloc(sizeof(*client), TEE_MALLOC_FILL_ZERO);
85e084583eSEtienne Carriere 	if (!client)
86e084583eSEtienne Carriere 		return NULL;
87e084583eSEtienne Carriere 
88e084583eSEtienne Carriere 	TAILQ_INSERT_HEAD(&pkcs11_client_list, client, link);
89e084583eSEtienne Carriere 	TAILQ_INIT(&client->session_list);
90e084583eSEtienne Carriere 	handle_db_init(&client->session_handle_db);
91e084583eSEtienne Carriere 
92e084583eSEtienne Carriere 	return client;
93e084583eSEtienne Carriere }
94e084583eSEtienne Carriere 
95e084583eSEtienne Carriere void unregister_client(struct pkcs11_client *client)
96e084583eSEtienne Carriere {
97*6e4f8f17SEtienne Carriere 	struct pkcs11_session *session = NULL;
98*6e4f8f17SEtienne Carriere 	struct pkcs11_session *next = NULL;
99*6e4f8f17SEtienne Carriere 
100e084583eSEtienne Carriere 	if (!client) {
101e084583eSEtienne Carriere 		EMSG("Invalid TEE session handle");
102e084583eSEtienne Carriere 		return;
103e084583eSEtienne Carriere 	}
104e084583eSEtienne Carriere 
105*6e4f8f17SEtienne Carriere 	TAILQ_FOREACH_SAFE(session, &client->session_list, link, next)
106*6e4f8f17SEtienne Carriere 		close_ck_session(session);
107*6e4f8f17SEtienne Carriere 
108e084583eSEtienne Carriere 	TAILQ_REMOVE(&pkcs11_client_list, client, link);
109e084583eSEtienne Carriere 	handle_db_destroy(&client->session_handle_db);
110e084583eSEtienne Carriere 	TEE_Free(client);
111e084583eSEtienne Carriere }
112e084583eSEtienne Carriere 
113c84ccd0aSEtienne Carriere static TEE_Result pkcs11_token_init(unsigned int id)
114c84ccd0aSEtienne Carriere {
115c84ccd0aSEtienne Carriere 	struct ck_token *token = init_persistent_db(id);
116c84ccd0aSEtienne Carriere 
117c84ccd0aSEtienne Carriere 	if (!token)
118c84ccd0aSEtienne Carriere 		return TEE_ERROR_SECURITY;
119c84ccd0aSEtienne Carriere 
120c84ccd0aSEtienne Carriere 	if (token->state == PKCS11_TOKEN_RESET) {
121c84ccd0aSEtienne Carriere 		/* As per PKCS#11 spec, token resets to read/write state */
122c84ccd0aSEtienne Carriere 		token->state = PKCS11_TOKEN_READ_WRITE;
123c84ccd0aSEtienne Carriere 		token->session_count = 0;
124c84ccd0aSEtienne Carriere 		token->rw_session_count = 0;
125c84ccd0aSEtienne Carriere 	}
126c84ccd0aSEtienne Carriere 
127c84ccd0aSEtienne Carriere 	return TEE_SUCCESS;
128c84ccd0aSEtienne Carriere }
129c84ccd0aSEtienne Carriere 
130c84ccd0aSEtienne Carriere TEE_Result pkcs11_init(void)
131c84ccd0aSEtienne Carriere {
132c84ccd0aSEtienne Carriere 	unsigned int id = 0;
133c84ccd0aSEtienne Carriere 	TEE_Result ret = TEE_ERROR_GENERIC;
134c84ccd0aSEtienne Carriere 
135c84ccd0aSEtienne Carriere 	for (id = 0; id < TOKEN_COUNT; id++) {
136c84ccd0aSEtienne Carriere 		ret = pkcs11_token_init(id);
137c84ccd0aSEtienne Carriere 		if (ret)
138e084583eSEtienne Carriere 			break;
139c84ccd0aSEtienne Carriere 	}
140c84ccd0aSEtienne Carriere 
141c84ccd0aSEtienne Carriere 	return ret;
142c84ccd0aSEtienne Carriere }
143c84ccd0aSEtienne Carriere 
144c84ccd0aSEtienne Carriere void pkcs11_deinit(void)
145c84ccd0aSEtienne Carriere {
146c84ccd0aSEtienne Carriere 	unsigned int id = 0;
147c84ccd0aSEtienne Carriere 
148c84ccd0aSEtienne Carriere 	for (id = 0; id < TOKEN_COUNT; id++)
149c84ccd0aSEtienne Carriere 		close_persistent_db(get_token(id));
150c84ccd0aSEtienne Carriere }
15122ac6984SEtienne Carriere 
15222ac6984SEtienne Carriere uint32_t entry_ck_slot_list(uint32_t ptypes, TEE_Param *params)
15322ac6984SEtienne Carriere {
15422ac6984SEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
15522ac6984SEtienne Carriere 						TEE_PARAM_TYPE_NONE,
15622ac6984SEtienne Carriere 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
15722ac6984SEtienne Carriere 						TEE_PARAM_TYPE_NONE);
15822ac6984SEtienne Carriere 	TEE_Param *out = &params[2];
15922ac6984SEtienne Carriere 	uint32_t token_id = 0;
16022ac6984SEtienne Carriere 	const size_t out_size = sizeof(token_id) * TOKEN_COUNT;
16122ac6984SEtienne Carriere 	uint8_t *id = NULL;
16222ac6984SEtienne Carriere 
16322ac6984SEtienne Carriere 	if (ptypes != exp_pt ||
16422ac6984SEtienne Carriere 	    params[0].memref.size != TEE_PARAM0_SIZE_MIN)
16522ac6984SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
16622ac6984SEtienne Carriere 
16722ac6984SEtienne Carriere 	if (out->memref.size < out_size) {
16822ac6984SEtienne Carriere 		out->memref.size = out_size;
16922ac6984SEtienne Carriere 
17022ac6984SEtienne Carriere 		if (out->memref.buffer)
17122ac6984SEtienne Carriere 			return PKCS11_CKR_BUFFER_TOO_SMALL;
17222ac6984SEtienne Carriere 		else
17322ac6984SEtienne Carriere 			return PKCS11_CKR_OK;
17422ac6984SEtienne Carriere 	}
17522ac6984SEtienne Carriere 
17622ac6984SEtienne Carriere 	for (token_id = 0, id = out->memref.buffer; token_id < TOKEN_COUNT;
17722ac6984SEtienne Carriere 	     token_id++, id += sizeof(token_id))
17822ac6984SEtienne Carriere 		TEE_MemMove(id, &token_id, sizeof(token_id));
17922ac6984SEtienne Carriere 
18022ac6984SEtienne Carriere 	out->memref.size = out_size;
18122ac6984SEtienne Carriere 
18222ac6984SEtienne Carriere 	return PKCS11_CKR_OK;
18322ac6984SEtienne Carriere }
184ce94efefSEtienne Carriere 
185b3ac5035SEtienne Carriere static void pad_str(uint8_t *str, size_t size)
186b3ac5035SEtienne Carriere {
187b3ac5035SEtienne Carriere 	int n = strnlen((char *)str, size);
188b3ac5035SEtienne Carriere 
189b3ac5035SEtienne Carriere 	TEE_MemFill(str + n, ' ', size - n);
190b3ac5035SEtienne Carriere }
191b3ac5035SEtienne Carriere 
192ce94efefSEtienne Carriere uint32_t entry_ck_slot_info(uint32_t ptypes, TEE_Param *params)
193ce94efefSEtienne Carriere {
194ce94efefSEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
195ce94efefSEtienne Carriere 						TEE_PARAM_TYPE_NONE,
196ce94efefSEtienne Carriere 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
197ce94efefSEtienne Carriere 						TEE_PARAM_TYPE_NONE);
198ce94efefSEtienne Carriere 	TEE_Param *ctrl = &params[0];
199ce94efefSEtienne Carriere 	TEE_Param *out = &params[2];
200ce94efefSEtienne Carriere 	uint32_t rv = 0;
201ce94efefSEtienne Carriere 	struct serialargs ctrlargs = { };
202ce94efefSEtienne Carriere 	uint32_t token_id = 0;
203ce94efefSEtienne Carriere 	struct ck_token *token = NULL;
204ce94efefSEtienne Carriere 	struct pkcs11_slot_info info = {
205ce94efefSEtienne Carriere 		.slot_description = PKCS11_SLOT_DESCRIPTION,
206ce94efefSEtienne Carriere 		.manufacturer_id = PKCS11_SLOT_MANUFACTURER,
207ce94efefSEtienne Carriere 		.flags = PKCS11_CKFS_TOKEN_PRESENT,
208ce94efefSEtienne Carriere 		.hardware_version = PKCS11_SLOT_HW_VERSION,
209ce94efefSEtienne Carriere 		.firmware_version = PKCS11_SLOT_FW_VERSION,
210ce94efefSEtienne Carriere 	};
211ce94efefSEtienne Carriere 
212ce94efefSEtienne Carriere 	COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_DESCRIPTION) <=
213ce94efefSEtienne Carriere 			    sizeof(info.slot_description));
214ce94efefSEtienne Carriere 	COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_MANUFACTURER) <=
215ce94efefSEtienne Carriere 			    sizeof(info.manufacturer_id));
216ce94efefSEtienne Carriere 
217ce94efefSEtienne Carriere 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
218ce94efefSEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
219ce94efefSEtienne Carriere 
220ce94efefSEtienne Carriere 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
221ce94efefSEtienne Carriere 
222ce94efefSEtienne Carriere 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
223ce94efefSEtienne Carriere 	if (rv)
224ce94efefSEtienne Carriere 		return rv;
225ce94efefSEtienne Carriere 
226ce94efefSEtienne Carriere 	if (serialargs_remaining_bytes(&ctrlargs))
227ce94efefSEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
228ce94efefSEtienne Carriere 
229ce94efefSEtienne Carriere 	token = get_token(token_id);
230ce94efefSEtienne Carriere 	if (!token)
231ce94efefSEtienne Carriere 		return PKCS11_CKR_SLOT_ID_INVALID;
232ce94efefSEtienne Carriere 
233b3ac5035SEtienne Carriere 	pad_str(info.slot_description, sizeof(info.slot_description));
234b3ac5035SEtienne Carriere 	pad_str(info.manufacturer_id, sizeof(info.manufacturer_id));
235ce94efefSEtienne Carriere 
236ce94efefSEtienne Carriere 	out->memref.size = sizeof(info);
237ce94efefSEtienne Carriere 	TEE_MemMove(out->memref.buffer, &info, out->memref.size);
238ce94efefSEtienne Carriere 
239ce94efefSEtienne Carriere 	return PKCS11_CKR_OK;
240ce94efefSEtienne Carriere }
241030e7392SEtienne Carriere 
242030e7392SEtienne Carriere uint32_t entry_ck_token_info(uint32_t ptypes, TEE_Param *params)
243030e7392SEtienne Carriere {
244030e7392SEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
245030e7392SEtienne Carriere 						TEE_PARAM_TYPE_NONE,
246030e7392SEtienne Carriere 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
247030e7392SEtienne Carriere 						TEE_PARAM_TYPE_NONE);
248030e7392SEtienne Carriere 	TEE_Param *ctrl = &params[0];
249030e7392SEtienne Carriere 	TEE_Param *out = &params[2];
250030e7392SEtienne Carriere 	uint32_t rv = 0;
251030e7392SEtienne Carriere 	struct serialargs ctrlargs = { };
252030e7392SEtienne Carriere 	uint32_t token_id = 0;
253030e7392SEtienne Carriere 	struct ck_token *token = NULL;
254030e7392SEtienne Carriere 	struct pkcs11_token_info info = {
255030e7392SEtienne Carriere 		.manufacturer_id = PKCS11_TOKEN_MANUFACTURER,
256030e7392SEtienne Carriere 		.model = PKCS11_TOKEN_MODEL,
257030e7392SEtienne Carriere 		.serial_number = PKCS11_TOKEN_SERIAL_NUMBER,
258030e7392SEtienne Carriere 		.max_session_count = UINT32_MAX,
259030e7392SEtienne Carriere 		.max_rw_session_count = UINT32_MAX,
260030e7392SEtienne Carriere 		.max_pin_len = PKCS11_TOKEN_PIN_SIZE_MAX,
261030e7392SEtienne Carriere 		.min_pin_len = PKCS11_TOKEN_PIN_SIZE_MIN,
262030e7392SEtienne Carriere 		.total_public_memory = UINT32_MAX,
263030e7392SEtienne Carriere 		.free_public_memory = UINT32_MAX,
264030e7392SEtienne Carriere 		.total_private_memory = UINT32_MAX,
265030e7392SEtienne Carriere 		.free_private_memory = UINT32_MAX,
266030e7392SEtienne Carriere 		.hardware_version = PKCS11_TOKEN_HW_VERSION,
267030e7392SEtienne Carriere 		.firmware_version = PKCS11_TOKEN_FW_VERSION,
268030e7392SEtienne Carriere 	};
269030e7392SEtienne Carriere 
270030e7392SEtienne Carriere 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
271030e7392SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
272030e7392SEtienne Carriere 
273030e7392SEtienne Carriere 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
274030e7392SEtienne Carriere 
275030e7392SEtienne Carriere 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
276030e7392SEtienne Carriere 	if (rv)
277030e7392SEtienne Carriere 		return rv;
278030e7392SEtienne Carriere 
279030e7392SEtienne Carriere 	if (serialargs_remaining_bytes(&ctrlargs))
280030e7392SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
281030e7392SEtienne Carriere 
282030e7392SEtienne Carriere 	token = get_token(token_id);
283030e7392SEtienne Carriere 	if (!token)
284030e7392SEtienne Carriere 		return PKCS11_CKR_SLOT_ID_INVALID;
285030e7392SEtienne Carriere 
286030e7392SEtienne Carriere 	pad_str(info.manufacturer_id, sizeof(info.manufacturer_id));
287030e7392SEtienne Carriere 	pad_str(info.model, sizeof(info.model));
288030e7392SEtienne Carriere 	pad_str(info.serial_number, sizeof(info.serial_number));
289030e7392SEtienne Carriere 
290030e7392SEtienne Carriere 	TEE_MemMove(info.label, token->db_main->label, sizeof(info.label));
291030e7392SEtienne Carriere 
292030e7392SEtienne Carriere 	info.flags = token->db_main->flags;
293030e7392SEtienne Carriere 	info.session_count = token->session_count;
294030e7392SEtienne Carriere 	info.rw_session_count = token->rw_session_count;
295030e7392SEtienne Carriere 
296030e7392SEtienne Carriere 	TEE_MemMove(out->memref.buffer, &info, sizeof(info));
297030e7392SEtienne Carriere 
298030e7392SEtienne Carriere 	return PKCS11_CKR_OK;
299030e7392SEtienne Carriere }
3006f74919dSEtienne Carriere 
3016f74919dSEtienne Carriere static void dmsg_print_supported_mechanism(unsigned int token_id __maybe_unused,
3026f74919dSEtienne Carriere 					   uint32_t *array __maybe_unused,
3036f74919dSEtienne Carriere 					   size_t count __maybe_unused)
3046f74919dSEtienne Carriere {
3056f74919dSEtienne Carriere 	size_t __maybe_unused n = 0;
3066f74919dSEtienne Carriere 
3076f74919dSEtienne Carriere 	if (TRACE_LEVEL < TRACE_DEBUG)
3086f74919dSEtienne Carriere 		return;
3096f74919dSEtienne Carriere 
3106f74919dSEtienne Carriere 	for (n = 0; n < count; n++)
3116f74919dSEtienne Carriere 		DMSG("PKCS11 token %"PRIu32": mechanism 0x%04"PRIx32": %s",
3126f74919dSEtienne Carriere 		     token_id, array[n], id2str_mechanism(array[n]));
3136f74919dSEtienne Carriere }
3146f74919dSEtienne Carriere 
3156f74919dSEtienne Carriere uint32_t entry_ck_token_mecha_ids(uint32_t ptypes, TEE_Param *params)
3166f74919dSEtienne Carriere {
3176f74919dSEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
3186f74919dSEtienne Carriere 						TEE_PARAM_TYPE_NONE,
3196f74919dSEtienne Carriere 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
3206f74919dSEtienne Carriere 						TEE_PARAM_TYPE_NONE);
3216f74919dSEtienne Carriere 	TEE_Param *ctrl = &params[0];
3226f74919dSEtienne Carriere 	TEE_Param *out = &params[2];
3236f74919dSEtienne Carriere 	uint32_t rv = 0;
3246f74919dSEtienne Carriere 	struct serialargs ctrlargs = { };
3256f74919dSEtienne Carriere 	uint32_t token_id = 0;
3266f74919dSEtienne Carriere 	struct ck_token __maybe_unused *token = NULL;
3276f74919dSEtienne Carriere 	size_t count = 0;
3286f74919dSEtienne Carriere 	uint32_t *array = NULL;
3296f74919dSEtienne Carriere 
3306f74919dSEtienne Carriere 	if (ptypes != exp_pt)
3316f74919dSEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
3326f74919dSEtienne Carriere 
3336f74919dSEtienne Carriere 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
3346f74919dSEtienne Carriere 
3356f74919dSEtienne Carriere 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
3366f74919dSEtienne Carriere 	if (rv)
3376f74919dSEtienne Carriere 		return rv;
3386f74919dSEtienne Carriere 
3396f74919dSEtienne Carriere 	if (serialargs_remaining_bytes(&ctrlargs))
3406f74919dSEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
3416f74919dSEtienne Carriere 
3426f74919dSEtienne Carriere 	token = get_token(token_id);
3436f74919dSEtienne Carriere 	if (!token)
3446f74919dSEtienne Carriere 		return PKCS11_CKR_SLOT_ID_INVALID;
3456f74919dSEtienne Carriere 
3466f74919dSEtienne Carriere 	count = out->memref.size / sizeof(*array);
3476f74919dSEtienne Carriere 	array = tee_malloc_mechanism_list(&count);
3486f74919dSEtienne Carriere 
3496f74919dSEtienne Carriere 	if (out->memref.size < count * sizeof(*array)) {
3506f74919dSEtienne Carriere 		assert(!array);
3516f74919dSEtienne Carriere 		out->memref.size = count * sizeof(*array);
3526f74919dSEtienne Carriere 		return PKCS11_CKR_BUFFER_TOO_SMALL;
3536f74919dSEtienne Carriere 	}
3546f74919dSEtienne Carriere 
3556f74919dSEtienne Carriere 	if (!array)
3566f74919dSEtienne Carriere 		return PKCS11_CKR_DEVICE_MEMORY;
3576f74919dSEtienne Carriere 
3586f74919dSEtienne Carriere 	dmsg_print_supported_mechanism(token_id, array, count);
3596f74919dSEtienne Carriere 
3606f74919dSEtienne Carriere 	out->memref.size = count * sizeof(*array);
3616f74919dSEtienne Carriere 	TEE_MemMove(out->memref.buffer, array, out->memref.size);
3626f74919dSEtienne Carriere 
3636f74919dSEtienne Carriere 	TEE_Free(array);
3646f74919dSEtienne Carriere 
3656f74919dSEtienne Carriere 	return rv;
3666f74919dSEtienne Carriere }
3671d3ebedbSEtienne Carriere 
3681d3ebedbSEtienne Carriere static void supported_mechanism_key_size(uint32_t proc_id,
3691d3ebedbSEtienne Carriere 					 uint32_t *max_key_size,
3701d3ebedbSEtienne Carriere 					 uint32_t *min_key_size)
3711d3ebedbSEtienne Carriere {
3721d3ebedbSEtienne Carriere 	switch (proc_id) {
3731d3ebedbSEtienne Carriere 	/* Will be filled once TA supports mechanisms */
3741d3ebedbSEtienne Carriere 	default:
3751d3ebedbSEtienne Carriere 		*min_key_size = 0;
3761d3ebedbSEtienne Carriere 		*max_key_size = 0;
3771d3ebedbSEtienne Carriere 		break;
3781d3ebedbSEtienne Carriere 	}
3791d3ebedbSEtienne Carriere }
3801d3ebedbSEtienne Carriere 
3811d3ebedbSEtienne Carriere uint32_t entry_ck_token_mecha_info(uint32_t ptypes, TEE_Param *params)
3821d3ebedbSEtienne Carriere {
3831d3ebedbSEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
3841d3ebedbSEtienne Carriere 						TEE_PARAM_TYPE_NONE,
3851d3ebedbSEtienne Carriere 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
3861d3ebedbSEtienne Carriere 						TEE_PARAM_TYPE_NONE);
3871d3ebedbSEtienne Carriere 	TEE_Param *ctrl = &params[0];
3881d3ebedbSEtienne Carriere 	TEE_Param *out = &params[2];
3891d3ebedbSEtienne Carriere 	uint32_t rv = 0;
3901d3ebedbSEtienne Carriere 	struct serialargs ctrlargs = { };
3911d3ebedbSEtienne Carriere 	uint32_t token_id = 0;
3921d3ebedbSEtienne Carriere 	uint32_t type = 0;
3931d3ebedbSEtienne Carriere 	struct ck_token *token = NULL;
3941d3ebedbSEtienne Carriere 	struct pkcs11_mechanism_info info = { };
3951d3ebedbSEtienne Carriere 
3961d3ebedbSEtienne Carriere 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
3971d3ebedbSEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
3981d3ebedbSEtienne Carriere 
3991d3ebedbSEtienne Carriere 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
4001d3ebedbSEtienne Carriere 
4011d3ebedbSEtienne Carriere 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
4021d3ebedbSEtienne Carriere 	if (rv)
4031d3ebedbSEtienne Carriere 		return rv;
4041d3ebedbSEtienne Carriere 
4051d3ebedbSEtienne Carriere 	rv = serialargs_get(&ctrlargs, &type, sizeof(uint32_t));
4061d3ebedbSEtienne Carriere 	if (rv)
4071d3ebedbSEtienne Carriere 		return rv;
4081d3ebedbSEtienne Carriere 
4091d3ebedbSEtienne Carriere 	if (serialargs_remaining_bytes(&ctrlargs))
4101d3ebedbSEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
4111d3ebedbSEtienne Carriere 
4121d3ebedbSEtienne Carriere 	token = get_token(token_id);
4131d3ebedbSEtienne Carriere 	if (!token)
4141d3ebedbSEtienne Carriere 		return PKCS11_CKR_SLOT_ID_INVALID;
4151d3ebedbSEtienne Carriere 
4161d3ebedbSEtienne Carriere 	if (!mechanism_is_valid(type))
4171d3ebedbSEtienne Carriere 		return PKCS11_CKR_MECHANISM_INVALID;
4181d3ebedbSEtienne Carriere 
4191d3ebedbSEtienne Carriere 	info.flags = mechanism_supported_flags(type);
4201d3ebedbSEtienne Carriere 
4211d3ebedbSEtienne Carriere 	supported_mechanism_key_size(type, &info.min_key_size,
4221d3ebedbSEtienne Carriere 				     &info.max_key_size);
4231d3ebedbSEtienne Carriere 
4241d3ebedbSEtienne Carriere 	TEE_MemMove(out->memref.buffer, &info, sizeof(info));
4251d3ebedbSEtienne Carriere 
4261d3ebedbSEtienne Carriere 	DMSG("PKCS11 token %"PRIu32": mechanism 0x%"PRIx32" info",
4271d3ebedbSEtienne Carriere 	     token_id, type);
4281d3ebedbSEtienne Carriere 
4291d3ebedbSEtienne Carriere 	return PKCS11_CKR_OK;
4301d3ebedbSEtienne Carriere }
431*6e4f8f17SEtienne Carriere 
432*6e4f8f17SEtienne Carriere /* Select the ReadOnly or ReadWrite state for session login state */
433*6e4f8f17SEtienne Carriere static void set_session_state(struct pkcs11_client *client,
434*6e4f8f17SEtienne Carriere 			      struct pkcs11_session *session, bool readonly)
435*6e4f8f17SEtienne Carriere {
436*6e4f8f17SEtienne Carriere 	struct pkcs11_session *sess = NULL;
437*6e4f8f17SEtienne Carriere 	enum pkcs11_session_state state = PKCS11_CKS_RO_PUBLIC_SESSION;
438*6e4f8f17SEtienne Carriere 
439*6e4f8f17SEtienne Carriere 	/* Default to public session if no session already registered */
440*6e4f8f17SEtienne Carriere 	if (readonly)
441*6e4f8f17SEtienne Carriere 		state = PKCS11_CKS_RO_PUBLIC_SESSION;
442*6e4f8f17SEtienne Carriere 	else
443*6e4f8f17SEtienne Carriere 		state = PKCS11_CKS_RW_PUBLIC_SESSION;
444*6e4f8f17SEtienne Carriere 
445*6e4f8f17SEtienne Carriere 	/*
446*6e4f8f17SEtienne Carriere 	 * No need to check all client sessions, the first found in
447*6e4f8f17SEtienne Carriere 	 * target token gives client login configuration.
448*6e4f8f17SEtienne Carriere 	 */
449*6e4f8f17SEtienne Carriere 	TAILQ_FOREACH(sess, &client->session_list, link) {
450*6e4f8f17SEtienne Carriere 		assert(sess != session);
451*6e4f8f17SEtienne Carriere 
452*6e4f8f17SEtienne Carriere 		if (sess->token == session->token) {
453*6e4f8f17SEtienne Carriere 			switch (sess->state) {
454*6e4f8f17SEtienne Carriere 			case PKCS11_CKS_RW_PUBLIC_SESSION:
455*6e4f8f17SEtienne Carriere 			case PKCS11_CKS_RO_PUBLIC_SESSION:
456*6e4f8f17SEtienne Carriere 				if (readonly)
457*6e4f8f17SEtienne Carriere 					state = PKCS11_CKS_RO_PUBLIC_SESSION;
458*6e4f8f17SEtienne Carriere 				else
459*6e4f8f17SEtienne Carriere 					state = PKCS11_CKS_RW_PUBLIC_SESSION;
460*6e4f8f17SEtienne Carriere 				break;
461*6e4f8f17SEtienne Carriere 			case PKCS11_CKS_RO_USER_FUNCTIONS:
462*6e4f8f17SEtienne Carriere 			case PKCS11_CKS_RW_USER_FUNCTIONS:
463*6e4f8f17SEtienne Carriere 				if (readonly)
464*6e4f8f17SEtienne Carriere 					state = PKCS11_CKS_RO_USER_FUNCTIONS;
465*6e4f8f17SEtienne Carriere 				else
466*6e4f8f17SEtienne Carriere 					state = PKCS11_CKS_RW_USER_FUNCTIONS;
467*6e4f8f17SEtienne Carriere 				break;
468*6e4f8f17SEtienne Carriere 			case PKCS11_CKS_RW_SO_FUNCTIONS:
469*6e4f8f17SEtienne Carriere 				if (readonly)
470*6e4f8f17SEtienne Carriere 					TEE_Panic(0);
471*6e4f8f17SEtienne Carriere 				else
472*6e4f8f17SEtienne Carriere 					state = PKCS11_CKS_RW_SO_FUNCTIONS;
473*6e4f8f17SEtienne Carriere 				break;
474*6e4f8f17SEtienne Carriere 			default:
475*6e4f8f17SEtienne Carriere 				TEE_Panic(0);
476*6e4f8f17SEtienne Carriere 			}
477*6e4f8f17SEtienne Carriere 			break;
478*6e4f8f17SEtienne Carriere 		}
479*6e4f8f17SEtienne Carriere 	}
480*6e4f8f17SEtienne Carriere 
481*6e4f8f17SEtienne Carriere 	session->state = state;
482*6e4f8f17SEtienne Carriere }
483*6e4f8f17SEtienne Carriere 
484*6e4f8f17SEtienne Carriere uint32_t entry_ck_open_session(struct pkcs11_client *client,
485*6e4f8f17SEtienne Carriere 			       uint32_t ptypes, TEE_Param *params)
486*6e4f8f17SEtienne Carriere {
487*6e4f8f17SEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
488*6e4f8f17SEtienne Carriere 						TEE_PARAM_TYPE_NONE,
489*6e4f8f17SEtienne Carriere 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
490*6e4f8f17SEtienne Carriere 						TEE_PARAM_TYPE_NONE);
491*6e4f8f17SEtienne Carriere 	TEE_Param *ctrl = &params[0];
492*6e4f8f17SEtienne Carriere 	TEE_Param *out = &params[2];
493*6e4f8f17SEtienne Carriere 	uint32_t rv = 0;
494*6e4f8f17SEtienne Carriere 	struct serialargs ctrlargs = { };
495*6e4f8f17SEtienne Carriere 	uint32_t token_id = 0;
496*6e4f8f17SEtienne Carriere 	uint32_t flags = 0;
497*6e4f8f17SEtienne Carriere 	struct ck_token *token = NULL;
498*6e4f8f17SEtienne Carriere 	struct pkcs11_session *session = NULL;
499*6e4f8f17SEtienne Carriere 	bool readonly = false;
500*6e4f8f17SEtienne Carriere 
501*6e4f8f17SEtienne Carriere 	if (!client || ptypes != exp_pt ||
502*6e4f8f17SEtienne Carriere 	    out->memref.size != sizeof(session->handle))
503*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
504*6e4f8f17SEtienne Carriere 
505*6e4f8f17SEtienne Carriere 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
506*6e4f8f17SEtienne Carriere 
507*6e4f8f17SEtienne Carriere 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
508*6e4f8f17SEtienne Carriere 	if (rv)
509*6e4f8f17SEtienne Carriere 		return rv;
510*6e4f8f17SEtienne Carriere 
511*6e4f8f17SEtienne Carriere 	rv = serialargs_get(&ctrlargs, &flags, sizeof(flags));
512*6e4f8f17SEtienne Carriere 	if (rv)
513*6e4f8f17SEtienne Carriere 		return rv;
514*6e4f8f17SEtienne Carriere 
515*6e4f8f17SEtienne Carriere 	if (serialargs_remaining_bytes(&ctrlargs))
516*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
517*6e4f8f17SEtienne Carriere 
518*6e4f8f17SEtienne Carriere 	token = get_token(token_id);
519*6e4f8f17SEtienne Carriere 	if (!token)
520*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_SLOT_ID_INVALID;
521*6e4f8f17SEtienne Carriere 
522*6e4f8f17SEtienne Carriere 	/* Sanitize session flags */
523*6e4f8f17SEtienne Carriere 	if (!(flags & PKCS11_CKFSS_SERIAL_SESSION) ||
524*6e4f8f17SEtienne Carriere 	    (flags & ~(PKCS11_CKFSS_RW_SESSION |
525*6e4f8f17SEtienne Carriere 		       PKCS11_CKFSS_SERIAL_SESSION)))
526*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
527*6e4f8f17SEtienne Carriere 
528*6e4f8f17SEtienne Carriere 	readonly = !(flags & PKCS11_CKFSS_RW_SESSION);
529*6e4f8f17SEtienne Carriere 
530*6e4f8f17SEtienne Carriere 	if (!readonly && token->state == PKCS11_TOKEN_READ_ONLY)
531*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_TOKEN_WRITE_PROTECTED;
532*6e4f8f17SEtienne Carriere 
533*6e4f8f17SEtienne Carriere 	if (readonly) {
534*6e4f8f17SEtienne Carriere 		/* Specifically reject read-only session under SO login */
535*6e4f8f17SEtienne Carriere 		TAILQ_FOREACH(session, &client->session_list, link)
536*6e4f8f17SEtienne Carriere 			if (pkcs11_session_is_so(session))
537*6e4f8f17SEtienne Carriere 				return PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS;
538*6e4f8f17SEtienne Carriere 	}
539*6e4f8f17SEtienne Carriere 
540*6e4f8f17SEtienne Carriere 	session = TEE_Malloc(sizeof(*session), TEE_MALLOC_FILL_ZERO);
541*6e4f8f17SEtienne Carriere 	if (!session)
542*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_DEVICE_MEMORY;
543*6e4f8f17SEtienne Carriere 
544*6e4f8f17SEtienne Carriere 	session->handle = handle_get(&client->session_handle_db, session);
545*6e4f8f17SEtienne Carriere 	if (!session->handle) {
546*6e4f8f17SEtienne Carriere 		TEE_Free(session);
547*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_DEVICE_MEMORY;
548*6e4f8f17SEtienne Carriere 	}
549*6e4f8f17SEtienne Carriere 
550*6e4f8f17SEtienne Carriere 	session->token = token;
551*6e4f8f17SEtienne Carriere 	session->client = client;
552*6e4f8f17SEtienne Carriere 
553*6e4f8f17SEtienne Carriere 	set_session_state(client, session, readonly);
554*6e4f8f17SEtienne Carriere 
555*6e4f8f17SEtienne Carriere 	TAILQ_INSERT_HEAD(&client->session_list, session, link);
556*6e4f8f17SEtienne Carriere 
557*6e4f8f17SEtienne Carriere 	session->token->session_count++;
558*6e4f8f17SEtienne Carriere 	if (!readonly)
559*6e4f8f17SEtienne Carriere 		session->token->rw_session_count++;
560*6e4f8f17SEtienne Carriere 
561*6e4f8f17SEtienne Carriere 	TEE_MemMove(out->memref.buffer, &session->handle,
562*6e4f8f17SEtienne Carriere 		    sizeof(session->handle));
563*6e4f8f17SEtienne Carriere 
564*6e4f8f17SEtienne Carriere 	DMSG("Open PKCS11 session %"PRIu32, session->handle);
565*6e4f8f17SEtienne Carriere 
566*6e4f8f17SEtienne Carriere 	return PKCS11_CKR_OK;
567*6e4f8f17SEtienne Carriere }
568*6e4f8f17SEtienne Carriere 
569*6e4f8f17SEtienne Carriere static void close_ck_session(struct pkcs11_session *session)
570*6e4f8f17SEtienne Carriere {
571*6e4f8f17SEtienne Carriere 	TAILQ_REMOVE(&session->client->session_list, session, link);
572*6e4f8f17SEtienne Carriere 	handle_put(&session->client->session_handle_db, session->handle);
573*6e4f8f17SEtienne Carriere 
574*6e4f8f17SEtienne Carriere 	session->token->session_count--;
575*6e4f8f17SEtienne Carriere 	if (pkcs11_session_is_read_write(session))
576*6e4f8f17SEtienne Carriere 		session->token->rw_session_count--;
577*6e4f8f17SEtienne Carriere 
578*6e4f8f17SEtienne Carriere 	TEE_Free(session);
579*6e4f8f17SEtienne Carriere 
580*6e4f8f17SEtienne Carriere 	DMSG("Close PKCS11 session %"PRIu32, session->handle);
581*6e4f8f17SEtienne Carriere }
582*6e4f8f17SEtienne Carriere 
583*6e4f8f17SEtienne Carriere uint32_t entry_ck_close_session(struct pkcs11_client *client,
584*6e4f8f17SEtienne Carriere 				uint32_t ptypes, TEE_Param *params)
585*6e4f8f17SEtienne Carriere {
586*6e4f8f17SEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
587*6e4f8f17SEtienne Carriere 						TEE_PARAM_TYPE_NONE,
588*6e4f8f17SEtienne Carriere 						TEE_PARAM_TYPE_NONE,
589*6e4f8f17SEtienne Carriere 						TEE_PARAM_TYPE_NONE);
590*6e4f8f17SEtienne Carriere 	TEE_Param *ctrl = &params[0];
591*6e4f8f17SEtienne Carriere 	uint32_t rv = 0;
592*6e4f8f17SEtienne Carriere 	struct serialargs ctrlargs = { };
593*6e4f8f17SEtienne Carriere 	uint32_t session_handle = 0;
594*6e4f8f17SEtienne Carriere 	struct pkcs11_session *session = NULL;
595*6e4f8f17SEtienne Carriere 
596*6e4f8f17SEtienne Carriere 	if (!client || ptypes != exp_pt)
597*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
598*6e4f8f17SEtienne Carriere 
599*6e4f8f17SEtienne Carriere 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
600*6e4f8f17SEtienne Carriere 
601*6e4f8f17SEtienne Carriere 	rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
602*6e4f8f17SEtienne Carriere 	if (rv)
603*6e4f8f17SEtienne Carriere 		return rv;
604*6e4f8f17SEtienne Carriere 
605*6e4f8f17SEtienne Carriere 	if (serialargs_remaining_bytes(&ctrlargs))
606*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
607*6e4f8f17SEtienne Carriere 
608*6e4f8f17SEtienne Carriere 	session = pkcs11_handle2session(session_handle, client);
609*6e4f8f17SEtienne Carriere 	if (!session)
610*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_SESSION_HANDLE_INVALID;
611*6e4f8f17SEtienne Carriere 
612*6e4f8f17SEtienne Carriere 	close_ck_session(session);
613*6e4f8f17SEtienne Carriere 
614*6e4f8f17SEtienne Carriere 	return PKCS11_CKR_OK;
615*6e4f8f17SEtienne Carriere }
616*6e4f8f17SEtienne Carriere 
617*6e4f8f17SEtienne Carriere uint32_t entry_ck_close_all_sessions(struct pkcs11_client *client,
618*6e4f8f17SEtienne Carriere 				     uint32_t ptypes, TEE_Param *params)
619*6e4f8f17SEtienne Carriere {
620*6e4f8f17SEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
621*6e4f8f17SEtienne Carriere 						TEE_PARAM_TYPE_NONE,
622*6e4f8f17SEtienne Carriere 						TEE_PARAM_TYPE_NONE,
623*6e4f8f17SEtienne Carriere 						TEE_PARAM_TYPE_NONE);
624*6e4f8f17SEtienne Carriere 	TEE_Param *ctrl = &params[0];
625*6e4f8f17SEtienne Carriere 	uint32_t rv = 0;
626*6e4f8f17SEtienne Carriere 	struct serialargs ctrlargs = { };
627*6e4f8f17SEtienne Carriere 	uint32_t token_id = 0;
628*6e4f8f17SEtienne Carriere 	struct ck_token *token = NULL;
629*6e4f8f17SEtienne Carriere 	struct pkcs11_session *session = NULL;
630*6e4f8f17SEtienne Carriere 	struct pkcs11_session *next = NULL;
631*6e4f8f17SEtienne Carriere 
632*6e4f8f17SEtienne Carriere 	if (!client || ptypes != exp_pt)
633*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
634*6e4f8f17SEtienne Carriere 
635*6e4f8f17SEtienne Carriere 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
636*6e4f8f17SEtienne Carriere 
637*6e4f8f17SEtienne Carriere 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
638*6e4f8f17SEtienne Carriere 	if (rv)
639*6e4f8f17SEtienne Carriere 		return rv;
640*6e4f8f17SEtienne Carriere 
641*6e4f8f17SEtienne Carriere 	if (serialargs_remaining_bytes(&ctrlargs))
642*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
643*6e4f8f17SEtienne Carriere 
644*6e4f8f17SEtienne Carriere 	token = get_token(token_id);
645*6e4f8f17SEtienne Carriere 	if (!token)
646*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_SLOT_ID_INVALID;
647*6e4f8f17SEtienne Carriere 
648*6e4f8f17SEtienne Carriere 	DMSG("Close all sessions for PKCS11 token %"PRIu32, token_id);
649*6e4f8f17SEtienne Carriere 
650*6e4f8f17SEtienne Carriere 	TAILQ_FOREACH_SAFE(session, &client->session_list, link, next)
651*6e4f8f17SEtienne Carriere 		if (session->token == token)
652*6e4f8f17SEtienne Carriere 			close_ck_session(session);
653*6e4f8f17SEtienne Carriere 
654*6e4f8f17SEtienne Carriere 	return PKCS11_CKR_OK;
655*6e4f8f17SEtienne Carriere }
656*6e4f8f17SEtienne Carriere 
657*6e4f8f17SEtienne Carriere uint32_t entry_ck_session_info(struct pkcs11_client *client,
658*6e4f8f17SEtienne Carriere 			       uint32_t ptypes, TEE_Param *params)
659*6e4f8f17SEtienne Carriere {
660*6e4f8f17SEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
661*6e4f8f17SEtienne Carriere 						TEE_PARAM_TYPE_NONE,
662*6e4f8f17SEtienne Carriere 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
663*6e4f8f17SEtienne Carriere 						TEE_PARAM_TYPE_NONE);
664*6e4f8f17SEtienne Carriere 	TEE_Param *ctrl = &params[0];
665*6e4f8f17SEtienne Carriere 	TEE_Param *out = &params[2];
666*6e4f8f17SEtienne Carriere 	uint32_t rv = 0;
667*6e4f8f17SEtienne Carriere 	struct serialargs ctrlargs = { };
668*6e4f8f17SEtienne Carriere 	uint32_t session_handle = 0;
669*6e4f8f17SEtienne Carriere 	struct pkcs11_session *session = NULL;
670*6e4f8f17SEtienne Carriere 	struct pkcs11_session_info info = {
671*6e4f8f17SEtienne Carriere 		.flags = PKCS11_CKFSS_SERIAL_SESSION,
672*6e4f8f17SEtienne Carriere 	};
673*6e4f8f17SEtienne Carriere 
674*6e4f8f17SEtienne Carriere 	if (!client || ptypes != exp_pt || out->memref.size != sizeof(info))
675*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
676*6e4f8f17SEtienne Carriere 
677*6e4f8f17SEtienne Carriere 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
678*6e4f8f17SEtienne Carriere 
679*6e4f8f17SEtienne Carriere 	rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
680*6e4f8f17SEtienne Carriere 	if (rv)
681*6e4f8f17SEtienne Carriere 		return rv;
682*6e4f8f17SEtienne Carriere 
683*6e4f8f17SEtienne Carriere 	if (serialargs_remaining_bytes(&ctrlargs))
684*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
685*6e4f8f17SEtienne Carriere 
686*6e4f8f17SEtienne Carriere 	session = pkcs11_handle2session(session_handle, client);
687*6e4f8f17SEtienne Carriere 	if (!session)
688*6e4f8f17SEtienne Carriere 		return PKCS11_CKR_SESSION_HANDLE_INVALID;
689*6e4f8f17SEtienne Carriere 
690*6e4f8f17SEtienne Carriere 	info.slot_id = get_token_id(session->token);
691*6e4f8f17SEtienne Carriere 	info.state = session->state;
692*6e4f8f17SEtienne Carriere 	if (pkcs11_session_is_read_write(session))
693*6e4f8f17SEtienne Carriere 		info.flags |= PKCS11_CKFSS_RW_SESSION;
694*6e4f8f17SEtienne Carriere 
695*6e4f8f17SEtienne Carriere 	TEE_MemMove(out->memref.buffer, &info, sizeof(info));
696*6e4f8f17SEtienne Carriere 
697*6e4f8f17SEtienne Carriere 	DMSG("Get find on PKCS11 session %"PRIu32, session->handle);
698*6e4f8f17SEtienne Carriere 
699*6e4f8f17SEtienne Carriere 	return PKCS11_CKR_OK;
700*6e4f8f17SEtienne Carriere }
701