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