1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017-2020, Linaro Limited
4  */
5 
6 #include <ck_debug.h>
7 #include <pkcs11.h>
8 #include <pkcs11_ta.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "ck_helpers.h"
13 #include "invoke_ta.h"
14 #include "local_utils.h"
15 #include "pkcs11_token.h"
16 
17 #define PKCS11_LIB_MANUFACTURER		"Linaro"
18 #define PKCS11_LIB_DESCRIPTION		"OP-TEE PKCS11 Cryptoki library"
19 
20 /**
21  * Converts uint32_t value to CK_ULONG with unavailable information support
22  *
23  * On 64 bit systems uint32_t cannot handle CK_ULONG defined
24  * CK_UNAVAILABLE_INFORMATION. Check for this specific situation and return
25  * correct value.
26  *
27  * @ta_value: Value form PKCS#11 TA
28  * @return Valid CK_ULONG value
29  */
maybe_unavail(uint32_t ta_value)30 static CK_ULONG maybe_unavail(uint32_t ta_value)
31 {
32 	if (ta_value == PKCS11_CK_UNAVAILABLE_INFORMATION)
33 		return CK_UNAVAILABLE_INFORMATION;
34 	else
35 		return ta_value;
36 }
37 
38 /**
39  * ck_get_info - Get local information for C_GetInfo
40  */
ck_get_info(CK_INFO_PTR info)41 CK_RV ck_get_info(CK_INFO_PTR info)
42 {
43 	const CK_INFO lib_info = {
44 		.cryptokiVersion = {
45 			CK_PKCS11_VERSION_MAJOR,
46 			CK_PKCS11_VERSION_MINOR,
47 		},
48 		.manufacturerID = PKCS11_LIB_MANUFACTURER,
49 		.flags = 0,		/* must be zero per the PKCS#11 2.40 */
50 		.libraryDescription = PKCS11_LIB_DESCRIPTION,
51 		.libraryVersion = {
52 			PKCS11_TA_VERSION_MAJOR,
53 			PKCS11_TA_VERSION_MINOR
54 		},
55 	};
56 	int n = 0;
57 
58 	if (!info)
59 		return CKR_ARGUMENTS_BAD;
60 
61 	*info = lib_info;
62 
63 	/* Pad strings with blank characters */
64 	n = strnlen((char *)info->manufacturerID,
65 		    sizeof(info->manufacturerID));
66 	memset(&info->manufacturerID[n], ' ',
67 	       sizeof(info->manufacturerID) - n);
68 
69 	n = strnlen((char *)info->libraryDescription,
70 		    sizeof(info->libraryDescription));
71 	memset(&info->libraryDescription[n], ' ',
72 	       sizeof(info->libraryDescription) - n);
73 
74 	return CKR_OK;
75 }
76 
77 /**
78  * ck_slot_get_list - Wrap C_GetSlotList into PKCS11_CMD_SLOT_LIST
79  */
ck_slot_get_list(CK_BBOOL present,CK_SLOT_ID_PTR slots,CK_ULONG_PTR count)80 CK_RV ck_slot_get_list(CK_BBOOL present,
81 		       CK_SLOT_ID_PTR slots, CK_ULONG_PTR count)
82 {
83 	CK_RV rv = CKR_GENERAL_ERROR;
84 	TEEC_SharedMemory *shm = NULL;
85 	uint32_t *slot_ids = NULL;
86 	size_t client_count = 0;
87 	size_t size = 0;
88 	size_t n = 0;
89 
90 	/* Discard @present: all slots reported by TA are present */
91 	(void)present;
92 
93 	if (!count)
94 		return CKR_ARGUMENTS_BAD;
95 
96 	/*
97 	 * As per spec, if @slots is NULL, "The contents of *pulCount on
98 	 * entry to C_GetSlotList has no meaning in this case (...)"
99 	 */
100 	if (slots)
101 		client_count = *count;
102 
103 	size = client_count * sizeof(*slot_ids);
104 
105 	shm = ckteec_alloc_shm(size, CKTEEC_SHM_OUT);
106 	if (!shm)
107 		return CKR_HOST_MEMORY;
108 
109 	rv = ckteec_invoke_ta(PKCS11_CMD_SLOT_LIST, NULL,
110 			      NULL, shm, &size, NULL, NULL);
111 
112 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
113 		*count = size / sizeof(*slot_ids);
114 
115 	if (!slots && rv == CKR_BUFFER_TOO_SMALL)
116 		rv = CKR_OK;
117 	if (!slots || rv)
118 		goto out;
119 
120 	slot_ids = shm->buffer;
121 	for (n = 0; n < *count; n++)
122 		slots[n] = slot_ids[n];
123 
124 out:
125 	ckteec_free_shm(shm);
126 
127 	return rv;
128 }
129 
130 /**
131  * ck_slot_get_info - Wrap C_GetSlotInfo into PKCS11_CMD_SLOT_INFO
132  */
ck_slot_get_info(CK_SLOT_ID slot,CK_SLOT_INFO_PTR info)133 CK_RV ck_slot_get_info(CK_SLOT_ID slot, CK_SLOT_INFO_PTR info)
134 {
135 	CK_RV rv = CKR_GENERAL_ERROR;
136 	TEEC_SharedMemory *ctrl = NULL;
137 	TEEC_SharedMemory *out = NULL;
138 	uint32_t slot_id = slot;
139 	struct pkcs11_slot_info *ta_info = NULL;
140 	size_t out_size = 0;
141 
142 	if (!info)
143 		return CKR_ARGUMENTS_BAD;
144 
145 	ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT);
146 	if (!ctrl) {
147 		rv = CKR_HOST_MEMORY;
148 		goto out;
149 	}
150 	memcpy(ctrl->buffer, &slot_id, sizeof(slot_id));
151 
152 	out = ckteec_alloc_shm(sizeof(*ta_info), CKTEEC_SHM_OUT);
153 	if (!out) {
154 		rv = CKR_HOST_MEMORY;
155 		goto out;
156 	}
157 
158 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_SLOT_INFO, ctrl, out, &out_size);
159 	if (rv != CKR_OK || out_size != out->size) {
160 		if (rv == CKR_OK)
161 			rv = CKR_DEVICE_ERROR;
162 		goto out;
163 	}
164 
165 	ta_info = out->buffer;
166 
167 	COMPILE_TIME_ASSERT(sizeof(info->slotDescription) ==
168 			    sizeof(ta_info->slot_description));
169 	memcpy(info->slotDescription, ta_info->slot_description,
170 	       sizeof(info->slotDescription));
171 
172 	COMPILE_TIME_ASSERT(sizeof(info->manufacturerID) ==
173 			    sizeof(ta_info->manufacturer_id));
174 	memcpy(info->manufacturerID, ta_info->manufacturer_id,
175 	       sizeof(info->manufacturerID));
176 
177 	info->flags = ta_info->flags;
178 
179 	COMPILE_TIME_ASSERT(sizeof(info->hardwareVersion) ==
180 			    sizeof(ta_info->hardware_version));
181 	memcpy(&info->hardwareVersion, ta_info->hardware_version,
182 	       sizeof(info->hardwareVersion));
183 
184 	COMPILE_TIME_ASSERT(sizeof(info->firmwareVersion) ==
185 			    sizeof(ta_info->firmware_version));
186 	memcpy(&info->firmwareVersion, ta_info->firmware_version,
187 	       sizeof(info->firmwareVersion));
188 
189 out:
190 	ckteec_free_shm(ctrl);
191 	ckteec_free_shm(out);
192 
193 	return rv;
194 }
195 
196 /**
197  * ck_token_get_info - Wrap C_GetTokenInfo into PKCS11_CMD_TOKEN_INFO
198  */
ck_token_get_info(CK_SLOT_ID slot,CK_TOKEN_INFO_PTR info)199 CK_RV ck_token_get_info(CK_SLOT_ID slot, CK_TOKEN_INFO_PTR info)
200 {
201 	CK_RV rv = CKR_GENERAL_ERROR;
202 	TEEC_SharedMemory *ctrl = NULL;
203 	TEEC_SharedMemory *out_shm = NULL;
204 	uint32_t slot_id = slot;
205 	struct pkcs11_token_info *ta_info = NULL;
206 	size_t out_size = 0;
207 
208 	if (!info)
209 		return CKR_ARGUMENTS_BAD;
210 
211 	ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT);
212 	if (!ctrl) {
213 		rv = CKR_HOST_MEMORY;
214 		goto out;
215 	}
216 	memcpy(ctrl->buffer, &slot_id, sizeof(slot_id));
217 
218 	out_shm = ckteec_alloc_shm(sizeof(*ta_info), CKTEEC_SHM_OUT);
219 	if (!out_shm) {
220 		rv = CKR_HOST_MEMORY;
221 		goto out;
222 	}
223 
224 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_TOKEN_INFO, ctrl,
225 				    out_shm, &out_size);
226 	if (rv)
227 		goto out;
228 
229 	if (out_size != out_shm->size) {
230 		rv = CKR_DEVICE_ERROR;
231 		goto out;
232 	}
233 
234 	ta_info = out_shm->buffer;
235 
236 	COMPILE_TIME_ASSERT(sizeof(info->label) == sizeof(ta_info->label));
237 	memcpy(info->label, ta_info->label, sizeof(info->label));
238 
239 	COMPILE_TIME_ASSERT(sizeof(info->manufacturerID) ==
240 			    sizeof(ta_info->manufacturer_id));
241 	memcpy(info->manufacturerID, ta_info->manufacturer_id,
242 	       sizeof(info->manufacturerID));
243 
244 	COMPILE_TIME_ASSERT(sizeof(info->model) == sizeof(ta_info->model));
245 	memcpy(info->model, ta_info->model, sizeof(info->model));
246 
247 	COMPILE_TIME_ASSERT(sizeof(info->serialNumber) ==
248 			    sizeof(ta_info->serial_number));
249 	memcpy(info->serialNumber, ta_info->serial_number,
250 	       sizeof(info->serialNumber));
251 
252 	info->flags = ta_info->flags;
253 	info->ulMaxSessionCount = maybe_unavail(ta_info->max_session_count);
254 	info->ulSessionCount = maybe_unavail(ta_info->session_count);
255 	info->ulMaxRwSessionCount =
256 		maybe_unavail(ta_info->max_rw_session_count);
257 	info->ulRwSessionCount = maybe_unavail(ta_info->rw_session_count);
258 	info->ulMaxPinLen = ta_info->max_pin_len;
259 	info->ulMinPinLen = ta_info->min_pin_len;
260 	info->ulTotalPublicMemory =
261 		maybe_unavail(ta_info->total_public_memory);
262 	info->ulFreePublicMemory = maybe_unavail(ta_info->free_public_memory);
263 	info->ulTotalPrivateMemory =
264 		maybe_unavail(ta_info->total_private_memory);
265 	info->ulFreePrivateMemory =
266 		maybe_unavail(ta_info->free_private_memory);
267 
268 	COMPILE_TIME_ASSERT(sizeof(info->hardwareVersion) ==
269 			    sizeof(ta_info->hardware_version));
270 	memcpy(&info->hardwareVersion, ta_info->hardware_version,
271 	       sizeof(info->hardwareVersion));
272 
273 	COMPILE_TIME_ASSERT(sizeof(info->firmwareVersion) ==
274 			    sizeof(ta_info->firmware_version));
275 	memcpy(&info->firmwareVersion, ta_info->firmware_version,
276 	       sizeof(info->firmwareVersion));
277 
278 	COMPILE_TIME_ASSERT(sizeof(info->utcTime) == sizeof(ta_info->utc_time));
279 	memcpy(&info->utcTime, ta_info->utc_time, sizeof(info->utcTime));
280 
281 out:
282 	ckteec_free_shm(ctrl);
283 	ckteec_free_shm(out_shm);
284 
285 	return rv;
286 }
287 
288 /**
289  * ck_token_mechanism_ids - Wrap C_GetMechanismList
290  */
ck_token_mechanism_ids(CK_SLOT_ID slot,CK_MECHANISM_TYPE_PTR mechanisms,CK_ULONG_PTR count)291 CK_RV ck_token_mechanism_ids(CK_SLOT_ID slot,
292 			     CK_MECHANISM_TYPE_PTR mechanisms,
293 			     CK_ULONG_PTR count)
294 {
295 	CK_RV rv = CKR_GENERAL_ERROR;
296 	TEEC_SharedMemory *ctrl = NULL;
297 	TEEC_SharedMemory *out = NULL;
298 	uint32_t slot_id = slot;
299 	uint32_t *mecha_ids = NULL;
300 	size_t out_size = 0;
301 	size_t n = 0;
302 
303 	if (!count)
304 		return CKR_ARGUMENTS_BAD;
305 
306 	/*
307 	 * As per spec, if @mechanism is NULL, "The contents of *pulCount on
308 	 * entry to C_GetMechanismList has no meaning in this case (...)"
309 	 */
310 	if (mechanisms)
311 		out_size = *count * sizeof(*mecha_ids);
312 
313 	ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT);
314 	if (!ctrl) {
315 		rv = CKR_HOST_MEMORY;
316 		goto out;
317 	}
318 	memcpy(ctrl->buffer, &slot_id, sizeof(slot_id));
319 
320 	out = ckteec_alloc_shm(out_size, CKTEEC_SHM_OUT);
321 	if (!out) {
322 		rv = CKR_HOST_MEMORY;
323 		goto out;
324 	}
325 
326 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_MECHANISM_IDS,
327 				    ctrl, out, &out_size);
328 
329 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
330 		*count = out_size / sizeof(*mecha_ids);
331 
332 	if (!mechanisms && rv == CKR_BUFFER_TOO_SMALL)
333 		rv = CKR_OK;
334 	if (!mechanisms || rv)
335 		goto out;
336 
337 	mecha_ids = out->buffer;
338 	for (n = 0; n < *count; n++)
339 		mechanisms[n] = mecha_ids[n];
340 
341 out:
342 	ckteec_free_shm(ctrl);
343 	ckteec_free_shm(out);
344 
345 	return rv;
346 }
347 
348 /**
349  * ck_token_mechanism_info - Wrap C_GetMechanismInfo into command MECHANISM_INFO
350  */
ck_token_mechanism_info(CK_SLOT_ID slot,CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR info)351 CK_RV ck_token_mechanism_info(CK_SLOT_ID slot, CK_MECHANISM_TYPE type,
352 			      CK_MECHANISM_INFO_PTR info)
353 {
354 	CK_RV rv = CKR_GENERAL_ERROR;
355 	TEEC_SharedMemory *ctrl = NULL;
356 	TEEC_SharedMemory *out = NULL;
357 	uint32_t slot_id = slot;
358 	uint32_t mecha_type = type;
359 	struct pkcs11_mechanism_info *ta_info = NULL;
360 	char *buf = NULL;
361 	size_t out_size = 0;
362 
363 	if (!info)
364 		return CKR_ARGUMENTS_BAD;
365 
366 	ctrl = ckteec_alloc_shm(sizeof(slot_id) + sizeof(mecha_type),
367 				CKTEEC_SHM_INOUT);
368 	if (!ctrl) {
369 		rv = CKR_HOST_MEMORY;
370 		goto out;
371 	}
372 
373 	buf = ctrl->buffer;
374 
375 	memcpy(buf, &slot_id, sizeof(slot_id));
376 	buf += sizeof(slot_id);
377 
378 	memcpy(buf, &mecha_type, sizeof(mecha_type));
379 
380 	out = ckteec_alloc_shm(sizeof(*ta_info), CKTEEC_SHM_OUT);
381 	if (!out) {
382 		rv = CKR_HOST_MEMORY;
383 		goto out;
384 	}
385 
386 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_MECHANISM_INFO,
387 				    ctrl, out, &out_size);
388 
389 	if (rv != CKR_OK || out_size != out->size) {
390 		if (rv == CKR_OK)
391 			rv = CKR_DEVICE_ERROR;
392 		goto out;
393 	}
394 
395 	ta_info = out->buffer;
396 
397 	info->ulMinKeySize = ta_info->min_key_size;
398 	info->ulMaxKeySize = ta_info->max_key_size;
399 	info->flags = ta_info->flags;
400 
401 out:
402 	ckteec_free_shm(ctrl);
403 	ckteec_free_shm(out);
404 
405 	return rv;
406 }
407 
408 /**
409  * ck_open_session - Wrap C_OpenSession into PKCS11_CMD_OPEN_{RW|RO}_SESSION
410  *
411  * Note: cookie and callback are not utilized by libckteec and are silently
412  * sinked in to have better out-of-box compatibility with 3rd party libraries
413  * and applications which provides the callback.
414  */
ck_open_session(CK_SLOT_ID slot,CK_FLAGS flags,CK_VOID_PTR cookie,CK_NOTIFY callback,CK_SESSION_HANDLE_PTR session)415 CK_RV ck_open_session(CK_SLOT_ID slot, CK_FLAGS flags, CK_VOID_PTR cookie,
416 		      CK_NOTIFY callback, CK_SESSION_HANDLE_PTR session)
417 {
418 	CK_RV rv = CKR_GENERAL_ERROR;
419 	TEEC_SharedMemory *ctrl = NULL;
420 	TEEC_SharedMemory *out = NULL;
421 	uint32_t slot_id = slot;
422 	uint32_t u32_flags = flags;
423 	uint32_t handle = 0;
424 	size_t out_size = 0;
425 	uint8_t *buf;
426 
427 	/* Ignore notify callback */
428 	(void)cookie;
429 	(void)callback;
430 
431 	if ((flags & ~(CKF_RW_SESSION | CKF_SERIAL_SESSION)) || !session)
432 		return CKR_ARGUMENTS_BAD;
433 
434 	/* Shm io0: (in/out) ctrl = [slot-id][flags] / [status] */
435 	ctrl = ckteec_alloc_shm(sizeof(slot_id) + sizeof(u32_flags),
436 				CKTEEC_SHM_INOUT);
437 	if (!ctrl) {
438 		rv = CKR_HOST_MEMORY;
439 		goto out;
440 	}
441 	buf = (uint8_t *)ctrl->buffer;
442 	memcpy(buf, &slot_id, sizeof(slot_id));
443 	buf += sizeof(slot_id);
444 	memcpy(buf, &u32_flags, sizeof(u32_flags));
445 
446 	/* Shm io2: (out) [session handle] */
447 	out = ckteec_alloc_shm(sizeof(handle), CKTEEC_SHM_OUT);
448 	if (!out) {
449 		rv = CKR_HOST_MEMORY;
450 		goto out;
451 	}
452 
453 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_OPEN_SESSION,
454 				    ctrl, out, &out_size);
455 	if (rv != CKR_OK || out_size != out->size) {
456 		if (rv == CKR_OK)
457 			rv = CKR_DEVICE_ERROR;
458 		goto out;
459 	}
460 
461 	memcpy(&handle, out->buffer, sizeof(handle));
462 	*session = handle;
463 
464 out:
465 	ckteec_free_shm(ctrl);
466 	ckteec_free_shm(out);
467 
468 	return rv;
469 }
470 
471 /**
472  * ck_open_session - Wrap C_OpenSession into PKCS11_CMD_CLOSE_SESSION
473  */
ck_close_session(CK_SESSION_HANDLE session)474 CK_RV ck_close_session(CK_SESSION_HANDLE session)
475 {
476 	CK_RV rv = CKR_GENERAL_ERROR;
477 	TEEC_SharedMemory *ctrl = NULL;
478 	uint32_t session_handle = session;
479 
480 	/* Shm io0: (in/out) ctrl = [session-handle] / [status] */
481 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
482 	if (!ctrl) {
483 		rv = CKR_HOST_MEMORY;
484 		goto out;
485 	}
486 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
487 
488 	rv = ckteec_invoke_ctrl(PKCS11_CMD_CLOSE_SESSION, ctrl);
489 
490 out:
491 	ckteec_free_shm(ctrl);
492 
493 	return rv;
494 }
495 
496 /**
497  * ck_close_all_sessions - Wrap C_CloseAllSessions into TA command
498  */
ck_close_all_sessions(CK_SLOT_ID slot)499 CK_RV ck_close_all_sessions(CK_SLOT_ID slot)
500 {
501 	CK_RV rv = CKR_GENERAL_ERROR;
502 	TEEC_SharedMemory *ctrl = NULL;
503 	uint32_t slot_id = slot;
504 
505 	/* Shm io0: (in/out) ctrl = [slot-id] / [status] */
506 	ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT);
507 	if (!ctrl) {
508 		rv = CKR_HOST_MEMORY;
509 		goto out;
510 	}
511 	memcpy(ctrl->buffer, &slot_id, sizeof(slot_id));
512 
513 	rv = ckteec_invoke_ctrl(PKCS11_CMD_CLOSE_ALL_SESSIONS, ctrl);
514 
515 out:
516 	ckteec_free_shm(ctrl);
517 
518 	return rv;
519 }
520 
521 /**
522  * ck_get_session_info - Wrap C_GetSessionInfo into PKCS11_CMD_SESSION_INFO
523  */
ck_get_session_info(CK_SESSION_HANDLE session,CK_SESSION_INFO_PTR info)524 CK_RV ck_get_session_info(CK_SESSION_HANDLE session,
525 			  CK_SESSION_INFO_PTR info)
526 {
527 	CK_RV rv = CKR_GENERAL_ERROR;
528 	TEEC_SharedMemory *ctrl = NULL;
529 	TEEC_SharedMemory *out = NULL;
530 	uint32_t session_handle = session;
531 	struct pkcs11_session_info *ta_info = NULL;
532 	size_t out_size = 0;
533 
534 	if (!info)
535 		return CKR_ARGUMENTS_BAD;
536 
537 	/* Shm io0: (in/out) ctrl = [session-handle] / [status] */
538 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
539 	if (!ctrl) {
540 		rv = CKR_HOST_MEMORY;
541 		goto out;
542 	}
543 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
544 
545 	/* Shm io2: (out) [session info] */
546 	out = ckteec_alloc_shm(sizeof(struct pkcs11_session_info),
547 			       CKTEEC_SHM_OUT);
548 	if (!out) {
549 		rv = CKR_HOST_MEMORY;
550 		goto out;
551 	}
552 
553 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_SESSION_INFO,
554 				    ctrl, out, &out_size);
555 
556 	if (rv != CKR_OK || out_size != out->size) {
557 		if (rv == CKR_OK)
558 			rv = CKR_DEVICE_ERROR;
559 		goto out;
560 	}
561 
562 	ta_info = (struct pkcs11_session_info *)out->buffer;
563 	info->slotID = ta_info->slot_id;
564 	info->state = ta_info->state;
565 	info->flags = ta_info->flags;
566 	info->ulDeviceError = ta_info->device_error;
567 
568 out:
569 	ckteec_free_shm(ctrl);
570 	ckteec_free_shm(out);
571 
572 	return rv;
573 }
574 
575 /**
576  * ck_init_token - Wrap C_InitToken into PKCS11_CMD_INIT_TOKEN
577  */
ck_init_token(CK_SLOT_ID slot,CK_UTF8CHAR_PTR pin,CK_ULONG pin_len,CK_UTF8CHAR_PTR label)578 CK_RV ck_init_token(CK_SLOT_ID slot, CK_UTF8CHAR_PTR pin,
579 		    CK_ULONG pin_len, CK_UTF8CHAR_PTR label)
580 {
581 	CK_RV rv = CKR_GENERAL_ERROR;
582 	TEEC_SharedMemory *ctrl = NULL;
583 	uint32_t slot_id = slot;
584 	uint32_t pkcs11_pin_len = pin_len;
585 	size_t ctrl_size = 0;
586 	char *buf = NULL;
587 
588 	if (!pin && pin_len)
589 		return CKR_ARGUMENTS_BAD;
590 
591 	if (!label)
592 		return CKR_ARGUMENTS_BAD;
593 
594 	/* Shm io0: (in/out) ctrl = [slot-id][pin_len][label][pin] / [status] */
595 	ctrl_size = sizeof(slot_id) + sizeof(pkcs11_pin_len) +
596 		    32 * sizeof(uint8_t) + pkcs11_pin_len;
597 
598 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
599 	if (!ctrl)
600 		return CKR_HOST_MEMORY;
601 
602 	buf = ctrl->buffer;
603 
604 	memcpy(buf, &slot_id, sizeof(slot_id));
605 	buf += sizeof(slot_id);
606 
607 	memcpy(buf, &pkcs11_pin_len, sizeof(pkcs11_pin_len));
608 	buf += sizeof(pkcs11_pin_len);
609 
610 	memcpy(buf, label, 32 * sizeof(uint8_t));
611 	buf += 32 * sizeof(uint8_t);
612 
613 	memcpy(buf, pin, pkcs11_pin_len);
614 
615 	rv = ckteec_invoke_ctrl(PKCS11_CMD_INIT_TOKEN, ctrl);
616 
617 	ckteec_free_shm(ctrl);
618 
619 	return rv;
620 }
621 
622 /**
623  * ck_init_pin - Wrap C_InitPIN into PKCS11_CMD_INIT_PIN
624  */
ck_init_pin(CK_SESSION_HANDLE session,CK_UTF8CHAR_PTR pin,CK_ULONG pin_len)625 CK_RV ck_init_pin(CK_SESSION_HANDLE session,
626 		  CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
627 {
628 	CK_RV rv = CKR_GENERAL_ERROR;
629 	TEEC_SharedMemory *ctrl = NULL;
630 	uint32_t pkcs11_session = session;
631 	uint32_t pkcs11_pin_len = pin_len;
632 	size_t ctrl_size = 0;
633 	char *buf = NULL;
634 
635 	if (!pin && pin_len)
636 		return CKR_ARGUMENTS_BAD;
637 
638 	/* Shm io0: (in/out) ctrl = [session][pin_len][pin] / [status] */
639 	ctrl_size = sizeof(pkcs11_session) + sizeof(pkcs11_pin_len) +
640 		    pkcs11_pin_len;
641 
642 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
643 	if (!ctrl)
644 		return CKR_HOST_MEMORY;
645 
646 	buf = ctrl->buffer;
647 
648 	memcpy(buf, &pkcs11_session, sizeof(pkcs11_session));
649 	buf += sizeof(pkcs11_session);
650 
651 	memcpy(buf, &pkcs11_pin_len, sizeof(pkcs11_pin_len));
652 	buf += sizeof(pkcs11_pin_len);
653 
654 	memcpy(buf, pin, pkcs11_pin_len);
655 
656 	rv = ckteec_invoke_ctrl(PKCS11_CMD_INIT_PIN, ctrl);
657 
658 	ckteec_free_shm(ctrl);
659 
660 	return rv;
661 }
662 
663 /**
664  * ck_set_pin - Wrap C_SetPIN into PKCS11_CMD_SET_PIN
665  */
ck_set_pin(CK_SESSION_HANDLE session,CK_UTF8CHAR_PTR old,CK_ULONG old_len,CK_UTF8CHAR_PTR new,CK_ULONG new_len)666 CK_RV ck_set_pin(CK_SESSION_HANDLE session,
667 		 CK_UTF8CHAR_PTR old, CK_ULONG old_len,
668 		 CK_UTF8CHAR_PTR new, CK_ULONG new_len)
669 {
670 	CK_RV rv = CKR_GENERAL_ERROR;
671 	TEEC_SharedMemory *ctrl = NULL;
672 	uint32_t pkcs11_session = session;
673 	uint32_t pkcs11_old_len = old_len;
674 	uint32_t pkcs11_new_len = new_len;
675 	size_t ctrl_size = 0;
676 	char *buf;
677 
678 	if ((!old && old_len) || (!new && new_len))
679 		return CKR_ARGUMENTS_BAD;
680 
681 	/*
682 	 * Shm io0: (in/out) ctrl
683 	 * (in) [session][old_pin_len][new_pin_len][old pin][new pin]
684 	 * (out) [status]
685 	 */
686 	ctrl_size = sizeof(pkcs11_session) + sizeof(pkcs11_old_len) +
687 		    sizeof(pkcs11_new_len) + pkcs11_old_len + pkcs11_new_len;
688 
689 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
690 	if (!ctrl)
691 		return CKR_HOST_MEMORY;
692 
693 	buf = ctrl->buffer;
694 
695 	memcpy(buf, &pkcs11_session, sizeof(pkcs11_session));
696 	buf += sizeof(pkcs11_session);
697 
698 	memcpy(buf, &pkcs11_old_len, sizeof(pkcs11_old_len));
699 	buf += sizeof(pkcs11_old_len);
700 
701 	memcpy(buf, &pkcs11_new_len, sizeof(pkcs11_new_len));
702 	buf += sizeof(pkcs11_new_len);
703 
704 	memcpy(buf, old, pkcs11_old_len);
705 	buf += pkcs11_old_len;
706 
707 	memcpy(buf, new, pkcs11_new_len);
708 
709 	rv = ckteec_invoke_ctrl(PKCS11_CMD_SET_PIN, ctrl);
710 
711 	ckteec_free_shm(ctrl);
712 
713 	return rv;
714 }
715 
716 /**
717  * ck_login - Wrap C_Login into PKCS11_CMD_LOGIN
718  */
ck_login(CK_SESSION_HANDLE session,CK_USER_TYPE user_type,CK_UTF8CHAR_PTR pin,CK_ULONG pin_len)719 CK_RV ck_login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type,
720 	       CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
721 
722 {
723 	CK_RV rv = CKR_GENERAL_ERROR;
724 	TEEC_SharedMemory *ctrl = NULL;
725 	uint32_t pkcs11_session = session;
726 	uint32_t pkcs11_user = user_type;
727 	uint32_t pkcs11_pin_len = pin_len;
728 	size_t ctrl_size = 0;
729 	char *buf = NULL;
730 
731 	if (!pin && pin_len)
732 		return CKR_ARGUMENTS_BAD;
733 
734 	/* Shm io0: (i/o) ctrl = [session][user][pin length][pin] / [status] */
735 	ctrl_size = sizeof(pkcs11_session) + sizeof(pkcs11_user) +
736 		    sizeof(pkcs11_pin_len) + pkcs11_pin_len;
737 
738 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
739 	if (!ctrl)
740 		return CKR_HOST_MEMORY;
741 
742 	buf = ctrl->buffer;
743 
744 	memcpy(buf, &pkcs11_session, sizeof(pkcs11_session));
745 	buf += sizeof(pkcs11_session);
746 
747 	memcpy(buf, &pkcs11_user, sizeof(pkcs11_user));
748 	buf += sizeof(pkcs11_user);
749 
750 	memcpy(buf, &pkcs11_pin_len, sizeof(pkcs11_pin_len));
751 	buf += sizeof(pkcs11_pin_len);
752 
753 	memcpy(buf, pin, pkcs11_pin_len);
754 
755 	rv = ckteec_invoke_ctrl(PKCS11_CMD_LOGIN, ctrl);
756 
757 	ckteec_free_shm(ctrl);
758 
759 	return rv;
760 }
761 
762 /**
763  * ck_logout - Wrap C_Logout into PKCS11_CMD_LOGOUT
764  */
ck_logout(CK_SESSION_HANDLE session)765 CK_RV ck_logout(CK_SESSION_HANDLE session)
766 {
767 	CK_RV rv = CKR_GENERAL_ERROR;
768 	TEEC_SharedMemory *ctrl = NULL;
769 	uint32_t session_handle = session;
770 
771 	/* io0 = [session-handle] */
772 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
773 	if (!ctrl)
774 		return CKR_HOST_MEMORY;
775 
776 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
777 
778 	rv = ckteec_invoke_ctrl(PKCS11_CMD_LOGOUT, ctrl);
779 
780 	ckteec_free_shm(ctrl);
781 
782 	return rv;
783 }
784 
ck_seed_random(CK_SESSION_HANDLE session,CK_BYTE_PTR seed,CK_ULONG length)785 CK_RV ck_seed_random(CK_SESSION_HANDLE session, CK_BYTE_PTR seed,
786 		     CK_ULONG length)
787 {
788 	CK_RV rv = CKR_GENERAL_ERROR;
789 	size_t ctrl_size = 0;
790 	TEEC_SharedMemory *ctrl = NULL;
791 	TEEC_SharedMemory *in_shm = NULL;
792 	uint32_t session_handle = session;
793 
794 	if (!seed && length)
795 		return CKR_ARGUMENTS_BAD;
796 
797 	if (!seed)
798 		return CKR_OK;
799 
800 	/* Shm io0: (i/o) [session-handle] / [status] */
801 	ctrl_size = sizeof(session_handle);
802 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
803 	if (!ctrl)
804 		return CKR_HOST_MEMORY;
805 
806 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
807 
808 	/* Shm io1: (in) [seed data] */
809 	in_shm = ckteec_register_shm(seed, length, CKTEEC_SHM_IN);
810 	if (!in_shm) {
811 		rv = CKR_HOST_MEMORY;
812 		goto out;
813 	}
814 
815 	rv = ckteec_invoke_ctrl_in(PKCS11_CMD_SEED_RANDOM, ctrl, in_shm);
816 
817 out:
818 	ckteec_free_shm(in_shm);
819 	ckteec_free_shm(ctrl);
820 
821 	return rv;
822 }
823 
ck_generate_random(CK_SESSION_HANDLE session,CK_BYTE_PTR data,CK_ULONG length)824 CK_RV ck_generate_random(CK_SESSION_HANDLE session, CK_BYTE_PTR data,
825 			 CK_ULONG length)
826 {
827 	CK_RV rv = CKR_GENERAL_ERROR;
828 	size_t ctrl_size = 0;
829 	TEEC_SharedMemory *ctrl = NULL;
830 	TEEC_SharedMemory *out_shm = NULL;
831 	uint32_t session_handle = session;
832 	size_t out_size = 0;
833 
834 	if (!data && length)
835 		return CKR_ARGUMENTS_BAD;
836 
837 	if (!data)
838 		return CKR_OK;
839 
840 	/* Shm io0: (i/o) [session-handle] / [status] */
841 	ctrl_size = sizeof(session_handle);
842 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
843 	if (!ctrl)
844 		return CKR_HOST_MEMORY;
845 
846 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
847 
848 	/* Shm io2: (out) [generated random] */
849 	out_shm = ckteec_register_shm(data, length, CKTEEC_SHM_OUT);
850 	if (!out_shm) {
851 		rv = CKR_HOST_MEMORY;
852 		goto out;
853 	}
854 
855 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GENERATE_RANDOM, ctrl, out_shm,
856 				    &out_size);
857 
858 out:
859 	ckteec_free_shm(out_shm);
860 	ckteec_free_shm(ctrl);
861 
862 	return rv;
863 }
864