xref: /optee_os/ta/pkcs11/src/pkcs11_token.c (revision d628ebd9b0a9fd05355f934d89a28bc2154713df)
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 		.serial_number = PKCS11_TOKEN_SERIAL_NUMBER,
281 		.max_session_count = UINT32_MAX,
282 		.max_rw_session_count = UINT32_MAX,
283 		.max_pin_len = PKCS11_TOKEN_PIN_SIZE_MAX,
284 		.min_pin_len = PKCS11_TOKEN_PIN_SIZE_MIN,
285 		.total_public_memory = UINT32_MAX,
286 		.free_public_memory = UINT32_MAX,
287 		.total_private_memory = UINT32_MAX,
288 		.free_private_memory = UINT32_MAX,
289 		.hardware_version = PKCS11_TOKEN_HW_VERSION,
290 		.firmware_version = PKCS11_TOKEN_FW_VERSION,
291 	};
292 
293 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
294 		return PKCS11_CKR_ARGUMENTS_BAD;
295 
296 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
297 
298 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
299 	if (rv)
300 		return rv;
301 
302 	if (serialargs_remaining_bytes(&ctrlargs))
303 		return PKCS11_CKR_ARGUMENTS_BAD;
304 
305 	token = get_token(token_id);
306 	if (!token)
307 		return PKCS11_CKR_SLOT_ID_INVALID;
308 
309 	pad_str(info.manufacturer_id, sizeof(info.manufacturer_id));
310 	pad_str(info.model, sizeof(info.model));
311 	pad_str(info.serial_number, sizeof(info.serial_number));
312 
313 	TEE_MemMove(info.label, token->db_main->label, sizeof(info.label));
314 
315 	info.flags = token->db_main->flags;
316 	info.session_count = token->session_count;
317 	info.rw_session_count = token->rw_session_count;
318 
319 	TEE_MemMove(out->memref.buffer, &info, sizeof(info));
320 
321 	return PKCS11_CKR_OK;
322 }
323 
324 static void dmsg_print_supported_mechanism(unsigned int token_id __maybe_unused,
325 					   uint32_t *array __maybe_unused,
326 					   size_t count __maybe_unused)
327 {
328 	size_t __maybe_unused n = 0;
329 
330 	if (TRACE_LEVEL < TRACE_DEBUG)
331 		return;
332 
333 	for (n = 0; n < count; n++)
334 		DMSG("PKCS11 token %"PRIu32": mechanism 0x%04"PRIx32": %s",
335 		     token_id, array[n], id2str_mechanism(array[n]));
336 }
337 
338 uint32_t entry_ck_token_mecha_ids(uint32_t ptypes, TEE_Param *params)
339 {
340 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
341 						TEE_PARAM_TYPE_NONE,
342 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
343 						TEE_PARAM_TYPE_NONE);
344 	TEE_Param *ctrl = &params[0];
345 	TEE_Param *out = &params[2];
346 	uint32_t rv = 0;
347 	struct serialargs ctrlargs = { };
348 	uint32_t token_id = 0;
349 	struct ck_token __maybe_unused *token = NULL;
350 	size_t count = 0;
351 	uint32_t *array = NULL;
352 
353 	if (ptypes != exp_pt)
354 		return PKCS11_CKR_ARGUMENTS_BAD;
355 
356 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
357 
358 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
359 	if (rv)
360 		return rv;
361 
362 	if (serialargs_remaining_bytes(&ctrlargs))
363 		return PKCS11_CKR_ARGUMENTS_BAD;
364 
365 	token = get_token(token_id);
366 	if (!token)
367 		return PKCS11_CKR_SLOT_ID_INVALID;
368 
369 	count = out->memref.size / sizeof(*array);
370 	array = tee_malloc_mechanism_list(&count);
371 
372 	if (out->memref.size < count * sizeof(*array)) {
373 		assert(!array);
374 		out->memref.size = count * sizeof(*array);
375 		if (out->memref.buffer)
376 			return PKCS11_CKR_BUFFER_TOO_SMALL;
377 		else
378 			return PKCS11_CKR_OK;
379 	}
380 
381 	if (!array)
382 		return PKCS11_CKR_DEVICE_MEMORY;
383 
384 	dmsg_print_supported_mechanism(token_id, array, count);
385 
386 	out->memref.size = count * sizeof(*array);
387 	TEE_MemMove(out->memref.buffer, array, out->memref.size);
388 
389 	TEE_Free(array);
390 
391 	return rv;
392 }
393 
394 static void supported_mechanism_key_size(uint32_t proc_id,
395 					 uint32_t *max_key_size,
396 					 uint32_t *min_key_size)
397 {
398 	switch (proc_id) {
399 	/* Will be filled once TA supports mechanisms */
400 	default:
401 		*min_key_size = 0;
402 		*max_key_size = 0;
403 		break;
404 	}
405 }
406 
407 uint32_t entry_ck_token_mecha_info(uint32_t ptypes, TEE_Param *params)
408 {
409 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
410 						TEE_PARAM_TYPE_NONE,
411 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
412 						TEE_PARAM_TYPE_NONE);
413 	TEE_Param *ctrl = &params[0];
414 	TEE_Param *out = &params[2];
415 	uint32_t rv = 0;
416 	struct serialargs ctrlargs = { };
417 	uint32_t token_id = 0;
418 	uint32_t type = 0;
419 	struct ck_token *token = NULL;
420 	struct pkcs11_mechanism_info info = { };
421 
422 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
423 		return PKCS11_CKR_ARGUMENTS_BAD;
424 
425 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
426 
427 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
428 	if (rv)
429 		return rv;
430 
431 	rv = serialargs_get(&ctrlargs, &type, sizeof(uint32_t));
432 	if (rv)
433 		return rv;
434 
435 	if (serialargs_remaining_bytes(&ctrlargs))
436 		return PKCS11_CKR_ARGUMENTS_BAD;
437 
438 	token = get_token(token_id);
439 	if (!token)
440 		return PKCS11_CKR_SLOT_ID_INVALID;
441 
442 	if (!mechanism_is_valid(type))
443 		return PKCS11_CKR_MECHANISM_INVALID;
444 
445 	info.flags = mechanism_supported_flags(type);
446 
447 	supported_mechanism_key_size(type, &info.min_key_size,
448 				     &info.max_key_size);
449 
450 	TEE_MemMove(out->memref.buffer, &info, sizeof(info));
451 
452 	DMSG("PKCS11 token %"PRIu32": mechanism 0x%"PRIx32" info",
453 	     token_id, type);
454 
455 	return PKCS11_CKR_OK;
456 }
457 
458 /* Select the ReadOnly or ReadWrite state for session login state */
459 static void set_session_state(struct pkcs11_client *client,
460 			      struct pkcs11_session *session, bool readonly)
461 {
462 	struct pkcs11_session *sess = NULL;
463 	enum pkcs11_session_state state = PKCS11_CKS_RO_PUBLIC_SESSION;
464 
465 	/* Default to public session if no session already registered */
466 	if (readonly)
467 		state = PKCS11_CKS_RO_PUBLIC_SESSION;
468 	else
469 		state = PKCS11_CKS_RW_PUBLIC_SESSION;
470 
471 	/*
472 	 * No need to check all client sessions, the first found in
473 	 * target token gives client login configuration.
474 	 */
475 	TAILQ_FOREACH(sess, &client->session_list, link) {
476 		assert(sess != session);
477 
478 		if (sess->token == session->token) {
479 			switch (sess->state) {
480 			case PKCS11_CKS_RW_PUBLIC_SESSION:
481 			case PKCS11_CKS_RO_PUBLIC_SESSION:
482 				if (readonly)
483 					state = PKCS11_CKS_RO_PUBLIC_SESSION;
484 				else
485 					state = PKCS11_CKS_RW_PUBLIC_SESSION;
486 				break;
487 			case PKCS11_CKS_RO_USER_FUNCTIONS:
488 			case PKCS11_CKS_RW_USER_FUNCTIONS:
489 				if (readonly)
490 					state = PKCS11_CKS_RO_USER_FUNCTIONS;
491 				else
492 					state = PKCS11_CKS_RW_USER_FUNCTIONS;
493 				break;
494 			case PKCS11_CKS_RW_SO_FUNCTIONS:
495 				if (readonly)
496 					TEE_Panic(0);
497 				else
498 					state = PKCS11_CKS_RW_SO_FUNCTIONS;
499 				break;
500 			default:
501 				TEE_Panic(0);
502 			}
503 			break;
504 		}
505 	}
506 
507 	session->state = state;
508 }
509 
510 uint32_t entry_ck_open_session(struct pkcs11_client *client,
511 			       uint32_t ptypes, TEE_Param *params)
512 {
513 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
514 						TEE_PARAM_TYPE_NONE,
515 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
516 						TEE_PARAM_TYPE_NONE);
517 	TEE_Param *ctrl = &params[0];
518 	TEE_Param *out = &params[2];
519 	uint32_t rv = 0;
520 	struct serialargs ctrlargs = { };
521 	uint32_t token_id = 0;
522 	uint32_t flags = 0;
523 	struct ck_token *token = NULL;
524 	struct pkcs11_session *session = NULL;
525 	bool readonly = false;
526 
527 	if (!client || ptypes != exp_pt ||
528 	    out->memref.size != sizeof(session->handle))
529 		return PKCS11_CKR_ARGUMENTS_BAD;
530 
531 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
532 
533 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
534 	if (rv)
535 		return rv;
536 
537 	rv = serialargs_get(&ctrlargs, &flags, sizeof(flags));
538 	if (rv)
539 		return rv;
540 
541 	if (serialargs_remaining_bytes(&ctrlargs))
542 		return PKCS11_CKR_ARGUMENTS_BAD;
543 
544 	token = get_token(token_id);
545 	if (!token)
546 		return PKCS11_CKR_SLOT_ID_INVALID;
547 
548 	/* Sanitize session flags */
549 	if (!(flags & PKCS11_CKFSS_SERIAL_SESSION) ||
550 	    (flags & ~(PKCS11_CKFSS_RW_SESSION |
551 		       PKCS11_CKFSS_SERIAL_SESSION)))
552 		return PKCS11_CKR_ARGUMENTS_BAD;
553 
554 	readonly = !(flags & PKCS11_CKFSS_RW_SESSION);
555 
556 	if (!readonly && token->state == PKCS11_TOKEN_READ_ONLY)
557 		return PKCS11_CKR_TOKEN_WRITE_PROTECTED;
558 
559 	if (readonly) {
560 		/* Specifically reject read-only session under SO login */
561 		TAILQ_FOREACH(session, &client->session_list, link)
562 			if (pkcs11_session_is_so(session))
563 				return PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS;
564 	}
565 
566 	session = TEE_Malloc(sizeof(*session), TEE_MALLOC_FILL_ZERO);
567 	if (!session)
568 		return PKCS11_CKR_DEVICE_MEMORY;
569 
570 	session->handle = handle_get(&client->session_handle_db, session);
571 	if (!session->handle) {
572 		TEE_Free(session);
573 		return PKCS11_CKR_DEVICE_MEMORY;
574 	}
575 
576 	session->token = token;
577 	session->client = client;
578 
579 	set_session_state(client, session, readonly);
580 
581 	TAILQ_INSERT_HEAD(&client->session_list, session, link);
582 
583 	session->token->session_count++;
584 	if (!readonly)
585 		session->token->rw_session_count++;
586 
587 	TEE_MemMove(out->memref.buffer, &session->handle,
588 		    sizeof(session->handle));
589 
590 	DMSG("Open PKCS11 session %"PRIu32, session->handle);
591 
592 	return PKCS11_CKR_OK;
593 }
594 
595 static void close_ck_session(struct pkcs11_session *session)
596 {
597 	TAILQ_REMOVE(&session->client->session_list, session, link);
598 	handle_put(&session->client->session_handle_db, session->handle);
599 
600 	session->token->session_count--;
601 	if (pkcs11_session_is_read_write(session))
602 		session->token->rw_session_count--;
603 
604 	TEE_Free(session);
605 
606 	DMSG("Close PKCS11 session %"PRIu32, session->handle);
607 }
608 
609 uint32_t entry_ck_close_session(struct pkcs11_client *client,
610 				uint32_t ptypes, TEE_Param *params)
611 {
612 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
613 						TEE_PARAM_TYPE_NONE,
614 						TEE_PARAM_TYPE_NONE,
615 						TEE_PARAM_TYPE_NONE);
616 	TEE_Param *ctrl = &params[0];
617 	uint32_t rv = 0;
618 	struct serialargs ctrlargs = { };
619 	uint32_t session_handle = 0;
620 	struct pkcs11_session *session = NULL;
621 
622 	if (!client || ptypes != exp_pt)
623 		return PKCS11_CKR_ARGUMENTS_BAD;
624 
625 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
626 
627 	rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
628 	if (rv)
629 		return rv;
630 
631 	if (serialargs_remaining_bytes(&ctrlargs))
632 		return PKCS11_CKR_ARGUMENTS_BAD;
633 
634 	session = pkcs11_handle2session(session_handle, client);
635 	if (!session)
636 		return PKCS11_CKR_SESSION_HANDLE_INVALID;
637 
638 	close_ck_session(session);
639 
640 	return PKCS11_CKR_OK;
641 }
642 
643 uint32_t entry_ck_close_all_sessions(struct pkcs11_client *client,
644 				     uint32_t ptypes, TEE_Param *params)
645 {
646 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
647 						TEE_PARAM_TYPE_NONE,
648 						TEE_PARAM_TYPE_NONE,
649 						TEE_PARAM_TYPE_NONE);
650 	TEE_Param *ctrl = &params[0];
651 	uint32_t rv = 0;
652 	struct serialargs ctrlargs = { };
653 	uint32_t token_id = 0;
654 	struct ck_token *token = NULL;
655 	struct pkcs11_session *session = NULL;
656 	struct pkcs11_session *next = NULL;
657 
658 	if (!client || ptypes != exp_pt)
659 		return PKCS11_CKR_ARGUMENTS_BAD;
660 
661 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
662 
663 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
664 	if (rv)
665 		return rv;
666 
667 	if (serialargs_remaining_bytes(&ctrlargs))
668 		return PKCS11_CKR_ARGUMENTS_BAD;
669 
670 	token = get_token(token_id);
671 	if (!token)
672 		return PKCS11_CKR_SLOT_ID_INVALID;
673 
674 	DMSG("Close all sessions for PKCS11 token %"PRIu32, token_id);
675 
676 	TAILQ_FOREACH_SAFE(session, &client->session_list, link, next)
677 		if (session->token == token)
678 			close_ck_session(session);
679 
680 	return PKCS11_CKR_OK;
681 }
682 
683 uint32_t entry_ck_session_info(struct pkcs11_client *client,
684 			       uint32_t ptypes, TEE_Param *params)
685 {
686 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
687 						TEE_PARAM_TYPE_NONE,
688 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
689 						TEE_PARAM_TYPE_NONE);
690 	TEE_Param *ctrl = &params[0];
691 	TEE_Param *out = &params[2];
692 	uint32_t rv = 0;
693 	struct serialargs ctrlargs = { };
694 	uint32_t session_handle = 0;
695 	struct pkcs11_session *session = NULL;
696 	struct pkcs11_session_info info = {
697 		.flags = PKCS11_CKFSS_SERIAL_SESSION,
698 	};
699 
700 	if (!client || ptypes != exp_pt || out->memref.size != sizeof(info))
701 		return PKCS11_CKR_ARGUMENTS_BAD;
702 
703 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
704 
705 	rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
706 	if (rv)
707 		return rv;
708 
709 	if (serialargs_remaining_bytes(&ctrlargs))
710 		return PKCS11_CKR_ARGUMENTS_BAD;
711 
712 	session = pkcs11_handle2session(session_handle, client);
713 	if (!session)
714 		return PKCS11_CKR_SESSION_HANDLE_INVALID;
715 
716 	info.slot_id = get_token_id(session->token);
717 	info.state = session->state;
718 	if (pkcs11_session_is_read_write(session))
719 		info.flags |= PKCS11_CKFSS_RW_SESSION;
720 
721 	TEE_MemMove(out->memref.buffer, &info, sizeof(info));
722 
723 	DMSG("Get find on PKCS11 session %"PRIu32, session->handle);
724 
725 	return PKCS11_CKR_OK;
726 }
727 
728 uint32_t entry_ck_token_initialize(uint32_t ptypes, TEE_Param *params)
729 {
730 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
731 						TEE_PARAM_TYPE_NONE,
732 						TEE_PARAM_TYPE_NONE,
733 						TEE_PARAM_TYPE_NONE);
734 	char label[PKCS11_TOKEN_LABEL_SIZE] = { 0 };
735 	struct pkcs11_client *client = NULL;
736 	struct pkcs11_session *sess = NULL;
737 	enum pkcs11_rc rc = PKCS11_CKR_OK;
738 	struct serialargs ctrlargs = { };
739 	struct ck_token *token = NULL;
740 	TEE_Param *ctrl = params;
741 	uint32_t token_id = 0;
742 	uint32_t pin_size = 0;
743 	void *pin = NULL;
744 
745 	if (ptypes != exp_pt)
746 		return PKCS11_CKR_ARGUMENTS_BAD;
747 
748 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
749 
750 	rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
751 	if (rc)
752 		return rc;
753 
754 	rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
755 	if (rc)
756 		return rc;
757 
758 	rc = serialargs_get(&ctrlargs, &label, PKCS11_TOKEN_LABEL_SIZE);
759 	if (rc)
760 		return rc;
761 
762 	rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
763 	if (rc)
764 		return rc;
765 
766 	if (serialargs_remaining_bytes(&ctrlargs))
767 		return PKCS11_CKR_ARGUMENTS_BAD;
768 
769 	token = get_token(token_id);
770 	if (!token)
771 		return PKCS11_CKR_SLOT_ID_INVALID;
772 
773 	if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) {
774 		IMSG("Token %"PRIu32": SO PIN locked", token_id);
775 		return PKCS11_CKR_PIN_LOCKED;
776 	}
777 
778 	/* Check there's no open session on this token */
779 	TAILQ_FOREACH(client, &pkcs11_client_list, link)
780 		TAILQ_FOREACH(sess, &client->session_list, link)
781 			if (sess->token == token)
782 				return PKCS11_CKR_SESSION_EXISTS;
783 
784 	if (!token->db_main->so_pin_salt) {
785 		/*
786 		 * The spec doesn't permit returning
787 		 * PKCS11_CKR_PIN_LEN_RANGE for this function, take another
788 		 * error code.
789 		 */
790 		if (pin_size < PKCS11_TOKEN_PIN_SIZE_MIN ||
791 		    pin_size > PKCS11_TOKEN_PIN_SIZE_MAX)
792 			return PKCS11_CKR_ARGUMENTS_BAD;
793 
794 		rc = hash_pin(PKCS11_CKU_SO, pin, pin_size,
795 			      &token->db_main->so_pin_salt,
796 			      token->db_main->so_pin_hash);
797 		if (rc)
798 			return rc;
799 
800 		update_persistent_db(token);
801 
802 		goto inited;
803 	}
804 
805 	rc = verify_pin(PKCS11_CKU_SO, pin, pin_size,
806 			token->db_main->so_pin_salt,
807 			token->db_main->so_pin_hash);
808 	if (rc) {
809 		unsigned int pin_count = 0;
810 
811 		if (rc != PKCS11_CKR_PIN_INCORRECT)
812 			return rc;
813 
814 		token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW;
815 		token->db_main->so_pin_count++;
816 
817 		pin_count = token->db_main->so_pin_count;
818 		if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1)
819 			token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY;
820 		if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX)
821 			token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED;
822 
823 		update_persistent_db(token);
824 
825 		return PKCS11_CKR_PIN_INCORRECT;
826 	}
827 
828 	token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW |
829 				   PKCS11_CKFT_SO_PIN_FINAL_TRY);
830 	token->db_main->so_pin_count = 0;
831 
832 inited:
833 	TEE_MemMove(token->db_main->label, label, PKCS11_TOKEN_LABEL_SIZE);
834 	token->db_main->flags |= PKCS11_CKFT_TOKEN_INITIALIZED;
835 	/* Reset user PIN */
836 	token->db_main->user_pin_salt = 0;
837 	token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_INITIALIZED |
838 				   PKCS11_CKFT_USER_PIN_COUNT_LOW |
839 				   PKCS11_CKFT_USER_PIN_FINAL_TRY |
840 				   PKCS11_CKFT_USER_PIN_LOCKED |
841 				   PKCS11_CKFT_USER_PIN_TO_BE_CHANGED);
842 
843 	update_persistent_db(token);
844 
845 	IMSG("PKCS11 token %"PRIu32": initialized", token_id);
846 
847 	return PKCS11_CKR_OK;
848 }
849 
850 static enum pkcs11_rc set_pin(struct pkcs11_session *session,
851 			      uint8_t *new_pin, size_t new_pin_size,
852 			      enum pkcs11_user_type user_type)
853 {
854 	enum pkcs11_rc rc = PKCS11_CKR_OK;
855 	uint32_t flags_clear = 0;
856 	uint32_t flags_set = 0;
857 
858 	if (session->token->db_main->flags & PKCS11_CKFT_WRITE_PROTECTED)
859 		return PKCS11_CKR_TOKEN_WRITE_PROTECTED;
860 
861 	if (!pkcs11_session_is_read_write(session))
862 		return PKCS11_CKR_SESSION_READ_ONLY;
863 
864 	if (new_pin_size < PKCS11_TOKEN_PIN_SIZE_MIN ||
865 	    new_pin_size > PKCS11_TOKEN_PIN_SIZE_MAX)
866 		return PKCS11_CKR_PIN_LEN_RANGE;
867 
868 	switch (user_type) {
869 	case PKCS11_CKU_SO:
870 		rc = hash_pin(user_type, new_pin, new_pin_size,
871 			      &session->token->db_main->so_pin_salt,
872 			      session->token->db_main->so_pin_hash);
873 		if (rc)
874 			return rc;
875 		session->token->db_main->so_pin_count = 0;
876 		flags_clear = PKCS11_CKFT_SO_PIN_COUNT_LOW |
877 			      PKCS11_CKFT_SO_PIN_FINAL_TRY |
878 			      PKCS11_CKFT_SO_PIN_LOCKED |
879 			      PKCS11_CKFT_SO_PIN_TO_BE_CHANGED;
880 		break;
881 	case PKCS11_CKU_USER:
882 		rc = hash_pin(user_type, new_pin, new_pin_size,
883 			      &session->token->db_main->user_pin_salt,
884 			      session->token->db_main->user_pin_hash);
885 		if (rc)
886 			return rc;
887 		session->token->db_main->user_pin_count = 0;
888 		flags_clear = PKCS11_CKFT_USER_PIN_COUNT_LOW |
889 			      PKCS11_CKFT_USER_PIN_FINAL_TRY |
890 			      PKCS11_CKFT_USER_PIN_LOCKED |
891 			      PKCS11_CKFT_USER_PIN_TO_BE_CHANGED;
892 		flags_set = PKCS11_CKFT_USER_PIN_INITIALIZED;
893 		break;
894 	default:
895 		return PKCS11_CKR_FUNCTION_FAILED;
896 	}
897 
898 	session->token->db_main->flags &= ~flags_clear;
899 	session->token->db_main->flags |= flags_set;
900 
901 	update_persistent_db(session->token);
902 
903 	return PKCS11_CKR_OK;
904 }
905 
906 uint32_t entry_ck_init_pin(struct pkcs11_client *client,
907 			   uint32_t ptypes, TEE_Param *params)
908 {
909 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
910 						TEE_PARAM_TYPE_NONE,
911 						TEE_PARAM_TYPE_NONE,
912 						TEE_PARAM_TYPE_NONE);
913 	struct pkcs11_session *session = NULL;
914 	enum pkcs11_rc rc = PKCS11_CKR_OK;
915 	struct serialargs ctrlargs = { };
916 	uint32_t session_handle = 0;
917 	TEE_Param *ctrl = params;
918 	uint32_t pin_size = 0;
919 	void *pin = NULL;
920 
921 	if (!client || ptypes != exp_pt)
922 		return PKCS11_CKR_ARGUMENTS_BAD;
923 
924 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
925 
926 	rc = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
927 	if (rc)
928 		return rc;
929 
930 	rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
931 	if (rc)
932 		return rc;
933 
934 	rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
935 	if (rc)
936 		return rc;
937 
938 	if (serialargs_remaining_bytes(&ctrlargs))
939 		return PKCS11_CKR_ARGUMENTS_BAD;
940 
941 	session = pkcs11_handle2session(session_handle, client);
942 	if (!session)
943 		return PKCS11_CKR_SESSION_HANDLE_INVALID;
944 
945 	if (!pkcs11_session_is_so(session))
946 		return PKCS11_CKR_USER_NOT_LOGGED_IN;
947 
948 	assert(session->token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED);
949 
950 	IMSG("PKCS11 session %"PRIu32": init PIN", session_handle);
951 
952 	return set_pin(session, pin, pin_size, PKCS11_CKU_USER);
953 }
954 
955 static uint32_t check_so_pin(struct pkcs11_session *session,
956 			     uint8_t *pin, size_t pin_size)
957 {
958 	struct ck_token *token = session->token;
959 	enum pkcs11_rc rc = PKCS11_CKR_OK;
960 
961 	assert(token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED);
962 
963 	if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED)
964 		return PKCS11_CKR_PIN_LOCKED;
965 
966 	rc = verify_pin(PKCS11_CKU_SO, pin, pin_size,
967 			token->db_main->so_pin_salt,
968 			token->db_main->so_pin_hash);
969 	if (rc) {
970 		unsigned int pin_count = 0;
971 
972 		if (rc != PKCS11_CKR_PIN_INCORRECT)
973 			return rc;
974 
975 		token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW;
976 		token->db_main->so_pin_count++;
977 
978 		pin_count = token->db_main->so_pin_count;
979 		if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1)
980 			token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY;
981 		if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX)
982 			token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED;
983 
984 		update_persistent_db(token);
985 
986 		if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED)
987 			return PKCS11_CKR_PIN_LOCKED;
988 
989 		return PKCS11_CKR_PIN_INCORRECT;
990 	}
991 
992 	if (token->db_main->so_pin_count) {
993 		token->db_main->so_pin_count = 0;
994 
995 		update_persistent_db(token);
996 	}
997 
998 	if (token->db_main->flags & (PKCS11_CKFT_SO_PIN_COUNT_LOW |
999 				     PKCS11_CKFT_SO_PIN_FINAL_TRY)) {
1000 		token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW |
1001 					   PKCS11_CKFT_SO_PIN_FINAL_TRY);
1002 
1003 		update_persistent_db(token);
1004 	}
1005 
1006 	return PKCS11_CKR_OK;
1007 }
1008 
1009 static uint32_t check_user_pin(struct pkcs11_session *session,
1010 			       uint8_t *pin, size_t pin_size)
1011 {
1012 	struct ck_token *token = session->token;
1013 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1014 
1015 	if (!token->db_main->user_pin_salt)
1016 		return PKCS11_CKR_USER_PIN_NOT_INITIALIZED;
1017 
1018 	if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED)
1019 		return PKCS11_CKR_PIN_LOCKED;
1020 
1021 	rc = verify_pin(PKCS11_CKU_USER, pin, pin_size,
1022 			token->db_main->user_pin_salt,
1023 			token->db_main->user_pin_hash);
1024 	if (rc) {
1025 		unsigned int pin_count = 0;
1026 
1027 		if (rc != PKCS11_CKR_PIN_INCORRECT)
1028 			return rc;
1029 
1030 		token->db_main->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW;
1031 		token->db_main->user_pin_count++;
1032 
1033 		pin_count = token->db_main->user_pin_count;
1034 		if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1)
1035 			token->db_main->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY;
1036 		if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX)
1037 			token->db_main->flags |= PKCS11_CKFT_USER_PIN_LOCKED;
1038 
1039 		update_persistent_db(token);
1040 
1041 		if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED)
1042 			return PKCS11_CKR_PIN_LOCKED;
1043 
1044 		return PKCS11_CKR_PIN_INCORRECT;
1045 	}
1046 
1047 	if (token->db_main->user_pin_count) {
1048 		token->db_main->user_pin_count = 0;
1049 
1050 		update_persistent_db(token);
1051 	}
1052 
1053 	if (token->db_main->flags & (PKCS11_CKFT_USER_PIN_COUNT_LOW |
1054 				     PKCS11_CKFT_USER_PIN_FINAL_TRY)) {
1055 		token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_COUNT_LOW |
1056 					   PKCS11_CKFT_USER_PIN_FINAL_TRY);
1057 
1058 		update_persistent_db(token);
1059 	}
1060 
1061 	return PKCS11_CKR_OK;
1062 }
1063 
1064 uint32_t entry_ck_set_pin(struct pkcs11_client *client,
1065 			  uint32_t ptypes, TEE_Param *params)
1066 {
1067 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1068 						TEE_PARAM_TYPE_NONE,
1069 						TEE_PARAM_TYPE_NONE,
1070 						TEE_PARAM_TYPE_NONE);
1071 	struct pkcs11_session *session = NULL;
1072 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1073 	struct serialargs ctrlargs = { };
1074 	uint32_t session_handle = 0;
1075 	uint32_t old_pin_size = 0;
1076 	TEE_Param *ctrl = params;
1077 	uint32_t pin_size = 0;
1078 	void *old_pin = NULL;
1079 	void *pin = NULL;
1080 
1081 	if (!client || ptypes != exp_pt)
1082 		return PKCS11_CKR_ARGUMENTS_BAD;
1083 
1084 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1085 
1086 	rc = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
1087 	if (rc)
1088 		return rc;
1089 
1090 	rc = serialargs_get(&ctrlargs, &old_pin_size, sizeof(uint32_t));
1091 	if (rc)
1092 		return rc;
1093 
1094 	rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
1095 	if (rc)
1096 		return rc;
1097 
1098 	rc = serialargs_get_ptr(&ctrlargs, &old_pin, old_pin_size);
1099 	if (rc)
1100 		return rc;
1101 
1102 	rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
1103 	if (rc)
1104 		return rc;
1105 
1106 	if (serialargs_remaining_bytes(&ctrlargs))
1107 		return PKCS11_CKR_ARGUMENTS_BAD;
1108 
1109 	session = pkcs11_handle2session(session_handle, client);
1110 	if (!session)
1111 		return PKCS11_CKR_SESSION_HANDLE_INVALID;
1112 
1113 	if (!pkcs11_session_is_read_write(session))
1114 		return PKCS11_CKR_SESSION_READ_ONLY;
1115 
1116 	if (pkcs11_session_is_so(session)) {
1117 		if (!(session->token->db_main->flags &
1118 		      PKCS11_CKFT_TOKEN_INITIALIZED))
1119 			return PKCS11_CKR_GENERAL_ERROR;
1120 
1121 		rc = check_so_pin(session, old_pin, old_pin_size);
1122 		if (rc)
1123 			return rc;
1124 
1125 		IMSG("PKCS11 session %"PRIu32": set PIN", session_handle);
1126 
1127 		return set_pin(session, pin, pin_size, PKCS11_CKU_SO);
1128 	}
1129 
1130 	if (!(session->token->db_main->flags &
1131 	      PKCS11_CKFT_USER_PIN_INITIALIZED))
1132 		return PKCS11_CKR_GENERAL_ERROR;
1133 
1134 	rc = check_user_pin(session, old_pin, old_pin_size);
1135 	if (rc)
1136 		return rc;
1137 
1138 	IMSG("PKCS11 session %"PRIu32": set PIN", session_handle);
1139 
1140 	return set_pin(session, pin, pin_size, PKCS11_CKU_USER);
1141 }
1142 
1143 static void session_login_user(struct pkcs11_session *session)
1144 {
1145 	struct pkcs11_client *client = session->client;
1146 	struct pkcs11_session *sess = NULL;
1147 
1148 	TAILQ_FOREACH(sess, &client->session_list, link) {
1149 		if (sess->token != session->token)
1150 			continue;
1151 
1152 		if (pkcs11_session_is_read_write(sess))
1153 			sess->state = PKCS11_CKS_RW_USER_FUNCTIONS;
1154 		else
1155 			sess->state = PKCS11_CKS_RO_USER_FUNCTIONS;
1156 	}
1157 }
1158 
1159 static void session_login_so(struct pkcs11_session *session)
1160 {
1161 	struct pkcs11_client *client = session->client;
1162 	struct pkcs11_session *sess = NULL;
1163 
1164 	TAILQ_FOREACH(sess, &client->session_list, link) {
1165 		if (sess->token != session->token)
1166 			continue;
1167 
1168 		if (pkcs11_session_is_read_write(sess))
1169 			sess->state = PKCS11_CKS_RW_SO_FUNCTIONS;
1170 		else
1171 			TEE_Panic(0);
1172 	}
1173 }
1174 
1175 static void session_logout(struct pkcs11_session *session)
1176 {
1177 	struct pkcs11_client *client = session->client;
1178 	struct pkcs11_session *sess = NULL;
1179 
1180 	TAILQ_FOREACH(sess, &client->session_list, link) {
1181 		if (sess->token != session->token)
1182 			continue;
1183 
1184 		if (pkcs11_session_is_read_write(sess))
1185 			sess->state = PKCS11_CKS_RW_PUBLIC_SESSION;
1186 		else
1187 			sess->state = PKCS11_CKS_RO_PUBLIC_SESSION;
1188 	}
1189 }
1190 
1191 uint32_t entry_ck_login(struct pkcs11_client *client,
1192 			uint32_t ptypes, TEE_Param *params)
1193 {
1194 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1195 						TEE_PARAM_TYPE_NONE,
1196 						TEE_PARAM_TYPE_NONE,
1197 						TEE_PARAM_TYPE_NONE);
1198 	struct pkcs11_session *session = NULL;
1199 	struct pkcs11_session *sess = NULL;
1200 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1201 	struct serialargs ctrlargs = { };
1202 	uint32_t session_handle = 0;
1203 	TEE_Param *ctrl = params;
1204 	uint32_t user_type = 0;
1205 	uint32_t pin_size = 0;
1206 	void *pin = NULL;
1207 
1208 	if (!client || ptypes != exp_pt)
1209 		return PKCS11_CKR_ARGUMENTS_BAD;
1210 
1211 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1212 
1213 	rc = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
1214 	if (rc)
1215 		return rc;
1216 
1217 	rc = serialargs_get(&ctrlargs, &user_type, sizeof(uint32_t));
1218 	if (rc)
1219 		return rc;
1220 
1221 	rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
1222 	if (rc)
1223 		return rc;
1224 
1225 	rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
1226 	if (rc)
1227 		return rc;
1228 
1229 	if (serialargs_remaining_bytes(&ctrlargs))
1230 		return PKCS11_CKR_ARGUMENTS_BAD;
1231 
1232 	session = pkcs11_handle2session(session_handle, client);
1233 	if (!session)
1234 		return PKCS11_CKR_SESSION_HANDLE_INVALID;
1235 
1236 	switch (user_type) {
1237 	case PKCS11_CKU_SO:
1238 		if (pkcs11_session_is_so(session))
1239 			return PKCS11_CKR_USER_ALREADY_LOGGED_IN;
1240 
1241 		if (pkcs11_session_is_user(session))
1242 			return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
1243 
1244 		TAILQ_FOREACH(sess, &client->session_list, link)
1245 			if (sess->token == session->token &&
1246 			    !pkcs11_session_is_read_write(sess))
1247 				return PKCS11_CKR_SESSION_READ_ONLY_EXISTS;
1248 
1249 		/*
1250 		 * This is the point where we could check if another client
1251 		 * has another user or SO logged in.
1252 		 *
1253 		 * The spec says:
1254 		 * CKR_USER_TOO_MANY_TYPES: An attempt was made to have
1255 		 * more distinct users simultaneously logged into the token
1256 		 * than the token and/or library permits. For example, if
1257 		 * some application has an open SO session, and another
1258 		 * application attempts to log the normal user into a
1259 		 * session, the attempt may return this error. It is not
1260 		 * required to, however. Only if the simultaneous distinct
1261 		 * users cannot be supported does C_Login have to return
1262 		 * this value. Note that this error code generalizes to
1263 		 * true multi-user tokens.
1264 		 *
1265 		 * So it's permitted to have another user or SO logged in
1266 		 * from another client.
1267 		 */
1268 
1269 		rc = check_so_pin(session, pin, pin_size);
1270 		if (!rc)
1271 			session_login_so(session);
1272 
1273 		break;
1274 
1275 	case PKCS11_CKU_USER:
1276 		if (pkcs11_session_is_so(session))
1277 			return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
1278 
1279 		if (pkcs11_session_is_user(session))
1280 			return PKCS11_CKR_USER_ALREADY_LOGGED_IN;
1281 
1282 		/*
1283 		 * This is the point where we could check if another client
1284 		 * has another user or SO logged in.
1285 		 * See comment on CKR_USER_TOO_MANY_TYPES above.
1286 		 */
1287 
1288 		rc = check_user_pin(session, pin, pin_size);
1289 		if (!rc)
1290 			session_login_user(session);
1291 
1292 		break;
1293 
1294 	case PKCS11_CKU_CONTEXT_SPECIFIC:
1295 		return PKCS11_CKR_OPERATION_NOT_INITIALIZED;
1296 
1297 	default:
1298 		return PKCS11_CKR_USER_TYPE_INVALID;
1299 	}
1300 
1301 	if (!rc)
1302 		IMSG("PKCS11 session %"PRIu32": login", session_handle);
1303 
1304 	return rc;
1305 }
1306 
1307 uint32_t entry_ck_logout(struct pkcs11_client *client,
1308 			 uint32_t ptypes, TEE_Param *params)
1309 {
1310 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1311 						TEE_PARAM_TYPE_NONE,
1312 						TEE_PARAM_TYPE_NONE,
1313 						TEE_PARAM_TYPE_NONE);
1314 	struct pkcs11_session *session = NULL;
1315 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1316 	struct serialargs ctrlargs = { };
1317 	uint32_t session_handle = 0;
1318 	TEE_Param *ctrl = params;
1319 
1320 	if (!client || ptypes != exp_pt)
1321 		return PKCS11_CKR_ARGUMENTS_BAD;
1322 
1323 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1324 
1325 	rc = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
1326 	if (rc)
1327 		return rc;
1328 
1329 	if (serialargs_remaining_bytes(&ctrlargs))
1330 		return PKCS11_CKR_ARGUMENTS_BAD;
1331 
1332 	session = pkcs11_handle2session(session_handle, client);
1333 	if (!session)
1334 		return PKCS11_CKR_SESSION_HANDLE_INVALID;
1335 
1336 	if (pkcs11_session_is_public(session))
1337 		return PKCS11_CKR_USER_NOT_LOGGED_IN;
1338 
1339 	session_logout(session);
1340 
1341 	IMSG("PKCS11 session %"PRIu32": logout", session_handle);
1342 
1343 	return PKCS11_CKR_OK;
1344 }
1345