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