xref: /optee_os/ta/pkcs11/src/pkcs11_token.c (revision ed3fa831cdd6c545bf2813de8aeccc2564387983)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017-2020, Linaro Limited
4  */
5 
6 #include <assert.h>
7 #include <confine_array_index.h>
8 #include <pkcs11_ta.h>
9 #include <printk.h>
10 #include <string.h>
11 #include <string_ext.h>
12 #include <sys/queue.h>
13 #include <tee_api_types.h>
14 #include <tee_internal_api_extensions.h>
15 #include <util.h>
16 
17 #include "pkcs11_helpers.h"
18 #include "pkcs11_token.h"
19 #include "serializer.h"
20 
21 /* Provide 3 slots/tokens, ID is token index */
22 #ifndef CFG_PKCS11_TA_TOKEN_COUNT
23 #define TOKEN_COUNT		3
24 #else
25 #define TOKEN_COUNT		CFG_PKCS11_TA_TOKEN_COUNT
26 #endif
27 
28 /*
29  * Structure tracking client applications
30  *
31  * @link - chained list of registered client applications
32  * @sessions - list of the PKCS11 sessions opened by the client application
33  */
34 struct pkcs11_client {
35 	TAILQ_ENTRY(pkcs11_client) link;
36 	struct session_list session_list;
37 	struct handle_db session_handle_db;
38 };
39 
40 /* Static allocation of tokens runtime instances (reset to 0 at load) */
41 struct ck_token ck_token[TOKEN_COUNT];
42 
43 static struct client_list pkcs11_client_list =
44 	TAILQ_HEAD_INITIALIZER(pkcs11_client_list);
45 
46 static void close_ck_session(struct pkcs11_session *session);
47 
48 struct ck_token *get_token(unsigned int token_id)
49 {
50 	if (token_id < TOKEN_COUNT)
51 		return &ck_token[confine_array_index(token_id, TOKEN_COUNT)];
52 
53 	return NULL;
54 }
55 
56 unsigned int get_token_id(struct ck_token *token)
57 {
58 	ptrdiff_t id = token - ck_token;
59 
60 	assert(id >= 0 && id < TOKEN_COUNT);
61 	return id;
62 }
63 
64 struct pkcs11_client *tee_session2client(void *tee_session)
65 {
66 	struct pkcs11_client *client = NULL;
67 
68 	TAILQ_FOREACH(client, &pkcs11_client_list, link)
69 		if (client == tee_session)
70 			break;
71 
72 	return client;
73 }
74 
75 struct pkcs11_session *pkcs11_handle2session(uint32_t handle,
76 					     struct pkcs11_client *client)
77 {
78 	return handle_lookup(&client->session_handle_db, handle);
79 }
80 
81 struct pkcs11_client *register_client(void)
82 {
83 	struct pkcs11_client *client = NULL;
84 
85 	client = TEE_Malloc(sizeof(*client), TEE_MALLOC_FILL_ZERO);
86 	if (!client)
87 		return NULL;
88 
89 	TAILQ_INSERT_HEAD(&pkcs11_client_list, client, link);
90 	TAILQ_INIT(&client->session_list);
91 	handle_db_init(&client->session_handle_db);
92 
93 	return client;
94 }
95 
96 void unregister_client(struct pkcs11_client *client)
97 {
98 	struct pkcs11_session *session = NULL;
99 	struct pkcs11_session *next = NULL;
100 
101 	if (!client) {
102 		EMSG("Invalid TEE session handle");
103 		return;
104 	}
105 
106 	TAILQ_FOREACH_SAFE(session, &client->session_list, link, next)
107 		close_ck_session(session);
108 
109 	TAILQ_REMOVE(&pkcs11_client_list, client, link);
110 	handle_db_destroy(&client->session_handle_db);
111 	TEE_Free(client);
112 }
113 
114 static TEE_Result pkcs11_token_init(unsigned int id)
115 {
116 	struct ck_token *token = init_persistent_db(id);
117 
118 	if (!token)
119 		return TEE_ERROR_SECURITY;
120 
121 	if (token->state == PKCS11_TOKEN_RESET) {
122 		/* As per PKCS#11 spec, token resets to read/write state */
123 		token->state = PKCS11_TOKEN_READ_WRITE;
124 		token->session_count = 0;
125 		token->rw_session_count = 0;
126 	}
127 
128 	return TEE_SUCCESS;
129 }
130 
131 TEE_Result pkcs11_init(void)
132 {
133 	unsigned int id = 0;
134 	TEE_Result ret = TEE_ERROR_GENERIC;
135 
136 	for (id = 0; id < TOKEN_COUNT; id++) {
137 		ret = pkcs11_token_init(id);
138 		if (ret)
139 			break;
140 	}
141 
142 	return ret;
143 }
144 
145 void pkcs11_deinit(void)
146 {
147 	unsigned int id = 0;
148 
149 	for (id = 0; id < TOKEN_COUNT; id++)
150 		close_persistent_db(get_token(id));
151 }
152 
153 uint32_t entry_ck_slot_list(uint32_t ptypes, TEE_Param *params)
154 {
155 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
156 						TEE_PARAM_TYPE_NONE,
157 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
158 						TEE_PARAM_TYPE_NONE);
159 	TEE_Param *out = &params[2];
160 	uint32_t token_id = 0;
161 	const size_t out_size = sizeof(token_id) * TOKEN_COUNT;
162 	uint8_t *id = NULL;
163 
164 	if (ptypes != exp_pt ||
165 	    params[0].memref.size != TEE_PARAM0_SIZE_MIN)
166 		return PKCS11_CKR_ARGUMENTS_BAD;
167 
168 	if (out->memref.size < out_size) {
169 		out->memref.size = out_size;
170 
171 		if (out->memref.buffer)
172 			return PKCS11_CKR_BUFFER_TOO_SMALL;
173 		else
174 			return PKCS11_CKR_OK;
175 	}
176 
177 	for (token_id = 0, id = out->memref.buffer; token_id < TOKEN_COUNT;
178 	     token_id++, id += sizeof(token_id))
179 		TEE_MemMove(id, &token_id, sizeof(token_id));
180 
181 	out->memref.size = out_size;
182 
183 	return PKCS11_CKR_OK;
184 }
185 
186 static void pad_str(uint8_t *str, size_t size)
187 {
188 	int n = strnlen((char *)str, size);
189 
190 	TEE_MemFill(str + n, ' ', size - n);
191 }
192 
193 static void set_token_description(struct pkcs11_slot_info *info)
194 {
195 	char desc[sizeof(info->slot_description) + 1] = { 0 };
196 	TEE_UUID dev_id = { };
197 	TEE_Result res = TEE_ERROR_GENERIC;
198 	int n = 0;
199 
200 	res = TEE_GetPropertyAsUUID(TEE_PROPSET_TEE_IMPLEMENTATION,
201 				    "gpd.tee.deviceID", &dev_id);
202 	if (res == TEE_SUCCESS) {
203 		n = snprintk(desc, sizeof(desc), PKCS11_SLOT_DESCRIPTION
204 			     " - TEE UUID %pUl", (void *)&dev_id);
205 	} else {
206 		n = snprintf(desc, sizeof(desc), PKCS11_SLOT_DESCRIPTION
207 			     " - No TEE UUID");
208 	}
209 	if (n < 0 || n >= (int)sizeof(desc))
210 		TEE_Panic(0);
211 
212 	TEE_MemMove(info->slot_description, desc, n);
213 	pad_str(info->slot_description, sizeof(info->slot_description));
214 }
215 
216 uint32_t entry_ck_slot_info(uint32_t ptypes, TEE_Param *params)
217 {
218 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
219 						TEE_PARAM_TYPE_NONE,
220 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
221 						TEE_PARAM_TYPE_NONE);
222 	TEE_Param *ctrl = &params[0];
223 	TEE_Param *out = &params[2];
224 	uint32_t rv = 0;
225 	struct serialargs ctrlargs = { };
226 	uint32_t token_id = 0;
227 	struct pkcs11_slot_info info = {
228 		.slot_description = PKCS11_SLOT_DESCRIPTION,
229 		.manufacturer_id = PKCS11_SLOT_MANUFACTURER,
230 		.flags = PKCS11_CKFS_TOKEN_PRESENT,
231 		.hardware_version = PKCS11_SLOT_HW_VERSION,
232 		.firmware_version = PKCS11_SLOT_FW_VERSION,
233 	};
234 
235 	COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_DESCRIPTION) <=
236 			    sizeof(info.slot_description));
237 	COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_MANUFACTURER) <=
238 			    sizeof(info.manufacturer_id));
239 
240 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
241 		return PKCS11_CKR_ARGUMENTS_BAD;
242 
243 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
244 
245 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
246 	if (rv)
247 		return rv;
248 
249 	if (serialargs_remaining_bytes(&ctrlargs))
250 		return PKCS11_CKR_ARGUMENTS_BAD;
251 
252 	if (!get_token(token_id))
253 		return PKCS11_CKR_SLOT_ID_INVALID;
254 
255 	set_token_description(&info);
256 
257 	pad_str(info.manufacturer_id, sizeof(info.manufacturer_id));
258 
259 	out->memref.size = sizeof(info);
260 	TEE_MemMove(out->memref.buffer, &info, out->memref.size);
261 
262 	return PKCS11_CKR_OK;
263 }
264 
265 uint32_t entry_ck_token_info(uint32_t ptypes, TEE_Param *params)
266 {
267 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
268 						TEE_PARAM_TYPE_NONE,
269 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
270 						TEE_PARAM_TYPE_NONE);
271 	TEE_Param *ctrl = &params[0];
272 	TEE_Param *out = &params[2];
273 	uint32_t rv = 0;
274 	struct serialargs ctrlargs = { };
275 	uint32_t token_id = 0;
276 	struct ck_token *token = NULL;
277 	struct pkcs11_token_info info = {
278 		.manufacturer_id = PKCS11_TOKEN_MANUFACTURER,
279 		.model = PKCS11_TOKEN_MODEL,
280 		.max_session_count = UINT32_MAX,
281 		.max_rw_session_count = UINT32_MAX,
282 		.max_pin_len = PKCS11_TOKEN_PIN_SIZE_MAX,
283 		.min_pin_len = PKCS11_TOKEN_PIN_SIZE_MIN,
284 		.total_public_memory = UINT32_MAX,
285 		.free_public_memory = UINT32_MAX,
286 		.total_private_memory = UINT32_MAX,
287 		.free_private_memory = UINT32_MAX,
288 		.hardware_version = PKCS11_TOKEN_HW_VERSION,
289 		.firmware_version = PKCS11_TOKEN_FW_VERSION,
290 	};
291 	char sn[sizeof(info.serial_number) + 1] = { 0 };
292 	int n = 0;
293 
294 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
295 		return PKCS11_CKR_ARGUMENTS_BAD;
296 
297 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
298 
299 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
300 	if (rv)
301 		return rv;
302 
303 	if (serialargs_remaining_bytes(&ctrlargs))
304 		return PKCS11_CKR_ARGUMENTS_BAD;
305 
306 	token = get_token(token_id);
307 	if (!token)
308 		return PKCS11_CKR_SLOT_ID_INVALID;
309 
310 	pad_str(info.manufacturer_id, sizeof(info.manufacturer_id));
311 	pad_str(info.model, sizeof(info.model));
312 
313 	n = snprintf(sn, sizeof(sn), "%0*"PRIu32,
314 		     (int)sizeof(info.serial_number), token_id);
315 	if (n != (int)sizeof(info.serial_number))
316 		TEE_Panic(0);
317 
318 	TEE_MemMove(info.serial_number, sn, sizeof(info.serial_number));
319 	pad_str(info.serial_number, sizeof(info.serial_number));
320 
321 	TEE_MemMove(info.label, token->db_main->label, sizeof(info.label));
322 
323 	info.flags = token->db_main->flags;
324 	info.session_count = token->session_count;
325 	info.rw_session_count = token->rw_session_count;
326 
327 	TEE_MemMove(out->memref.buffer, &info, sizeof(info));
328 
329 	return PKCS11_CKR_OK;
330 }
331 
332 static void dmsg_print_supported_mechanism(unsigned int token_id __maybe_unused,
333 					   uint32_t *array __maybe_unused,
334 					   size_t count __maybe_unused)
335 {
336 	size_t __maybe_unused n = 0;
337 
338 	if (TRACE_LEVEL < TRACE_DEBUG)
339 		return;
340 
341 	for (n = 0; n < count; n++)
342 		DMSG("PKCS11 token %"PRIu32": mechanism 0x%04"PRIx32": %s",
343 		     token_id, array[n], id2str_mechanism(array[n]));
344 }
345 
346 uint32_t entry_ck_token_mecha_ids(uint32_t ptypes, TEE_Param *params)
347 {
348 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
349 						TEE_PARAM_TYPE_NONE,
350 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
351 						TEE_PARAM_TYPE_NONE);
352 	TEE_Param *ctrl = &params[0];
353 	TEE_Param *out = &params[2];
354 	uint32_t rv = 0;
355 	struct serialargs ctrlargs = { };
356 	uint32_t token_id = 0;
357 	struct ck_token __maybe_unused *token = NULL;
358 	size_t count = 0;
359 	uint32_t *array = NULL;
360 
361 	if (ptypes != exp_pt)
362 		return PKCS11_CKR_ARGUMENTS_BAD;
363 
364 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
365 
366 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
367 	if (rv)
368 		return rv;
369 
370 	if (serialargs_remaining_bytes(&ctrlargs))
371 		return PKCS11_CKR_ARGUMENTS_BAD;
372 
373 	token = get_token(token_id);
374 	if (!token)
375 		return PKCS11_CKR_SLOT_ID_INVALID;
376 
377 	count = out->memref.size / sizeof(*array);
378 	array = tee_malloc_mechanism_list(&count);
379 
380 	if (out->memref.size < count * sizeof(*array)) {
381 		assert(!array);
382 		out->memref.size = count * sizeof(*array);
383 		if (out->memref.buffer)
384 			return PKCS11_CKR_BUFFER_TOO_SMALL;
385 		else
386 			return PKCS11_CKR_OK;
387 	}
388 
389 	if (!array)
390 		return PKCS11_CKR_DEVICE_MEMORY;
391 
392 	dmsg_print_supported_mechanism(token_id, array, count);
393 
394 	out->memref.size = count * sizeof(*array);
395 	TEE_MemMove(out->memref.buffer, array, out->memref.size);
396 
397 	TEE_Free(array);
398 
399 	return rv;
400 }
401 
402 static void supported_mechanism_key_size(uint32_t proc_id,
403 					 uint32_t *max_key_size,
404 					 uint32_t *min_key_size)
405 {
406 	switch (proc_id) {
407 	/* Will be filled once TA supports mechanisms */
408 	default:
409 		*min_key_size = 0;
410 		*max_key_size = 0;
411 		break;
412 	}
413 }
414 
415 uint32_t entry_ck_token_mecha_info(uint32_t ptypes, TEE_Param *params)
416 {
417 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
418 						TEE_PARAM_TYPE_NONE,
419 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
420 						TEE_PARAM_TYPE_NONE);
421 	TEE_Param *ctrl = &params[0];
422 	TEE_Param *out = &params[2];
423 	uint32_t rv = 0;
424 	struct serialargs ctrlargs = { };
425 	uint32_t token_id = 0;
426 	uint32_t type = 0;
427 	struct ck_token *token = NULL;
428 	struct pkcs11_mechanism_info info = { };
429 
430 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
431 		return PKCS11_CKR_ARGUMENTS_BAD;
432 
433 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
434 
435 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
436 	if (rv)
437 		return rv;
438 
439 	rv = serialargs_get(&ctrlargs, &type, sizeof(uint32_t));
440 	if (rv)
441 		return rv;
442 
443 	if (serialargs_remaining_bytes(&ctrlargs))
444 		return PKCS11_CKR_ARGUMENTS_BAD;
445 
446 	token = get_token(token_id);
447 	if (!token)
448 		return PKCS11_CKR_SLOT_ID_INVALID;
449 
450 	if (!mechanism_is_valid(type))
451 		return PKCS11_CKR_MECHANISM_INVALID;
452 
453 	info.flags = mechanism_supported_flags(type);
454 
455 	supported_mechanism_key_size(type, &info.min_key_size,
456 				     &info.max_key_size);
457 
458 	TEE_MemMove(out->memref.buffer, &info, sizeof(info));
459 
460 	DMSG("PKCS11 token %"PRIu32": mechanism 0x%"PRIx32" info",
461 	     token_id, type);
462 
463 	return PKCS11_CKR_OK;
464 }
465 
466 /* Select the ReadOnly or ReadWrite state for session login state */
467 static void set_session_state(struct pkcs11_client *client,
468 			      struct pkcs11_session *session, bool readonly)
469 {
470 	struct pkcs11_session *sess = NULL;
471 	enum pkcs11_session_state state = PKCS11_CKS_RO_PUBLIC_SESSION;
472 
473 	/* Default to public session if no session already registered */
474 	if (readonly)
475 		state = PKCS11_CKS_RO_PUBLIC_SESSION;
476 	else
477 		state = PKCS11_CKS_RW_PUBLIC_SESSION;
478 
479 	/*
480 	 * No need to check all client sessions, the first found in
481 	 * target token gives client login configuration.
482 	 */
483 	TAILQ_FOREACH(sess, &client->session_list, link) {
484 		assert(sess != session);
485 
486 		if (sess->token == session->token) {
487 			switch (sess->state) {
488 			case PKCS11_CKS_RW_PUBLIC_SESSION:
489 			case PKCS11_CKS_RO_PUBLIC_SESSION:
490 				if (readonly)
491 					state = PKCS11_CKS_RO_PUBLIC_SESSION;
492 				else
493 					state = PKCS11_CKS_RW_PUBLIC_SESSION;
494 				break;
495 			case PKCS11_CKS_RO_USER_FUNCTIONS:
496 			case PKCS11_CKS_RW_USER_FUNCTIONS:
497 				if (readonly)
498 					state = PKCS11_CKS_RO_USER_FUNCTIONS;
499 				else
500 					state = PKCS11_CKS_RW_USER_FUNCTIONS;
501 				break;
502 			case PKCS11_CKS_RW_SO_FUNCTIONS:
503 				if (readonly)
504 					TEE_Panic(0);
505 				else
506 					state = PKCS11_CKS_RW_SO_FUNCTIONS;
507 				break;
508 			default:
509 				TEE_Panic(0);
510 			}
511 			break;
512 		}
513 	}
514 
515 	session->state = state;
516 }
517 
518 uint32_t entry_ck_open_session(struct pkcs11_client *client,
519 			       uint32_t ptypes, TEE_Param *params)
520 {
521 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
522 						TEE_PARAM_TYPE_NONE,
523 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
524 						TEE_PARAM_TYPE_NONE);
525 	TEE_Param *ctrl = &params[0];
526 	TEE_Param *out = &params[2];
527 	uint32_t rv = 0;
528 	struct serialargs ctrlargs = { };
529 	uint32_t token_id = 0;
530 	uint32_t flags = 0;
531 	struct ck_token *token = NULL;
532 	struct pkcs11_session *session = NULL;
533 	bool readonly = false;
534 
535 	if (!client || ptypes != exp_pt ||
536 	    out->memref.size != sizeof(session->handle))
537 		return PKCS11_CKR_ARGUMENTS_BAD;
538 
539 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
540 
541 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
542 	if (rv)
543 		return rv;
544 
545 	rv = serialargs_get(&ctrlargs, &flags, sizeof(flags));
546 	if (rv)
547 		return rv;
548 
549 	if (serialargs_remaining_bytes(&ctrlargs))
550 		return PKCS11_CKR_ARGUMENTS_BAD;
551 
552 	token = get_token(token_id);
553 	if (!token)
554 		return PKCS11_CKR_SLOT_ID_INVALID;
555 
556 	/* Sanitize session flags */
557 	if (!(flags & PKCS11_CKFSS_SERIAL_SESSION) ||
558 	    (flags & ~(PKCS11_CKFSS_RW_SESSION |
559 		       PKCS11_CKFSS_SERIAL_SESSION)))
560 		return PKCS11_CKR_ARGUMENTS_BAD;
561 
562 	readonly = !(flags & PKCS11_CKFSS_RW_SESSION);
563 
564 	if (!readonly && token->state == PKCS11_TOKEN_READ_ONLY)
565 		return PKCS11_CKR_TOKEN_WRITE_PROTECTED;
566 
567 	if (readonly) {
568 		/* Specifically reject read-only session under SO login */
569 		TAILQ_FOREACH(session, &client->session_list, link)
570 			if (pkcs11_session_is_so(session))
571 				return PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS;
572 	}
573 
574 	session = TEE_Malloc(sizeof(*session), TEE_MALLOC_FILL_ZERO);
575 	if (!session)
576 		return PKCS11_CKR_DEVICE_MEMORY;
577 
578 	session->handle = handle_get(&client->session_handle_db, session);
579 	if (!session->handle) {
580 		TEE_Free(session);
581 		return PKCS11_CKR_DEVICE_MEMORY;
582 	}
583 
584 	session->token = token;
585 	session->client = client;
586 
587 	set_session_state(client, session, readonly);
588 
589 	TAILQ_INSERT_HEAD(&client->session_list, session, link);
590 
591 	session->token->session_count++;
592 	if (!readonly)
593 		session->token->rw_session_count++;
594 
595 	TEE_MemMove(out->memref.buffer, &session->handle,
596 		    sizeof(session->handle));
597 
598 	DMSG("Open PKCS11 session %"PRIu32, session->handle);
599 
600 	return PKCS11_CKR_OK;
601 }
602 
603 static void close_ck_session(struct pkcs11_session *session)
604 {
605 	TAILQ_REMOVE(&session->client->session_list, session, link);
606 	handle_put(&session->client->session_handle_db, session->handle);
607 
608 	session->token->session_count--;
609 	if (pkcs11_session_is_read_write(session))
610 		session->token->rw_session_count--;
611 
612 	TEE_Free(session);
613 
614 	DMSG("Close PKCS11 session %"PRIu32, session->handle);
615 }
616 
617 uint32_t entry_ck_close_session(struct pkcs11_client *client,
618 				uint32_t ptypes, TEE_Param *params)
619 {
620 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
621 						TEE_PARAM_TYPE_NONE,
622 						TEE_PARAM_TYPE_NONE,
623 						TEE_PARAM_TYPE_NONE);
624 	TEE_Param *ctrl = &params[0];
625 	uint32_t rv = 0;
626 	struct serialargs ctrlargs = { };
627 	struct pkcs11_session *session = NULL;
628 
629 	if (!client || ptypes != exp_pt)
630 		return PKCS11_CKR_ARGUMENTS_BAD;
631 
632 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
633 
634 	rv = serialargs_get_session_from_handle(&ctrlargs, client, &session);
635 	if (rv)
636 		return rv;
637 
638 	if (serialargs_remaining_bytes(&ctrlargs))
639 		return PKCS11_CKR_ARGUMENTS_BAD;
640 
641 	close_ck_session(session);
642 
643 	return PKCS11_CKR_OK;
644 }
645 
646 uint32_t entry_ck_close_all_sessions(struct pkcs11_client *client,
647 				     uint32_t ptypes, TEE_Param *params)
648 {
649 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
650 						TEE_PARAM_TYPE_NONE,
651 						TEE_PARAM_TYPE_NONE,
652 						TEE_PARAM_TYPE_NONE);
653 	TEE_Param *ctrl = &params[0];
654 	uint32_t rv = 0;
655 	struct serialargs ctrlargs = { };
656 	uint32_t token_id = 0;
657 	struct ck_token *token = NULL;
658 	struct pkcs11_session *session = NULL;
659 	struct pkcs11_session *next = NULL;
660 
661 	if (!client || ptypes != exp_pt)
662 		return PKCS11_CKR_ARGUMENTS_BAD;
663 
664 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
665 
666 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
667 	if (rv)
668 		return rv;
669 
670 	if (serialargs_remaining_bytes(&ctrlargs))
671 		return PKCS11_CKR_ARGUMENTS_BAD;
672 
673 	token = get_token(token_id);
674 	if (!token)
675 		return PKCS11_CKR_SLOT_ID_INVALID;
676 
677 	DMSG("Close all sessions for PKCS11 token %"PRIu32, token_id);
678 
679 	TAILQ_FOREACH_SAFE(session, &client->session_list, link, next)
680 		if (session->token == token)
681 			close_ck_session(session);
682 
683 	return PKCS11_CKR_OK;
684 }
685 
686 uint32_t entry_ck_session_info(struct pkcs11_client *client,
687 			       uint32_t ptypes, TEE_Param *params)
688 {
689 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
690 						TEE_PARAM_TYPE_NONE,
691 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
692 						TEE_PARAM_TYPE_NONE);
693 	TEE_Param *ctrl = &params[0];
694 	TEE_Param *out = &params[2];
695 	uint32_t rv = 0;
696 	struct serialargs ctrlargs = { };
697 	struct pkcs11_session *session = NULL;
698 	struct pkcs11_session_info info = {
699 		.flags = PKCS11_CKFSS_SERIAL_SESSION,
700 	};
701 
702 	if (!client || ptypes != exp_pt || out->memref.size != sizeof(info))
703 		return PKCS11_CKR_ARGUMENTS_BAD;
704 
705 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
706 
707 	rv = serialargs_get_session_from_handle(&ctrlargs, client, &session);
708 	if (rv)
709 		return rv;
710 
711 	if (serialargs_remaining_bytes(&ctrlargs))
712 		return PKCS11_CKR_ARGUMENTS_BAD;
713 
714 	info.slot_id = get_token_id(session->token);
715 	info.state = session->state;
716 	if (pkcs11_session_is_read_write(session))
717 		info.flags |= PKCS11_CKFSS_RW_SESSION;
718 
719 	TEE_MemMove(out->memref.buffer, &info, sizeof(info));
720 
721 	DMSG("Get find on PKCS11 session %"PRIu32, session->handle);
722 
723 	return PKCS11_CKR_OK;
724 }
725 
726 uint32_t entry_ck_token_initialize(uint32_t ptypes, TEE_Param *params)
727 {
728 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
729 						TEE_PARAM_TYPE_NONE,
730 						TEE_PARAM_TYPE_NONE,
731 						TEE_PARAM_TYPE_NONE);
732 	char label[PKCS11_TOKEN_LABEL_SIZE] = { 0 };
733 	struct pkcs11_client *client = NULL;
734 	struct pkcs11_session *sess = NULL;
735 	enum pkcs11_rc rc = PKCS11_CKR_OK;
736 	struct serialargs ctrlargs = { };
737 	struct ck_token *token = NULL;
738 	TEE_Param *ctrl = params;
739 	uint32_t token_id = 0;
740 	uint32_t pin_size = 0;
741 	void *pin = NULL;
742 
743 	if (ptypes != exp_pt)
744 		return PKCS11_CKR_ARGUMENTS_BAD;
745 
746 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
747 
748 	rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
749 	if (rc)
750 		return rc;
751 
752 	rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
753 	if (rc)
754 		return rc;
755 
756 	rc = serialargs_get(&ctrlargs, &label, PKCS11_TOKEN_LABEL_SIZE);
757 	if (rc)
758 		return rc;
759 
760 	rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
761 	if (rc)
762 		return rc;
763 
764 	if (serialargs_remaining_bytes(&ctrlargs))
765 		return PKCS11_CKR_ARGUMENTS_BAD;
766 
767 	token = get_token(token_id);
768 	if (!token)
769 		return PKCS11_CKR_SLOT_ID_INVALID;
770 
771 	if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) {
772 		IMSG("Token %"PRIu32": SO PIN locked", token_id);
773 		return PKCS11_CKR_PIN_LOCKED;
774 	}
775 
776 	/* Check there's no open session on this token */
777 	TAILQ_FOREACH(client, &pkcs11_client_list, link)
778 		TAILQ_FOREACH(sess, &client->session_list, link)
779 			if (sess->token == token)
780 				return PKCS11_CKR_SESSION_EXISTS;
781 
782 	if (!token->db_main->so_pin_salt) {
783 		/*
784 		 * The spec doesn't permit returning
785 		 * PKCS11_CKR_PIN_LEN_RANGE for this function, take another
786 		 * error code.
787 		 */
788 		if (pin_size < PKCS11_TOKEN_PIN_SIZE_MIN ||
789 		    pin_size > PKCS11_TOKEN_PIN_SIZE_MAX)
790 			return PKCS11_CKR_ARGUMENTS_BAD;
791 
792 		rc = hash_pin(PKCS11_CKU_SO, pin, pin_size,
793 			      &token->db_main->so_pin_salt,
794 			      token->db_main->so_pin_hash);
795 		if (rc)
796 			return rc;
797 
798 		update_persistent_db(token);
799 
800 		goto inited;
801 	}
802 
803 	rc = verify_pin(PKCS11_CKU_SO, pin, pin_size,
804 			token->db_main->so_pin_salt,
805 			token->db_main->so_pin_hash);
806 	if (rc) {
807 		unsigned int pin_count = 0;
808 
809 		if (rc != PKCS11_CKR_PIN_INCORRECT)
810 			return rc;
811 
812 		token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW;
813 		token->db_main->so_pin_count++;
814 
815 		pin_count = token->db_main->so_pin_count;
816 		if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1)
817 			token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY;
818 		if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX)
819 			token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED;
820 
821 		update_persistent_db(token);
822 
823 		return PKCS11_CKR_PIN_INCORRECT;
824 	}
825 
826 	token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW |
827 				   PKCS11_CKFT_SO_PIN_FINAL_TRY);
828 	token->db_main->so_pin_count = 0;
829 
830 inited:
831 	TEE_MemMove(token->db_main->label, label, PKCS11_TOKEN_LABEL_SIZE);
832 	token->db_main->flags |= PKCS11_CKFT_TOKEN_INITIALIZED;
833 	/* Reset user PIN */
834 	token->db_main->user_pin_salt = 0;
835 	token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_INITIALIZED |
836 				   PKCS11_CKFT_USER_PIN_COUNT_LOW |
837 				   PKCS11_CKFT_USER_PIN_FINAL_TRY |
838 				   PKCS11_CKFT_USER_PIN_LOCKED |
839 				   PKCS11_CKFT_USER_PIN_TO_BE_CHANGED);
840 
841 	update_persistent_db(token);
842 
843 	IMSG("PKCS11 token %"PRIu32": initialized", token_id);
844 
845 	return PKCS11_CKR_OK;
846 }
847 
848 static enum pkcs11_rc set_pin(struct pkcs11_session *session,
849 			      uint8_t *new_pin, size_t new_pin_size,
850 			      enum pkcs11_user_type user_type)
851 {
852 	enum pkcs11_rc rc = PKCS11_CKR_OK;
853 	uint32_t flags_clear = 0;
854 	uint32_t flags_set = 0;
855 
856 	if (session->token->db_main->flags & PKCS11_CKFT_WRITE_PROTECTED)
857 		return PKCS11_CKR_TOKEN_WRITE_PROTECTED;
858 
859 	if (!pkcs11_session_is_read_write(session))
860 		return PKCS11_CKR_SESSION_READ_ONLY;
861 
862 	if (new_pin_size < PKCS11_TOKEN_PIN_SIZE_MIN ||
863 	    new_pin_size > PKCS11_TOKEN_PIN_SIZE_MAX)
864 		return PKCS11_CKR_PIN_LEN_RANGE;
865 
866 	switch (user_type) {
867 	case PKCS11_CKU_SO:
868 		rc = hash_pin(user_type, new_pin, new_pin_size,
869 			      &session->token->db_main->so_pin_salt,
870 			      session->token->db_main->so_pin_hash);
871 		if (rc)
872 			return rc;
873 		session->token->db_main->so_pin_count = 0;
874 		flags_clear = PKCS11_CKFT_SO_PIN_COUNT_LOW |
875 			      PKCS11_CKFT_SO_PIN_FINAL_TRY |
876 			      PKCS11_CKFT_SO_PIN_LOCKED |
877 			      PKCS11_CKFT_SO_PIN_TO_BE_CHANGED;
878 		break;
879 	case PKCS11_CKU_USER:
880 		rc = hash_pin(user_type, new_pin, new_pin_size,
881 			      &session->token->db_main->user_pin_salt,
882 			      session->token->db_main->user_pin_hash);
883 		if (rc)
884 			return rc;
885 		session->token->db_main->user_pin_count = 0;
886 		flags_clear = PKCS11_CKFT_USER_PIN_COUNT_LOW |
887 			      PKCS11_CKFT_USER_PIN_FINAL_TRY |
888 			      PKCS11_CKFT_USER_PIN_LOCKED |
889 			      PKCS11_CKFT_USER_PIN_TO_BE_CHANGED;
890 		flags_set = PKCS11_CKFT_USER_PIN_INITIALIZED;
891 		break;
892 	default:
893 		return PKCS11_CKR_FUNCTION_FAILED;
894 	}
895 
896 	session->token->db_main->flags &= ~flags_clear;
897 	session->token->db_main->flags |= flags_set;
898 
899 	update_persistent_db(session->token);
900 
901 	return PKCS11_CKR_OK;
902 }
903 
904 uint32_t entry_ck_init_pin(struct pkcs11_client *client,
905 			   uint32_t ptypes, TEE_Param *params)
906 {
907 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
908 						TEE_PARAM_TYPE_NONE,
909 						TEE_PARAM_TYPE_NONE,
910 						TEE_PARAM_TYPE_NONE);
911 	struct pkcs11_session *session = NULL;
912 	enum pkcs11_rc rc = PKCS11_CKR_OK;
913 	struct serialargs ctrlargs = { };
914 	TEE_Param *ctrl = params;
915 	uint32_t pin_size = 0;
916 	void *pin = NULL;
917 
918 	if (!client || ptypes != exp_pt)
919 		return PKCS11_CKR_ARGUMENTS_BAD;
920 
921 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
922 
923 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
924 	if (rc)
925 		return rc;
926 
927 	rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
928 	if (rc)
929 		return rc;
930 
931 	rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
932 	if (rc)
933 		return rc;
934 
935 	if (serialargs_remaining_bytes(&ctrlargs))
936 		return PKCS11_CKR_ARGUMENTS_BAD;
937 
938 	if (!pkcs11_session_is_so(session))
939 		return PKCS11_CKR_USER_NOT_LOGGED_IN;
940 
941 	assert(session->token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED);
942 
943 	IMSG("PKCS11 session %"PRIu32": init PIN", session->handle);
944 
945 	return set_pin(session, pin, pin_size, PKCS11_CKU_USER);
946 }
947 
948 static uint32_t check_so_pin(struct pkcs11_session *session,
949 			     uint8_t *pin, size_t pin_size)
950 {
951 	struct ck_token *token = session->token;
952 	enum pkcs11_rc rc = PKCS11_CKR_OK;
953 
954 	assert(token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED);
955 
956 	if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED)
957 		return PKCS11_CKR_PIN_LOCKED;
958 
959 	rc = verify_pin(PKCS11_CKU_SO, pin, pin_size,
960 			token->db_main->so_pin_salt,
961 			token->db_main->so_pin_hash);
962 	if (rc) {
963 		unsigned int pin_count = 0;
964 
965 		if (rc != PKCS11_CKR_PIN_INCORRECT)
966 			return rc;
967 
968 		token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW;
969 		token->db_main->so_pin_count++;
970 
971 		pin_count = token->db_main->so_pin_count;
972 		if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1)
973 			token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY;
974 		if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX)
975 			token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED;
976 
977 		update_persistent_db(token);
978 
979 		if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED)
980 			return PKCS11_CKR_PIN_LOCKED;
981 
982 		return PKCS11_CKR_PIN_INCORRECT;
983 	}
984 
985 	if (token->db_main->so_pin_count) {
986 		token->db_main->so_pin_count = 0;
987 
988 		update_persistent_db(token);
989 	}
990 
991 	if (token->db_main->flags & (PKCS11_CKFT_SO_PIN_COUNT_LOW |
992 				     PKCS11_CKFT_SO_PIN_FINAL_TRY)) {
993 		token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW |
994 					   PKCS11_CKFT_SO_PIN_FINAL_TRY);
995 
996 		update_persistent_db(token);
997 	}
998 
999 	return PKCS11_CKR_OK;
1000 }
1001 
1002 static uint32_t check_user_pin(struct pkcs11_session *session,
1003 			       uint8_t *pin, size_t pin_size)
1004 {
1005 	struct ck_token *token = session->token;
1006 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1007 
1008 	if (!token->db_main->user_pin_salt)
1009 		return PKCS11_CKR_USER_PIN_NOT_INITIALIZED;
1010 
1011 	if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED)
1012 		return PKCS11_CKR_PIN_LOCKED;
1013 
1014 	rc = verify_pin(PKCS11_CKU_USER, pin, pin_size,
1015 			token->db_main->user_pin_salt,
1016 			token->db_main->user_pin_hash);
1017 	if (rc) {
1018 		unsigned int pin_count = 0;
1019 
1020 		if (rc != PKCS11_CKR_PIN_INCORRECT)
1021 			return rc;
1022 
1023 		token->db_main->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW;
1024 		token->db_main->user_pin_count++;
1025 
1026 		pin_count = token->db_main->user_pin_count;
1027 		if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1)
1028 			token->db_main->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY;
1029 		if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX)
1030 			token->db_main->flags |= PKCS11_CKFT_USER_PIN_LOCKED;
1031 
1032 		update_persistent_db(token);
1033 
1034 		if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED)
1035 			return PKCS11_CKR_PIN_LOCKED;
1036 
1037 		return PKCS11_CKR_PIN_INCORRECT;
1038 	}
1039 
1040 	if (token->db_main->user_pin_count) {
1041 		token->db_main->user_pin_count = 0;
1042 
1043 		update_persistent_db(token);
1044 	}
1045 
1046 	if (token->db_main->flags & (PKCS11_CKFT_USER_PIN_COUNT_LOW |
1047 				     PKCS11_CKFT_USER_PIN_FINAL_TRY)) {
1048 		token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_COUNT_LOW |
1049 					   PKCS11_CKFT_USER_PIN_FINAL_TRY);
1050 
1051 		update_persistent_db(token);
1052 	}
1053 
1054 	return PKCS11_CKR_OK;
1055 }
1056 
1057 uint32_t entry_ck_set_pin(struct pkcs11_client *client,
1058 			  uint32_t ptypes, TEE_Param *params)
1059 {
1060 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1061 						TEE_PARAM_TYPE_NONE,
1062 						TEE_PARAM_TYPE_NONE,
1063 						TEE_PARAM_TYPE_NONE);
1064 	struct pkcs11_session *session = NULL;
1065 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1066 	struct serialargs ctrlargs = { };
1067 	uint32_t old_pin_size = 0;
1068 	TEE_Param *ctrl = params;
1069 	uint32_t pin_size = 0;
1070 	void *old_pin = NULL;
1071 	void *pin = NULL;
1072 
1073 	if (!client || ptypes != exp_pt)
1074 		return PKCS11_CKR_ARGUMENTS_BAD;
1075 
1076 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1077 
1078 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1079 	if (rc)
1080 		return rc;
1081 
1082 	rc = serialargs_get(&ctrlargs, &old_pin_size, sizeof(uint32_t));
1083 	if (rc)
1084 		return rc;
1085 
1086 	rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
1087 	if (rc)
1088 		return rc;
1089 
1090 	rc = serialargs_get_ptr(&ctrlargs, &old_pin, old_pin_size);
1091 	if (rc)
1092 		return rc;
1093 
1094 	rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
1095 	if (rc)
1096 		return rc;
1097 
1098 	if (serialargs_remaining_bytes(&ctrlargs))
1099 		return PKCS11_CKR_ARGUMENTS_BAD;
1100 
1101 	if (!pkcs11_session_is_read_write(session))
1102 		return PKCS11_CKR_SESSION_READ_ONLY;
1103 
1104 	if (pkcs11_session_is_so(session)) {
1105 		if (!(session->token->db_main->flags &
1106 		      PKCS11_CKFT_TOKEN_INITIALIZED))
1107 			return PKCS11_CKR_GENERAL_ERROR;
1108 
1109 		rc = check_so_pin(session, old_pin, old_pin_size);
1110 		if (rc)
1111 			return rc;
1112 
1113 		IMSG("PKCS11 session %"PRIu32": set PIN", session->handle);
1114 
1115 		return set_pin(session, pin, pin_size, PKCS11_CKU_SO);
1116 	}
1117 
1118 	if (!(session->token->db_main->flags &
1119 	      PKCS11_CKFT_USER_PIN_INITIALIZED))
1120 		return PKCS11_CKR_GENERAL_ERROR;
1121 
1122 	rc = check_user_pin(session, old_pin, old_pin_size);
1123 	if (rc)
1124 		return rc;
1125 
1126 	IMSG("PKCS11 session %"PRIu32": set PIN", session->handle);
1127 
1128 	return set_pin(session, pin, pin_size, PKCS11_CKU_USER);
1129 }
1130 
1131 static void session_login_user(struct pkcs11_session *session)
1132 {
1133 	struct pkcs11_client *client = session->client;
1134 	struct pkcs11_session *sess = NULL;
1135 
1136 	TAILQ_FOREACH(sess, &client->session_list, link) {
1137 		if (sess->token != session->token)
1138 			continue;
1139 
1140 		if (pkcs11_session_is_read_write(sess))
1141 			sess->state = PKCS11_CKS_RW_USER_FUNCTIONS;
1142 		else
1143 			sess->state = PKCS11_CKS_RO_USER_FUNCTIONS;
1144 	}
1145 }
1146 
1147 static void session_login_so(struct pkcs11_session *session)
1148 {
1149 	struct pkcs11_client *client = session->client;
1150 	struct pkcs11_session *sess = NULL;
1151 
1152 	TAILQ_FOREACH(sess, &client->session_list, link) {
1153 		if (sess->token != session->token)
1154 			continue;
1155 
1156 		if (pkcs11_session_is_read_write(sess))
1157 			sess->state = PKCS11_CKS_RW_SO_FUNCTIONS;
1158 		else
1159 			TEE_Panic(0);
1160 	}
1161 }
1162 
1163 static void session_logout(struct pkcs11_session *session)
1164 {
1165 	struct pkcs11_client *client = session->client;
1166 	struct pkcs11_session *sess = NULL;
1167 
1168 	TAILQ_FOREACH(sess, &client->session_list, link) {
1169 		if (sess->token != session->token)
1170 			continue;
1171 
1172 		if (pkcs11_session_is_read_write(sess))
1173 			sess->state = PKCS11_CKS_RW_PUBLIC_SESSION;
1174 		else
1175 			sess->state = PKCS11_CKS_RO_PUBLIC_SESSION;
1176 	}
1177 }
1178 
1179 uint32_t entry_ck_login(struct pkcs11_client *client,
1180 			uint32_t ptypes, TEE_Param *params)
1181 {
1182 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1183 						TEE_PARAM_TYPE_NONE,
1184 						TEE_PARAM_TYPE_NONE,
1185 						TEE_PARAM_TYPE_NONE);
1186 	struct pkcs11_session *session = NULL;
1187 	struct pkcs11_session *sess = NULL;
1188 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1189 	struct serialargs ctrlargs = { };
1190 	TEE_Param *ctrl = params;
1191 	uint32_t user_type = 0;
1192 	uint32_t pin_size = 0;
1193 	void *pin = NULL;
1194 
1195 	if (!client || ptypes != exp_pt)
1196 		return PKCS11_CKR_ARGUMENTS_BAD;
1197 
1198 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1199 
1200 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1201 	if (rc)
1202 		return rc;
1203 
1204 	rc = serialargs_get(&ctrlargs, &user_type, sizeof(uint32_t));
1205 	if (rc)
1206 		return rc;
1207 
1208 	rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
1209 	if (rc)
1210 		return rc;
1211 
1212 	rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
1213 	if (rc)
1214 		return rc;
1215 
1216 	if (serialargs_remaining_bytes(&ctrlargs))
1217 		return PKCS11_CKR_ARGUMENTS_BAD;
1218 
1219 	switch (user_type) {
1220 	case PKCS11_CKU_SO:
1221 		if (pkcs11_session_is_so(session))
1222 			return PKCS11_CKR_USER_ALREADY_LOGGED_IN;
1223 
1224 		if (pkcs11_session_is_user(session))
1225 			return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
1226 
1227 		TAILQ_FOREACH(sess, &client->session_list, link)
1228 			if (sess->token == session->token &&
1229 			    !pkcs11_session_is_read_write(sess))
1230 				return PKCS11_CKR_SESSION_READ_ONLY_EXISTS;
1231 
1232 		/*
1233 		 * This is the point where we could check if another client
1234 		 * has another user or SO logged in.
1235 		 *
1236 		 * The spec says:
1237 		 * CKR_USER_TOO_MANY_TYPES: An attempt was made to have
1238 		 * more distinct users simultaneously logged into the token
1239 		 * than the token and/or library permits. For example, if
1240 		 * some application has an open SO session, and another
1241 		 * application attempts to log the normal user into a
1242 		 * session, the attempt may return this error. It is not
1243 		 * required to, however. Only if the simultaneous distinct
1244 		 * users cannot be supported does C_Login have to return
1245 		 * this value. Note that this error code generalizes to
1246 		 * true multi-user tokens.
1247 		 *
1248 		 * So it's permitted to have another user or SO logged in
1249 		 * from another client.
1250 		 */
1251 
1252 		rc = check_so_pin(session, pin, pin_size);
1253 		if (!rc)
1254 			session_login_so(session);
1255 
1256 		break;
1257 
1258 	case PKCS11_CKU_USER:
1259 		if (pkcs11_session_is_so(session))
1260 			return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
1261 
1262 		if (pkcs11_session_is_user(session))
1263 			return PKCS11_CKR_USER_ALREADY_LOGGED_IN;
1264 
1265 		/*
1266 		 * This is the point where we could check if another client
1267 		 * has another user or SO logged in.
1268 		 * See comment on CKR_USER_TOO_MANY_TYPES above.
1269 		 */
1270 
1271 		rc = check_user_pin(session, pin, pin_size);
1272 		if (!rc)
1273 			session_login_user(session);
1274 
1275 		break;
1276 
1277 	case PKCS11_CKU_CONTEXT_SPECIFIC:
1278 		return PKCS11_CKR_OPERATION_NOT_INITIALIZED;
1279 
1280 	default:
1281 		return PKCS11_CKR_USER_TYPE_INVALID;
1282 	}
1283 
1284 	if (!rc)
1285 		IMSG("PKCS11 session %"PRIu32": login", session->handle);
1286 
1287 	return rc;
1288 }
1289 
1290 uint32_t entry_ck_logout(struct pkcs11_client *client,
1291 			 uint32_t ptypes, TEE_Param *params)
1292 {
1293 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1294 						TEE_PARAM_TYPE_NONE,
1295 						TEE_PARAM_TYPE_NONE,
1296 						TEE_PARAM_TYPE_NONE);
1297 	struct pkcs11_session *session = NULL;
1298 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1299 	struct serialargs ctrlargs = { };
1300 	TEE_Param *ctrl = params;
1301 
1302 	if (!client || ptypes != exp_pt)
1303 		return PKCS11_CKR_ARGUMENTS_BAD;
1304 
1305 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1306 
1307 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1308 	if (rc)
1309 		return rc;
1310 
1311 	if (serialargs_remaining_bytes(&ctrlargs))
1312 		return PKCS11_CKR_ARGUMENTS_BAD;
1313 
1314 	if (pkcs11_session_is_public(session))
1315 		return PKCS11_CKR_USER_NOT_LOGGED_IN;
1316 
1317 	session_logout(session);
1318 
1319 	IMSG("PKCS11 session %"PRIu32": logout", session->handle);
1320 
1321 	return PKCS11_CKR_OK;
1322 }
1323