1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017-2018, Linaro Limited
4  */
5 
6 #include <pkcs11.h>
7 #include <pkcs11_ta.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <tee_client_api.h>
12 
13 #include "pkcs11_processing.h"
14 #include "invoke_ta.h"
15 #include "serializer.h"
16 #include "serialize_ck.h"
17 
ck_create_object(CK_SESSION_HANDLE session,CK_ATTRIBUTE_PTR attribs,CK_ULONG count,CK_OBJECT_HANDLE_PTR handle)18 CK_RV ck_create_object(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR attribs,
19 		       CK_ULONG count, CK_OBJECT_HANDLE_PTR handle)
20 {
21 	CK_RV rv = CKR_GENERAL_ERROR;
22 	struct serializer obj = { 0 };
23 	size_t ctrl_size = 0;
24 	TEEC_SharedMemory *ctrl = NULL;
25 	TEEC_SharedMemory *out_shm = NULL;
26 	uint32_t session_handle = session;
27 	uint32_t key_handle = 0;
28 	char *buf = NULL;
29 	size_t out_size = 0;
30 
31 	if (!handle || !attribs || !count)
32 		return CKR_ARGUMENTS_BAD;
33 
34 	rv = serialize_ck_attributes(&obj, attribs, count);
35 	if (rv)
36 		goto out;
37 
38 	/* Shm io0: (i/o) [session-handle][serialized-attributes] / [status] */
39 	ctrl_size = sizeof(session_handle) + obj.size;
40 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
41 	if (!ctrl) {
42 		rv = CKR_HOST_MEMORY;
43 		goto out;
44 	}
45 
46 	buf = ctrl->buffer;
47 
48 	memcpy(buf, &session_handle, sizeof(session_handle));
49 	buf += sizeof(session_handle);
50 
51 	memcpy(buf, obj.buffer, obj.size);
52 
53 	/* Shm io2: (out) [object handle] */
54 	out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT);
55 	if (!out_shm) {
56 		rv = CKR_HOST_MEMORY;
57 		goto out;
58 	}
59 
60 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_CREATE_OBJECT,
61 				    ctrl, out_shm, &out_size);
62 
63 	if (rv != CKR_OK || out_size != out_shm->size) {
64 		if (rv == CKR_OK)
65 			rv = CKR_DEVICE_ERROR;
66 		goto out;
67 	}
68 
69 	memcpy(&key_handle, out_shm->buffer, sizeof(key_handle));
70 	*handle = key_handle;
71 
72 out:
73 	release_serial_object(&obj);
74 	ckteec_free_shm(out_shm);
75 	ckteec_free_shm(ctrl);
76 
77 	return rv;
78 }
79 
ck_destroy_object(CK_SESSION_HANDLE session,CK_OBJECT_HANDLE obj)80 CK_RV ck_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj)
81 {
82 	CK_RV rv = CKR_GENERAL_ERROR;
83 	TEEC_SharedMemory *ctrl = NULL;
84 	size_t ctrl_size = 0;
85 	char *buf = NULL;
86 	uint32_t session_handle = session;
87 	uint32_t obj_id = obj;
88 
89 	/* Shm io0: (i/o) ctrl = [session-handle][object-handle] / [status] */
90 	ctrl_size = sizeof(session_handle) + sizeof(obj_id);
91 
92 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
93 	if (!ctrl)
94 		return CKR_HOST_MEMORY;
95 
96 	buf = ctrl->buffer;
97 
98 	memcpy(buf, &session_handle, sizeof(session_handle));
99 	buf += sizeof(session_handle);
100 
101 	memcpy(buf, &obj_id, sizeof(obj_id));
102 
103 	rv = ckteec_invoke_ctrl(PKCS11_CMD_DESTROY_OBJECT, ctrl);
104 
105 	ckteec_free_shm(ctrl);
106 
107 	return rv;
108 }
109 
ck_encdecrypt_init(CK_SESSION_HANDLE session,CK_MECHANISM_PTR mechanism,CK_OBJECT_HANDLE key,int decrypt)110 CK_RV ck_encdecrypt_init(CK_SESSION_HANDLE session,
111 			 CK_MECHANISM_PTR mechanism,
112 			 CK_OBJECT_HANDLE key,
113 			 int decrypt)
114 {
115 	CK_RV rv = CKR_GENERAL_ERROR;
116 	TEEC_SharedMemory *ctrl = NULL;
117 	struct serializer obj = { 0 };
118 	uint32_t session_handle = session;
119 	uint32_t key_handle = key;
120 	size_t ctrl_size = 0;
121 	char *buf = NULL;
122 
123 	if (!mechanism)
124 		return CKR_ARGUMENTS_BAD;
125 
126 	rv = serialize_ck_mecha_params(&obj, mechanism);
127 	if (rv)
128 		return rv;
129 
130 	/*
131 	 * Shm io0: (in/out) ctrl
132 	 * (in) [session-handle][key-handle][serialized-mechanism-blob]
133 	 * (out) [status]
134 	 */
135 	ctrl_size = sizeof(session_handle) + sizeof(key_handle) + obj.size;
136 
137 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
138 	if (!ctrl) {
139 		rv = CKR_HOST_MEMORY;
140 		goto bail;
141 	}
142 
143 	buf = ctrl->buffer;
144 
145 	memcpy(buf, &session_handle, sizeof(session_handle));
146 	buf += sizeof(session_handle);
147 
148 	memcpy(buf, &key_handle, sizeof(key_handle));
149 	buf += sizeof(key_handle);
150 
151 	memcpy(buf, obj.buffer, obj.size);
152 
153 	rv = ckteec_invoke_ctrl(decrypt ? PKCS11_CMD_DECRYPT_INIT :
154 				PKCS11_CMD_ENCRYPT_INIT, ctrl);
155 
156 bail:
157 	ckteec_free_shm(ctrl);
158 	release_serial_object(&obj);
159 
160 	return rv;
161 }
162 
ck_encdecrypt_update(CK_SESSION_HANDLE session,CK_BYTE_PTR in,CK_ULONG in_len,CK_BYTE_PTR out,CK_ULONG_PTR out_len,int decrypt)163 CK_RV ck_encdecrypt_update(CK_SESSION_HANDLE session,
164 			   CK_BYTE_PTR in,
165 			   CK_ULONG in_len,
166 			   CK_BYTE_PTR out,
167 			   CK_ULONG_PTR out_len,
168 			   int decrypt)
169 {
170 	CK_RV rv = CKR_GENERAL_ERROR;
171 	TEEC_SharedMemory *ctrl = NULL;
172 	TEEC_SharedMemory *in_shm = NULL;
173 	TEEC_SharedMemory *out_shm = NULL;
174 	uint32_t session_handle = session;
175 	size_t out_size = 0;
176 
177 	if (!out_len || (in_len && !in)) {
178 		rv = CKR_ARGUMENTS_BAD;
179 		goto bail;
180 	}
181 
182 	/* Shm io0: (in/out) ctrl = [session-handle] / [status] */
183 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
184 	if (!ctrl) {
185 		rv = CKR_HOST_MEMORY;
186 		goto bail;
187 	}
188 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
189 
190 	/* Shm io1: input data buffer if any */
191 	if (in_len) {
192 		in_shm = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN);
193 		if (!in_shm) {
194 			rv = CKR_HOST_MEMORY;
195 			goto bail;
196 		}
197 	}
198 
199 	/* Shm io2: output data buffer */
200 	if (out && out_len && *out_len) {
201 		out_shm = ckteec_register_shm(out, *out_len, CKTEEC_SHM_OUT);
202 	} else {
203 		/* Query output data size */
204 		out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT);
205 	}
206 
207 	if (!out_shm) {
208 		rv = CKR_HOST_MEMORY;
209 		goto bail;
210 	}
211 
212 	/* Invoke */
213 	rv = ckteec_invoke_ta(decrypt ? PKCS11_CMD_DECRYPT_UPDATE :
214 			      PKCS11_CMD_ENCRYPT_UPDATE, ctrl,
215 			      in_shm, out_shm, &out_size, NULL, NULL);
216 
217 	if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
218 		*out_len = out_size;
219 
220 	if (rv == CKR_BUFFER_TOO_SMALL && out_size && !out)
221 		rv = CKR_OK;
222 
223 	goto bail_invoked;
224 
225 bail:
226 	ck_release_active_processing(session, decrypt ?
227 				     PKCS11_CMD_DECRYPT_UPDATE :
228 				     PKCS11_CMD_ENCRYPT_UPDATE);
229 bail_invoked:
230 	ckteec_free_shm(out_shm);
231 	ckteec_free_shm(in_shm);
232 	ckteec_free_shm(ctrl);
233 
234 	return rv;
235 }
236 
ck_encdecrypt_oneshot(CK_SESSION_HANDLE session,CK_BYTE_PTR in,CK_ULONG in_len,CK_BYTE_PTR out,CK_ULONG_PTR out_len,int decrypt)237 CK_RV ck_encdecrypt_oneshot(CK_SESSION_HANDLE session,
238 			    CK_BYTE_PTR in,
239 			    CK_ULONG in_len,
240 			    CK_BYTE_PTR out,
241 			    CK_ULONG_PTR out_len,
242 			    int decrypt)
243 {
244 	CK_RV rv = CKR_GENERAL_ERROR;
245 	TEEC_SharedMemory *ctrl = NULL;
246 	TEEC_SharedMemory *in_shm = NULL;
247 	TEEC_SharedMemory *out_shm = NULL;
248 	uint32_t session_handle = session;
249 	size_t out_size = 0;
250 
251 	if (!out_len || (in_len && !in)) {
252 		rv = CKR_ARGUMENTS_BAD;
253 		goto bail;
254 	}
255 
256 	/* Shm io0: (in/out) ctrl = [session-handle] / [status] */
257 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
258 	if (!ctrl) {
259 		rv = CKR_HOST_MEMORY;
260 		goto bail;
261 	}
262 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
263 
264 	/* Shm io1: input data buffer */
265 	in_shm = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN);
266 	if (!in_shm) {
267 		rv = CKR_HOST_MEMORY;
268 		goto bail;
269 	}
270 
271 	/* Shm io2: output data buffer */
272 	if (out && out_len && *out_len) {
273 		out_shm = ckteec_register_shm(out, *out_len, CKTEEC_SHM_OUT);
274 	} else {
275 		/* Query output data size */
276 		out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT);
277 	}
278 
279 	if (!out_shm) {
280 		rv = CKR_HOST_MEMORY;
281 		goto bail;
282 	}
283 
284 	rv = ckteec_invoke_ta(decrypt ? PKCS11_CMD_DECRYPT_ONESHOT :
285 			      PKCS11_CMD_ENCRYPT_ONESHOT, ctrl,
286 			      in_shm, out_shm, &out_size, NULL, NULL);
287 
288 	if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
289 		*out_len = out_size;
290 
291 	if (rv == CKR_BUFFER_TOO_SMALL && out_size && !out)
292 		rv = CKR_OK;
293 
294 	goto bail_invoked;
295 
296 bail:
297 	ck_release_active_processing(session, decrypt ?
298 				     PKCS11_CMD_DECRYPT_ONESHOT :
299 				     PKCS11_CMD_ENCRYPT_ONESHOT);
300 bail_invoked:
301 	ckteec_free_shm(out_shm);
302 	ckteec_free_shm(in_shm);
303 	ckteec_free_shm(ctrl);
304 
305 	return rv;
306 }
307 
ck_encdecrypt_final(CK_SESSION_HANDLE session,CK_BYTE_PTR out,CK_ULONG_PTR out_len,int decrypt)308 CK_RV ck_encdecrypt_final(CK_SESSION_HANDLE session,
309 			  CK_BYTE_PTR out,
310 			  CK_ULONG_PTR out_len,
311 			  int decrypt)
312 {
313 	CK_RV rv = CKR_GENERAL_ERROR;
314 	TEEC_SharedMemory *ctrl = NULL;
315 	TEEC_SharedMemory *out_shm = NULL;
316 	uint32_t session_handle = session;
317 	size_t out_size = 0;
318 
319 	if (!out_len) {
320 		rv = CKR_ARGUMENTS_BAD;
321 		goto bail;
322 	}
323 
324 	/* Shm io0: (in/out) ctrl = [session-handle] / [status] */
325 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
326 	if (!ctrl) {
327 		rv = CKR_HOST_MEMORY;
328 		goto bail;
329 	}
330 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
331 
332 	/* Shm io2: output buffer reference */
333 	if (out && out_len && *out_len) {
334 		out_shm = ckteec_register_shm(out, *out_len, CKTEEC_SHM_OUT);
335 	} else {
336 		/* Query output data size */
337 		out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT);
338 	}
339 
340 	if (!out_shm) {
341 		rv = CKR_HOST_MEMORY;
342 		goto bail;
343 	}
344 
345 	rv = ckteec_invoke_ctrl_out(decrypt ? PKCS11_CMD_DECRYPT_FINAL :
346 				    PKCS11_CMD_ENCRYPT_FINAL,
347 				    ctrl, out_shm, &out_size);
348 
349 	if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
350 		*out_len = out_size;
351 
352 	if (rv == CKR_BUFFER_TOO_SMALL && out_size && !out)
353 		rv = CKR_OK;
354 
355 	goto bail_invoked;
356 
357 bail:
358 	ck_release_active_processing(session, decrypt ?
359 				     PKCS11_CMD_DECRYPT_FINAL :
360 				     PKCS11_CMD_ENCRYPT_FINAL);
361 bail_invoked:
362 	ckteec_free_shm(out_shm);
363 	ckteec_free_shm(ctrl);
364 
365 	return rv;
366 }
367 
ck_digest_init(CK_SESSION_HANDLE session,CK_MECHANISM_PTR mechanism)368 CK_RV ck_digest_init(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism)
369 {
370 	CK_RV rv = CKR_GENERAL_ERROR;
371 	TEEC_SharedMemory *ctrl = NULL;
372 	struct serializer obj = { 0 };
373 	uint32_t session_handle = session;
374 	size_t ctrl_size = 0;
375 	uint8_t *buf = NULL;
376 
377 	if (!mechanism)
378 		return CKR_ARGUMENTS_BAD;
379 
380 	rv = serialize_ck_mecha_params(&obj, mechanism);
381 	if (rv)
382 		return rv;
383 
384 	/*
385 	 * Shm io0: (in/out) ctrl
386 	 * (in) [session-handle][serialized-mechanism-blob]
387 	 * (out) [status]
388 	 */
389 	ctrl_size = sizeof(session_handle) + obj.size;
390 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
391 	if (!ctrl) {
392 		rv = CKR_HOST_MEMORY;
393 		goto bail;
394 	}
395 
396 	buf = ctrl->buffer;
397 
398 	memcpy(buf, &session_handle, sizeof(session_handle));
399 	buf += sizeof(session_handle);
400 
401 	memcpy(buf, obj.buffer, obj.size);
402 
403 	rv = ckteec_invoke_ctrl(PKCS11_CMD_DIGEST_INIT, ctrl);
404 
405 bail:
406 	ckteec_free_shm(ctrl);
407 	release_serial_object(&obj);
408 
409 	return rv;
410 }
411 
ck_digest_key(CK_SESSION_HANDLE session,CK_OBJECT_HANDLE key)412 CK_RV ck_digest_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key)
413 {
414 	CK_RV rv = CKR_GENERAL_ERROR;
415 	TEEC_SharedMemory *ctrl = NULL;
416 	uint32_t session_handle = session;
417 	uint32_t key_handle = key;
418 	size_t ctrl_size = 0;
419 	uint8_t *buf = NULL;
420 
421 	/*
422 	 * Shm io0: (in/out) ctrl
423 	 * (in) [session-handle][key-handle]
424 	 * (out) [status]
425 	 */
426 	ctrl_size = sizeof(session_handle) + sizeof(key_handle);
427 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
428 	if (!ctrl)
429 		return CKR_HOST_MEMORY;
430 
431 	buf = ctrl->buffer;
432 
433 	memcpy(buf, &session_handle, sizeof(session_handle));
434 	buf += sizeof(session_handle);
435 
436 	memcpy(buf, &key_handle, sizeof(key_handle));
437 
438 	rv = ckteec_invoke_ctrl(PKCS11_CMD_DIGEST_KEY, ctrl);
439 
440 	ckteec_free_shm(ctrl);
441 
442 	return rv;
443 }
444 
ck_digest_update(CK_SESSION_HANDLE session,CK_BYTE_PTR in,CK_ULONG in_len)445 CK_RV ck_digest_update(CK_SESSION_HANDLE session, CK_BYTE_PTR in,
446 		       CK_ULONG in_len)
447 {
448 	CK_RV rv = CKR_GENERAL_ERROR;
449 	TEEC_SharedMemory *ctrl = NULL;
450 	TEEC_SharedMemory *io1 = NULL;
451 	uint32_t session_handle = session;
452 	uint8_t *buf = NULL;
453 
454 	if (!in && in_len) {
455 		rv = CKR_ARGUMENTS_BAD;
456 		goto bail;
457 	}
458 
459 	/*
460 	 * Shm io0: (in/out) ctrl = [session-handle] / [status]
461 	 */
462 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
463 	if (!ctrl) {
464 		rv = CKR_HOST_MEMORY;
465 		goto bail;
466 	}
467 	buf = ctrl->buffer;
468 
469 	memcpy(buf, &session_handle, sizeof(session_handle));
470 
471 	/* Shm io1: input payload */
472 	if (in_len && in) {
473 		io1 = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN);
474 		if (!io1) {
475 			rv = CKR_HOST_MEMORY;
476 			goto bail;
477 		}
478 	}
479 
480 	rv = ckteec_invoke_ctrl_in(PKCS11_CMD_DIGEST_UPDATE, ctrl, io1);
481 
482 	goto bail_invoked;
483 
484 bail:
485 	ck_release_active_processing(session, PKCS11_CMD_DIGEST_UPDATE);
486 bail_invoked:
487 	ckteec_free_shm(io1);
488 	ckteec_free_shm(ctrl);
489 
490 	return rv;
491 }
492 
ck_digest_oneshot(CK_SESSION_HANDLE session,CK_BYTE_PTR in,CK_ULONG in_len,CK_BYTE_PTR digest_ref,CK_ULONG_PTR digest_len)493 CK_RV ck_digest_oneshot(CK_SESSION_HANDLE session, CK_BYTE_PTR in,
494 			CK_ULONG in_len, CK_BYTE_PTR digest_ref,
495 			CK_ULONG_PTR digest_len)
496 {
497 	CK_RV rv = CKR_GENERAL_ERROR;
498 	TEEC_SharedMemory *ctrl = NULL;
499 	TEEC_SharedMemory *io1 = NULL;
500 	TEEC_SharedMemory *io2 = NULL;
501 	uint32_t session_handle = session;
502 	size_t out_size = 0;
503 	uint8_t *buf = NULL;
504 
505 	if ((!in && in_len) || !digest_len) {
506 		rv = CKR_ARGUMENTS_BAD;
507 		goto bail;
508 	}
509 
510 	/*
511 	 * Shm io0: (in/out) ctrl = [session-handle] / [status]
512 	 */
513 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
514 	if (!ctrl) {
515 		rv = CKR_HOST_MEMORY;
516 		goto bail;
517 	}
518 	buf = ctrl->buffer;
519 
520 	memcpy(buf, &session_handle, sizeof(session_handle));
521 
522 	/* Shm io1: input payload */
523 	if (in_len && in) {
524 		io1 = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN);
525 		if (!io1) {
526 			rv = CKR_HOST_MEMORY;
527 			goto bail;
528 		}
529 	}
530 
531 	/* Shm io2: output digest or null sized shm */
532 	if (digest_ref) {
533 		io2 = ckteec_register_shm(digest_ref, *digest_len,
534 					  CKTEEC_SHM_OUT);
535 	} else {
536 		/* Query size if output signature */
537 		io2 = ckteec_alloc_shm(0, CKTEEC_SHM_OUT);
538 	}
539 
540 	if (!io2) {
541 		rv = CKR_HOST_MEMORY;
542 		goto bail;
543 	}
544 
545 	rv = ckteec_invoke_ta(PKCS11_CMD_DIGEST_ONESHOT, ctrl,
546 			      io1, io2, &out_size, NULL, NULL);
547 
548 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
549 		*digest_len = out_size;
550 
551 	if (rv == CKR_BUFFER_TOO_SMALL && out_size && !digest_ref)
552 		rv = CKR_OK;
553 
554 	goto bail_invoked;
555 
556 bail:
557 	ck_release_active_processing(session, PKCS11_CMD_DIGEST_ONESHOT);
558 bail_invoked:
559 	ckteec_free_shm(io1);
560 	ckteec_free_shm(io2);
561 	ckteec_free_shm(ctrl);
562 
563 	return rv;
564 }
565 
ck_digest_final(CK_SESSION_HANDLE session,CK_BYTE_PTR digest_ref,CK_ULONG_PTR digest_len)566 CK_RV ck_digest_final(CK_SESSION_HANDLE session, CK_BYTE_PTR digest_ref,
567 		      CK_ULONG_PTR digest_len)
568 {
569 	CK_RV rv = CKR_GENERAL_ERROR;
570 	TEEC_SharedMemory *ctrl = NULL;
571 	TEEC_SharedMemory *io2 = NULL;
572 	uint32_t session_handle = session;
573 	size_t io2_size = 0;
574 	uint8_t *buf = NULL;
575 
576 	/*
577 	 * - If digest_ref == NULL AND digest_len == NULL -> need to call TA to
578 	 * terminate session.
579 	 * - If digest_len == NULL -> need to call to TA to terminate session.
580 	 * - If digest_ref == NULL BUT digest_len != NULL just operate normally
581 	 * to get size of the required buffer
582 	 */
583 	if (!digest_len) {
584 		rv = CKR_ARGUMENTS_BAD;
585 		goto bail;
586 	}
587 
588 	/*
589 	 * Shm io0: (in/out) ctrl = [session-handle] / [status]
590 	 */
591 	ctrl = ckteec_alloc_shm(sizeof(session_handle),	CKTEEC_SHM_INOUT);
592 	if (!ctrl) {
593 		rv = CKR_HOST_MEMORY;
594 		goto bail;
595 	}
596 	buf = ctrl->buffer;
597 
598 	memcpy(buf, &session_handle, sizeof(session_handle));
599 
600 	/* Shm io2: output digest or null sized shm */
601 	if (digest_ref)
602 		io2 = ckteec_register_shm(digest_ref, *digest_len,
603 					  CKTEEC_SHM_OUT);
604 	else
605 		io2 = ckteec_alloc_shm(0, CKTEEC_SHM_OUT);
606 
607 	if (!io2) {
608 		rv = CKR_HOST_MEMORY;
609 		goto bail;
610 	}
611 
612 	rv = ckteec_invoke_ta(PKCS11_CMD_DIGEST_FINAL, ctrl, NULL, io2,
613 			      &io2_size, NULL, NULL);
614 
615 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
616 		*digest_len = io2_size;
617 
618 	if (rv == CKR_BUFFER_TOO_SMALL && io2_size && !digest_ref)
619 		rv = CKR_OK;
620 
621 	goto bail_invoked;
622 
623 bail:
624 	ck_release_active_processing(session, PKCS11_CMD_DIGEST_FINAL);
625 bail_invoked:
626 	ckteec_free_shm(io2);
627 	ckteec_free_shm(ctrl);
628 
629 	return rv;
630 }
631 
ck_signverify_init(CK_SESSION_HANDLE session,CK_MECHANISM_PTR mechanism,CK_OBJECT_HANDLE key,int sign)632 CK_RV ck_signverify_init(CK_SESSION_HANDLE session,
633 			 CK_MECHANISM_PTR mechanism,
634 			 CK_OBJECT_HANDLE key,
635 			 int sign)
636 {
637 	CK_RV rv = CKR_GENERAL_ERROR;
638 	TEEC_SharedMemory *ctrl = NULL;
639 	struct serializer obj = { 0 };
640 	uint32_t session_handle = session;
641 	uint32_t key_handle = key;
642 	size_t ctrl_size = 0;
643 	char *buf = NULL;
644 
645 	if (!mechanism)
646 		return CKR_ARGUMENTS_BAD;
647 
648 	rv = serialize_ck_mecha_params(&obj, mechanism);
649 	if (rv)
650 		return rv;
651 
652 	/*
653 	 * Shm io0: (in/out) ctrl
654 	 * (in) [session-handle][key-handle][serialized-mechanism-blob]
655 	 * (out) [status]
656 	 */
657 	ctrl_size = sizeof(session_handle) + sizeof(key_handle) + obj.size;
658 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
659 	if (!ctrl) {
660 		rv = CKR_HOST_MEMORY;
661 		goto bail;
662 	}
663 
664 	buf = ctrl->buffer;
665 
666 	memcpy(buf, &session_handle, sizeof(session_handle));
667 	buf += sizeof(session_handle);
668 
669 	memcpy(buf, &key_handle, sizeof(key_handle));
670 	buf += sizeof(key_handle);
671 
672 	memcpy(buf, obj.buffer, obj.size);
673 
674 	rv = ckteec_invoke_ctrl(sign ? PKCS11_CMD_SIGN_INIT :
675 				PKCS11_CMD_VERIFY_INIT, ctrl);
676 
677 bail:
678 	ckteec_free_shm(ctrl);
679 	release_serial_object(&obj);
680 
681 	return rv;
682 }
683 
ck_signverify_update(CK_SESSION_HANDLE session,CK_BYTE_PTR in,CK_ULONG in_len,int sign)684 CK_RV ck_signverify_update(CK_SESSION_HANDLE session,
685 			   CK_BYTE_PTR in,
686 			   CK_ULONG in_len,
687 			   int sign)
688 {
689 	CK_RV rv = CKR_GENERAL_ERROR;
690 	TEEC_SharedMemory *ctrl = NULL;
691 	TEEC_SharedMemory *in_shm = NULL;
692 	uint32_t session_handle = session;
693 
694 	if (!in && in_len) {
695 		rv = CKR_ARGUMENTS_BAD;
696 		goto bail;
697 	}
698 
699 	/* Shm io0: (in/out) ctrl = [session-handle] / [status] */
700 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
701 	if (!ctrl) {
702 		rv = CKR_HOST_MEMORY;
703 		goto bail;
704 	}
705 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
706 
707 	/* Shm io1: input data */
708 	in_shm = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN);
709 	if (!in_shm) {
710 		rv = CKR_HOST_MEMORY;
711 		goto bail;
712 	}
713 
714 	rv = ckteec_invoke_ctrl_in(sign ? PKCS11_CMD_SIGN_UPDATE :
715 				   PKCS11_CMD_VERIFY_UPDATE, ctrl, in_shm);
716 
717 	goto bail_invoked;
718 
719 bail:
720 	ck_release_active_processing(session, sign ? PKCS11_CMD_SIGN_UPDATE :
721 				     PKCS11_CMD_VERIFY_UPDATE);
722 bail_invoked:
723 	ckteec_free_shm(in_shm);
724 	ckteec_free_shm(ctrl);
725 
726 	return rv;
727 }
728 
ck_signverify_oneshot(CK_SESSION_HANDLE session,CK_BYTE_PTR in,CK_ULONG in_len,CK_BYTE_PTR sign_ref,CK_ULONG_PTR sign_len,int sign)729 CK_RV ck_signverify_oneshot(CK_SESSION_HANDLE session,
730 			    CK_BYTE_PTR in,
731 			    CK_ULONG in_len,
732 			    CK_BYTE_PTR sign_ref,
733 			    CK_ULONG_PTR sign_len,
734 			    int sign)
735 {
736 	CK_RV rv = CKR_GENERAL_ERROR;
737 	TEEC_SharedMemory *ctrl = NULL;
738 	TEEC_SharedMemory *io1 = NULL;
739 	TEEC_SharedMemory *io2 = NULL;
740 	uint32_t session_handle = session;
741 	size_t out_size = 0;
742 
743 	if ((in_len && !in) || (!sign && sign_len && *sign_len && !sign_ref) ||
744 	    (sign && !sign_len)) {
745 		rv = CKR_ARGUMENTS_BAD;
746 		goto bail;
747 	}
748 
749 	/* Shm io0: (in/out) ctrl = [session-handle] / [status] */
750 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
751 	if (!ctrl) {
752 		rv = CKR_HOST_MEMORY;
753 		goto bail;
754 	}
755 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
756 
757 	/* Shm io1: input payload */
758 	if (in_len) {
759 		io1 = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN);
760 		if (!io1) {
761 			rv = CKR_HOST_MEMORY;
762 			goto bail;
763 		}
764 	}
765 
766 	/*
767 	 * Shm io2: input signature (if verifying) or null sized shm
768 	 * or
769 	 * Shm io2: output signature (if signing) or null sized shm
770 	 */
771 	if (sign_ref && sign_len && *sign_len) {
772 		io2 = ckteec_register_shm(sign_ref, *sign_len,
773 					  sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN);
774 	} else {
775 		/* Query size if output signature */
776 		io2 = ckteec_alloc_shm(0, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN);
777 	}
778 
779 	if (!io2) {
780 		rv = CKR_HOST_MEMORY;
781 		goto bail;
782 	}
783 
784 	rv = ckteec_invoke_ta(sign ? PKCS11_CMD_SIGN_ONESHOT :
785 			      PKCS11_CMD_VERIFY_ONESHOT, ctrl,
786 			      io1, io2, &out_size, NULL, NULL);
787 
788 	if (sign && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
789 		*sign_len = out_size;
790 
791 	if (rv == CKR_BUFFER_TOO_SMALL && out_size && !sign_ref)
792 		rv = CKR_OK;
793 
794 	goto bail_invoked;
795 
796 bail:
797 	ck_release_active_processing(session, sign ? PKCS11_CMD_SIGN_ONESHOT :
798 				     PKCS11_CMD_VERIFY_ONESHOT);
799 bail_invoked:
800 	ckteec_free_shm(io1);
801 	ckteec_free_shm(io2);
802 	ckteec_free_shm(ctrl);
803 
804 	return rv;
805 }
806 
ck_signverify_final(CK_SESSION_HANDLE session,CK_BYTE_PTR sign_ref,CK_ULONG_PTR sign_len,int sign)807 CK_RV ck_signverify_final(CK_SESSION_HANDLE session,
808 			  CK_BYTE_PTR sign_ref,
809 			  CK_ULONG_PTR sign_len,
810 			  int sign)
811 {
812 	CK_RV rv = CKR_GENERAL_ERROR;
813 	TEEC_SharedMemory *ctrl = NULL;
814 	TEEC_SharedMemory *io = NULL;
815 	uint32_t session_handle = session;
816 	size_t io_size = 0;
817 
818 	if ((!sign && sign_len && *sign_len && !sign_ref) ||
819 	    (sign && !sign_len)) {
820 		rv = CKR_ARGUMENTS_BAD;
821 		goto bail;
822 	}
823 
824 	/* Shm io0: (in/out) ctrl = [session-handle] / [status] */
825 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
826 	if (!ctrl) {
827 		rv = CKR_HOST_MEMORY;
828 		goto bail;
829 	}
830 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
831 
832 	/*
833 	 * Shm io1: input signature (if verifying) or null sized shm
834 	 * or
835 	 * Shm io1: output signature (if signing) or null sized shm
836 	 */
837 	if (sign_ref && sign_len && *sign_len)
838 		io = ckteec_register_shm(sign_ref, *sign_len,
839 					 sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN);
840 	else
841 		io = ckteec_alloc_shm(0, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN);
842 
843 	if (!io) {
844 		rv = CKR_HOST_MEMORY;
845 		goto bail;
846 	}
847 
848 	rv = ckteec_invoke_ta(sign ? PKCS11_CMD_SIGN_FINAL :
849 			      PKCS11_CMD_VERIFY_FINAL, ctrl, NULL, io,
850 			      &io_size, NULL, NULL);
851 
852 	if (sign && sign_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
853 		*sign_len = io_size;
854 
855 	if (rv == CKR_BUFFER_TOO_SMALL && io_size && !sign_ref)
856 		rv = CKR_OK;
857 
858 	goto bail_invoked;
859 
860 bail:
861 	ck_release_active_processing(session, sign ? PKCS11_CMD_SIGN_FINAL :
862 				     PKCS11_CMD_VERIFY_FINAL);
863 bail_invoked:
864 	ckteec_free_shm(io);
865 	ckteec_free_shm(ctrl);
866 
867 	return rv;
868 }
869 
ck_generate_key(CK_SESSION_HANDLE session,CK_MECHANISM_PTR mechanism,CK_ATTRIBUTE_PTR attribs,CK_ULONG count,CK_OBJECT_HANDLE_PTR handle)870 CK_RV ck_generate_key(CK_SESSION_HANDLE session,
871 		      CK_MECHANISM_PTR mechanism,
872 		      CK_ATTRIBUTE_PTR attribs,
873 		      CK_ULONG count,
874 		      CK_OBJECT_HANDLE_PTR handle)
875 {
876 	CK_RV rv = CKR_GENERAL_ERROR;
877 	TEEC_SharedMemory *ctrl = NULL;
878 	TEEC_SharedMemory *out_shm = NULL;
879 	struct serializer smecha = { 0 };
880 	struct serializer sattr = { 0 };
881 	uint32_t session_handle = session;
882 	size_t ctrl_size = 0;
883 	uint32_t key_handle = 0;
884 	char *buf = NULL;
885 	size_t out_size = 0;
886 
887 	if (!handle || !mechanism || (count && !attribs))
888 		return CKR_ARGUMENTS_BAD;
889 
890 	rv = serialize_ck_mecha_params(&smecha, mechanism);
891 	if (rv)
892 		return rv;
893 
894 	rv = serialize_ck_attributes(&sattr, attribs, count);
895 	if (rv)
896 		goto bail;
897 
898 	/*
899 	 * Shm io0: (in/out) ctrl
900 	 * (in) [session-handle][serialized-mecha][serialized-attributes]
901 	 * (out) [status]
902 	 */
903 	ctrl_size = sizeof(session_handle) + smecha.size + sattr.size;
904 
905 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
906 	if (!ctrl) {
907 		rv = CKR_HOST_MEMORY;
908 		goto bail;
909 	}
910 
911 	buf = ctrl->buffer;
912 
913 	memcpy(buf, &session_handle, sizeof(session_handle));
914 	buf += sizeof(session_handle);
915 
916 	memcpy(buf, smecha.buffer, smecha.size);
917 	buf += smecha.size;
918 
919 	memcpy(buf, sattr.buffer, sattr.size);
920 
921 	/* Shm io2: (out) [object handle] */
922 	out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT);
923 	if (!out_shm) {
924 		rv = CKR_HOST_MEMORY;
925 		goto bail;
926 	}
927 
928 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GENERATE_KEY,
929 				    ctrl, out_shm, &out_size);
930 
931 	if (rv != CKR_OK || out_size != out_shm->size) {
932 		if (rv == CKR_OK)
933 			rv = CKR_DEVICE_ERROR;
934 		goto bail;
935 	}
936 
937 	memcpy(&key_handle, out_shm->buffer, sizeof(key_handle));
938 	*handle = key_handle;
939 
940 bail:
941 	ckteec_free_shm(out_shm);
942 	ckteec_free_shm(ctrl);
943 	release_serial_object(&sattr);
944 	release_serial_object(&smecha);
945 
946 	return rv;
947 }
948 
ck_find_objects_init(CK_SESSION_HANDLE session,CK_ATTRIBUTE_PTR attribs,CK_ULONG count)949 CK_RV ck_find_objects_init(CK_SESSION_HANDLE session,
950 			   CK_ATTRIBUTE_PTR attribs,
951 			   CK_ULONG count)
952 {
953 	CK_RV rv = CKR_GENERAL_ERROR;
954 	TEEC_SharedMemory *ctrl = NULL;
955 	uint32_t session_handle = session;
956 	struct serializer obj = { 0 };
957 	size_t ctrl_size = 0;
958 	char *buf = NULL;
959 
960 	if (count && !attribs)
961 		return CKR_ARGUMENTS_BAD;
962 
963 	rv = serialize_ck_attributes(&obj, attribs, count);
964 	if (rv)
965 		return rv;
966 
967 	/* Shm io0: (in/out) ctrl
968 	 * (in) [session-handle][headed-serialized-attributes]
969 	 * (out) [status]
970 	 */
971 	ctrl_size = sizeof(session_handle) + obj.size;
972 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
973 	if (!ctrl) {
974 		rv = CKR_HOST_MEMORY;
975 		goto bail;
976 	}
977 
978 	buf = ctrl->buffer;
979 
980 	memcpy(buf, &session_handle, sizeof(session_handle));
981 	buf += sizeof(session_handle);
982 
983 	memcpy(buf, obj.buffer, obj.size);
984 
985 	rv = ckteec_invoke_ctrl(PKCS11_CMD_FIND_OBJECTS_INIT, ctrl);
986 
987 bail:
988 	ckteec_free_shm(ctrl);
989 	release_serial_object(&obj);
990 
991 	return rv;
992 }
993 
ck_find_objects(CK_SESSION_HANDLE session,CK_OBJECT_HANDLE_PTR obj,CK_ULONG max_count,CK_ULONG_PTR count)994 CK_RV ck_find_objects(CK_SESSION_HANDLE session,
995 		      CK_OBJECT_HANDLE_PTR obj,
996 		      CK_ULONG max_count,
997 		      CK_ULONG_PTR count)
998 
999 {
1000 	CK_RV rv = CKR_GENERAL_ERROR;
1001 	TEEC_SharedMemory *ctrl = NULL;
1002 	TEEC_SharedMemory *out_shm = NULL;
1003 	uint32_t session_handle = session;
1004 	uint32_t *handles = NULL;
1005 	size_t handles_size = max_count * sizeof(uint32_t);
1006 	CK_ULONG n = 0;
1007 	CK_ULONG last = 0;
1008 	size_t out_size = 0;
1009 
1010 	if (!count || (max_count && !obj))
1011 		return CKR_ARGUMENTS_BAD;
1012 
1013 	/* Shm io0: (in/out) ctrl = [session-handle] / [status] */
1014 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
1015 	if (!ctrl) {
1016 		rv = CKR_HOST_MEMORY;
1017 		goto bail;
1018 	}
1019 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
1020 
1021 	/* Shm io2: (out) [object handle list] */
1022 	out_shm = ckteec_alloc_shm(handles_size, CKTEEC_SHM_OUT);
1023 	if (!out_shm) {
1024 		rv = CKR_HOST_MEMORY;
1025 		goto bail;
1026 	}
1027 
1028 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_FIND_OBJECTS,
1029 				    ctrl, out_shm, &out_size);
1030 
1031 	if (rv || out_size > out_shm->size) {
1032 		if (rv == CKR_OK)
1033 			rv = CKR_DEVICE_ERROR;
1034 		goto bail;
1035 	}
1036 
1037 	handles = out_shm->buffer;
1038 	last = out_size / sizeof(uint32_t);
1039 	*count = last;
1040 
1041 	for (n = 0; n < last; n++)
1042 		obj[n] = handles[n];
1043 
1044 bail:
1045 	ckteec_free_shm(out_shm);
1046 	ckteec_free_shm(ctrl);
1047 
1048 	return rv;
1049 }
1050 
ck_find_objects_final(CK_SESSION_HANDLE session)1051 CK_RV ck_find_objects_final(CK_SESSION_HANDLE session)
1052 {
1053 	CK_RV rv = CKR_GENERAL_ERROR;
1054 	TEEC_SharedMemory *ctrl = NULL;
1055 	uint32_t session_handle = session;
1056 
1057 	/* Shm io0: (in/out) ctrl = [session-handle] / [status] */
1058 	ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT);
1059 	if (!ctrl)
1060 		return CKR_HOST_MEMORY;
1061 
1062 	memcpy(ctrl->buffer, &session_handle, sizeof(session_handle));
1063 
1064 	rv = ckteec_invoke_ctrl(PKCS11_CMD_FIND_OBJECTS_FINAL, ctrl);
1065 
1066 	ckteec_free_shm(ctrl);
1067 
1068 	return rv;
1069 }
1070 
ck_get_object_size(CK_SESSION_HANDLE session,CK_OBJECT_HANDLE obj,CK_ULONG_PTR p_size)1071 CK_RV ck_get_object_size(CK_SESSION_HANDLE session,
1072 			 CK_OBJECT_HANDLE obj,
1073 			 CK_ULONG_PTR p_size)
1074 {
1075 	CK_RV rv = CKR_GENERAL_ERROR;
1076 	TEEC_SharedMemory *ctrl = NULL;
1077 	TEEC_SharedMemory *out_shm = NULL;
1078 	size_t ctrl_size = 0;
1079 	uint32_t session_handle = session;
1080 	uint32_t obj_handle = obj;
1081 	char *buf = NULL;
1082 	size_t out_size = 0;
1083 	uint32_t u32_sz = 0;
1084 
1085 	if (!p_size)
1086 		return CKR_ARGUMENTS_BAD;
1087 
1088 	/* Shm io0: (in/out) [session][obj-handle] / [status] */
1089 	ctrl_size = sizeof(session_handle) + sizeof(obj_handle);
1090 
1091 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
1092 	if (!ctrl) {
1093 		rv = CKR_HOST_MEMORY;
1094 		goto bail;
1095 	}
1096 
1097 	buf = ctrl->buffer;
1098 
1099 	memcpy(buf, &session_handle, sizeof(session_handle));
1100 	buf += sizeof(session_handle);
1101 
1102 	memcpy(buf, &obj_handle, sizeof(obj_handle));
1103 
1104 	/* Shm io2: (out) [object size] */
1105 	out_shm = ckteec_alloc_shm(sizeof(uint32_t), CKTEEC_SHM_OUT);
1106 	if (!out_shm) {
1107 		rv = CKR_HOST_MEMORY;
1108 		goto bail;
1109 	}
1110 
1111 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GET_OBJECT_SIZE,
1112 				    ctrl, out_shm, &out_size);
1113 	if (rv)
1114 		goto bail;
1115 
1116 	if (out_shm->size != sizeof(uint32_t)) {
1117 		rv = CKR_DEVICE_ERROR;
1118 		goto bail;
1119 	}
1120 
1121 	memcpy(&u32_sz, out_shm->buffer, out_shm->size);
1122 	*p_size = u32_sz;
1123 
1124 bail:
1125 	ckteec_free_shm(out_shm);
1126 	ckteec_free_shm(ctrl);
1127 
1128 	return rv;
1129 }
1130 
ck_get_attribute_value(CK_SESSION_HANDLE session,CK_OBJECT_HANDLE obj,CK_ATTRIBUTE_PTR attribs,CK_ULONG count)1131 CK_RV ck_get_attribute_value(CK_SESSION_HANDLE session,
1132 			     CK_OBJECT_HANDLE obj,
1133 			     CK_ATTRIBUTE_PTR attribs,
1134 			     CK_ULONG count)
1135 {
1136 	CK_RV rv = CKR_GENERAL_ERROR;
1137 	CK_RV rv2 = CKR_GENERAL_ERROR;
1138 	TEEC_SharedMemory *ctrl = NULL;
1139 	TEEC_SharedMemory *out_shm = NULL;
1140 	struct serializer sattr = { 0 };
1141 	size_t ctrl_size = 0;
1142 	uint32_t session_handle = session;
1143 	uint32_t obj_handle = obj;
1144 	char *buf = NULL;
1145 	size_t out_size = 0;
1146 
1147 	if (count && !attribs)
1148 		return CKR_ARGUMENTS_BAD;
1149 
1150 	rv = serialize_ck_attributes(&sattr, attribs, count);
1151 	if (rv)
1152 		goto bail;
1153 
1154 	/* Shm io0: (in/out) [session][obj-handle][attributes] / [status] */
1155 	ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + sattr.size;
1156 
1157 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
1158 	if (!ctrl) {
1159 		rv = CKR_HOST_MEMORY;
1160 		goto bail;
1161 	}
1162 
1163 	buf = ctrl->buffer;
1164 
1165 	memcpy(buf, &session_handle, sizeof(session_handle));
1166 	buf += sizeof(session_handle);
1167 
1168 	memcpy(buf, &obj_handle, sizeof(obj_handle));
1169 	buf += sizeof(obj_handle);
1170 
1171 	memcpy(buf, sattr.buffer, sattr.size);
1172 
1173 	/* Shm io2: (out) [attributes] */
1174 	out_shm = ckteec_alloc_shm(sattr.size, CKTEEC_SHM_OUT);
1175 	if (!out_shm) {
1176 		rv = CKR_HOST_MEMORY;
1177 		goto bail;
1178 	}
1179 
1180 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GET_ATTRIBUTE_VALUE,
1181 				    ctrl, out_shm, &out_size);
1182 
1183 	if (rv == CKR_OK || rv == CKR_ATTRIBUTE_SENSITIVE ||
1184 	    rv == CKR_ATTRIBUTE_TYPE_INVALID || rv == CKR_BUFFER_TOO_SMALL) {
1185 		rv2 = deserialize_ck_attributes(out_shm->buffer, attribs,
1186 						count);
1187 		if (rv2)
1188 			rv = CKR_GENERAL_ERROR;
1189 	}
1190 
1191 bail:
1192 	ckteec_free_shm(out_shm);
1193 	ckteec_free_shm(ctrl);
1194 	release_serial_object(&sattr);
1195 
1196 	return rv;
1197 }
1198 
ck_set_attribute_value(CK_SESSION_HANDLE session,CK_OBJECT_HANDLE obj,CK_ATTRIBUTE_PTR attribs,CK_ULONG count)1199 CK_RV ck_set_attribute_value(CK_SESSION_HANDLE session,
1200 			     CK_OBJECT_HANDLE obj,
1201 			     CK_ATTRIBUTE_PTR attribs,
1202 			     CK_ULONG count)
1203 {
1204 	CK_RV rv = CKR_GENERAL_ERROR;
1205 	TEEC_SharedMemory *ctrl = NULL;
1206 	struct serializer sattr = { 0 };
1207 	size_t ctrl_size = 0;
1208 	uint32_t session_handle = session;
1209 	uint32_t obj_handle = obj;
1210 	char *buf = NULL;
1211 
1212 	if (count && !attribs)
1213 		return CKR_ARGUMENTS_BAD;
1214 
1215 	rv = serialize_ck_attributes(&sattr, attribs, count);
1216 	if (rv)
1217 		goto bail;
1218 
1219 	/* Shm io0: (in/out) [session][obj-handle][attributes] / [status] */
1220 	ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + sattr.size;
1221 
1222 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
1223 	if (!ctrl) {
1224 		rv = CKR_HOST_MEMORY;
1225 		goto bail;
1226 	}
1227 
1228 	buf = ctrl->buffer;
1229 
1230 	memcpy(buf, &session_handle, sizeof(session_handle));
1231 	buf += sizeof(session_handle);
1232 
1233 	memcpy(buf, &obj_handle, sizeof(obj_handle));
1234 	buf += sizeof(obj_handle);
1235 
1236 	memcpy(buf, sattr.buffer, sattr.size);
1237 
1238 	rv = ckteec_invoke_ctrl(PKCS11_CMD_SET_ATTRIBUTE_VALUE, ctrl);
1239 
1240 bail:
1241 	ckteec_free_shm(ctrl);
1242 	release_serial_object(&sattr);
1243 
1244 	return rv;
1245 }
1246 
ck_copy_object(CK_SESSION_HANDLE session,CK_OBJECT_HANDLE obj,CK_ATTRIBUTE_PTR attribs,CK_ULONG count,CK_OBJECT_HANDLE_PTR handle)1247 CK_RV ck_copy_object(CK_SESSION_HANDLE session,
1248 		     CK_OBJECT_HANDLE obj,
1249 		     CK_ATTRIBUTE_PTR attribs,
1250 		     CK_ULONG count,
1251 		     CK_OBJECT_HANDLE_PTR handle)
1252 {
1253 	CK_RV rv = CKR_GENERAL_ERROR;
1254 	TEEC_SharedMemory *ctrl = NULL;
1255 	TEEC_SharedMemory *out_shm = NULL;
1256 	struct serializer sattr = { 0 };
1257 	size_t ctrl_size = 0;
1258 	uint32_t session_handle = session;
1259 	uint32_t obj_handle = obj;
1260 	uint32_t key_handle = 0;
1261 	char *buf = NULL;
1262 	size_t out_size = 0;
1263 
1264 	if (!handle || (count && !attribs))
1265 		return CKR_ARGUMENTS_BAD;
1266 
1267 	rv = serialize_ck_attributes(&sattr, attribs, count);
1268 	if (rv)
1269 		goto bail;
1270 
1271 	/* Shm io0: (in/out) [session][obj-handle][attributes] / [status] */
1272 	ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + sattr.size;
1273 
1274 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
1275 	if (!ctrl) {
1276 		rv = CKR_HOST_MEMORY;
1277 		goto bail;
1278 	}
1279 
1280 	buf = ctrl->buffer;
1281 
1282 	memcpy(buf, &session_handle, sizeof(session_handle));
1283 	buf += sizeof(session_handle);
1284 
1285 	memcpy(buf, &obj_handle, sizeof(obj_handle));
1286 	buf += sizeof(obj_handle);
1287 
1288 	memcpy(buf, sattr.buffer, sattr.size);
1289 
1290 	/* Shm io2: (out) [object handle] */
1291 	out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT);
1292 	if (!out_shm) {
1293 		rv = CKR_HOST_MEMORY;
1294 		goto bail;
1295 	}
1296 
1297 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_COPY_OBJECT,
1298 				    ctrl, out_shm, &out_size);
1299 	if (rv != CKR_OK || out_size != out_shm->size) {
1300 		if (rv == CKR_OK)
1301 			rv = CKR_DEVICE_ERROR;
1302 		goto bail;
1303 	}
1304 
1305 	memcpy(&key_handle, out_shm->buffer, sizeof(key_handle));
1306 	*handle = key_handle;
1307 
1308 bail:
1309 	ckteec_free_shm(out_shm);
1310 	ckteec_free_shm(ctrl);
1311 	release_serial_object(&sattr);
1312 
1313 	return rv;
1314 }
1315 
ck_derive_key(CK_SESSION_HANDLE session,CK_MECHANISM_PTR mechanism,CK_OBJECT_HANDLE parent_key,CK_ATTRIBUTE_PTR attribs,CK_ULONG count,CK_OBJECT_HANDLE_PTR handle)1316 CK_RV ck_derive_key(CK_SESSION_HANDLE session,
1317 		    CK_MECHANISM_PTR mechanism,
1318 		    CK_OBJECT_HANDLE parent_key,
1319 		    CK_ATTRIBUTE_PTR attribs,
1320 		    CK_ULONG count,
1321 		    CK_OBJECT_HANDLE_PTR handle)
1322 {
1323 	CK_RV rv = CKR_GENERAL_ERROR;
1324 	TEEC_SharedMemory *ctrl = NULL;
1325 	TEEC_SharedMemory *out_shm = NULL;
1326 	struct serializer smecha = { 0 };
1327 	struct serializer sattr = { 0 };
1328 	uint32_t session_handle = session;
1329 	uint32_t obj_handle = parent_key;
1330 	size_t ctrl_size = 0;
1331 	uint32_t key_handle = 0;
1332 	char *buf = NULL;
1333 	size_t out_size = 0;
1334 
1335 	if (!handle || !mechanism || (count && !attribs))
1336 		return CKR_ARGUMENTS_BAD;
1337 
1338 	rv = serialize_ck_mecha_params(&smecha, mechanism);
1339 	if (rv)
1340 		return rv;
1341 
1342 	rv = serialize_ck_attributes(&sattr, attribs, count);
1343 	if (rv)
1344 		goto bail;
1345 
1346 	/*
1347 	 * Shm io0: (in/out) ctrl
1348 	 * (in) [session-handle][obj-handle][serialized-mecha][serialized-attributes]
1349 	 * (out) [status]
1350 	 */
1351 	ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + smecha.size +
1352 		    sattr.size;
1353 
1354 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
1355 	if (!ctrl) {
1356 		rv = CKR_HOST_MEMORY;
1357 		goto bail;
1358 	}
1359 
1360 	buf = ctrl->buffer;
1361 
1362 	memcpy(buf, &session_handle, sizeof(session_handle));
1363 	buf += sizeof(session_handle);
1364 
1365 	memcpy(buf, &obj_handle, sizeof(obj_handle));
1366 	buf += sizeof(obj_handle);
1367 
1368 	memcpy(buf, smecha.buffer, smecha.size);
1369 	buf += smecha.size;
1370 
1371 	memcpy(buf, sattr.buffer, sattr.size);
1372 
1373 	/* Shm io2: (out) [object handle] */
1374 	out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT);
1375 	if (!out_shm) {
1376 		rv = CKR_HOST_MEMORY;
1377 		goto bail;
1378 	}
1379 
1380 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_DERIVE_KEY,
1381 				    ctrl, out_shm, &out_size);
1382 
1383 	if (rv != CKR_OK || out_size != out_shm->size) {
1384 		if (rv == CKR_OK)
1385 			rv = CKR_DEVICE_ERROR;
1386 		goto bail;
1387 	}
1388 
1389 	memcpy(&key_handle, out_shm->buffer, sizeof(key_handle));
1390 	*handle = key_handle;
1391 
1392 bail:
1393 	ckteec_free_shm(out_shm);
1394 	ckteec_free_shm(ctrl);
1395 	release_serial_object(&sattr);
1396 	release_serial_object(&smecha);
1397 
1398 	return rv;
1399 }
1400 
ck_release_active_processing(CK_SESSION_HANDLE session,enum pkcs11_ta_cmd command)1401 CK_RV ck_release_active_processing(CK_SESSION_HANDLE session,
1402 				   enum pkcs11_ta_cmd command)
1403 {
1404 	CK_RV rv = CKR_GENERAL_ERROR;
1405 	TEEC_SharedMemory *ctrl = NULL;
1406 	uint32_t session_handle = session;
1407 	uint32_t cmd = command;
1408 	size_t ctrl_size = 0;
1409 	char *buf = NULL;
1410 
1411 	/* Shm io0: (in/out) ctrl = [session-handle][command] / [status] */
1412 	ctrl_size = sizeof(session_handle) + sizeof(cmd);
1413 
1414 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
1415 	if (!ctrl)
1416 		return CKR_HOST_MEMORY;
1417 
1418 	buf = ctrl->buffer;
1419 
1420 	memcpy(buf, &session_handle, sizeof(session_handle));
1421 	buf += sizeof(session_handle);
1422 
1423 	memcpy(buf, &cmd, sizeof(cmd));
1424 
1425 	rv = ckteec_invoke_ctrl(PKCS11_CMD_RELEASE_ACTIVE_PROCESSING, ctrl);
1426 
1427 	ckteec_free_shm(ctrl);
1428 
1429 	return rv;
1430 }
1431 
ck_generate_key_pair(CK_SESSION_HANDLE session,CK_MECHANISM_PTR mechanism,CK_ATTRIBUTE_PTR pub_attribs,CK_ULONG pub_count,CK_ATTRIBUTE_PTR priv_attribs,CK_ULONG priv_count,CK_OBJECT_HANDLE_PTR pub_key,CK_OBJECT_HANDLE_PTR priv_key)1432 CK_RV ck_generate_key_pair(CK_SESSION_HANDLE session,
1433 			   CK_MECHANISM_PTR mechanism,
1434 			   CK_ATTRIBUTE_PTR pub_attribs,
1435 			   CK_ULONG pub_count,
1436 			   CK_ATTRIBUTE_PTR priv_attribs,
1437 			   CK_ULONG priv_count,
1438 			   CK_OBJECT_HANDLE_PTR pub_key,
1439 			   CK_OBJECT_HANDLE_PTR priv_key)
1440 {
1441 	CK_RV rv = CKR_GENERAL_ERROR;
1442 	TEEC_SharedMemory *ctrl = NULL;
1443 	TEEC_SharedMemory *out_shm = NULL;
1444 	struct serializer smecha = { 0 };
1445 	struct serializer pub_sattr = { 0 };
1446 	struct serializer priv_sattr = { 0 };
1447 	uint32_t session_handle = session;
1448 	size_t ctrl_size = 0;
1449 	uint32_t *key_handle = NULL;
1450 	size_t key_handle_size = 2 * sizeof(*key_handle);
1451 	char *buf = NULL;
1452 	size_t out_size = 0;
1453 
1454 	if (!(mechanism && pub_attribs && priv_attribs && pub_key && priv_key))
1455 		return CKR_ARGUMENTS_BAD;
1456 
1457 	rv = serialize_ck_mecha_params(&smecha, mechanism);
1458 	if (rv)
1459 		return rv;
1460 
1461 	rv = serialize_ck_attributes(&pub_sattr, pub_attribs, pub_count);
1462 	if (rv)
1463 		goto bail;
1464 
1465 	rv = serialize_ck_attributes(&priv_sattr, priv_attribs, priv_count);
1466 	if (rv)
1467 		goto bail;
1468 
1469 	/*
1470 	 * Shm io0: (in/out) ctrl
1471 	 * (in) [session-handle][serialized-mecha][serialized-pub_attribs]
1472 	 *      [serialized-priv_attribs]
1473 	 * (out) [status]
1474 	 */
1475 	ctrl_size = sizeof(session_handle) + smecha.size + pub_sattr.size +
1476 		    priv_sattr.size;
1477 
1478 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
1479 	if (!ctrl) {
1480 		rv = CKR_HOST_MEMORY;
1481 		goto bail;
1482 	}
1483 
1484 	buf = ctrl->buffer;
1485 
1486 	memcpy(buf, &session_handle, sizeof(session_handle));
1487 	buf += sizeof(session_handle);
1488 
1489 	memcpy(buf, smecha.buffer, smecha.size);
1490 	buf += smecha.size;
1491 
1492 	memcpy(buf, pub_sattr.buffer, pub_sattr.size);
1493 	buf += pub_sattr.size;
1494 
1495 	memcpy(buf, priv_sattr.buffer, priv_sattr.size);
1496 
1497 	/*
1498 	 * Shm io2: (out) public key object handle][private key object handle]
1499 	 */
1500 	out_shm = ckteec_alloc_shm(key_handle_size, CKTEEC_SHM_OUT);
1501 	if (!out_shm) {
1502 		rv = CKR_HOST_MEMORY;
1503 		goto bail;
1504 	}
1505 
1506 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GENERATE_KEY_PAIR,
1507 				    ctrl, out_shm, &out_size);
1508 
1509 	if (rv != CKR_OK || out_size != out_shm->size) {
1510 		if (rv == CKR_OK)
1511 			rv = CKR_DEVICE_ERROR;
1512 		goto bail;
1513 	}
1514 
1515 	key_handle = out_shm->buffer;
1516 	*pub_key = key_handle[0];
1517 	*priv_key = key_handle[1];
1518 
1519 bail:
1520 	ckteec_free_shm(out_shm);
1521 	ckteec_free_shm(ctrl);
1522 	release_serial_object(&priv_sattr);
1523 	release_serial_object(&pub_sattr);
1524 	release_serial_object(&smecha);
1525 
1526 	return rv;
1527 }
1528 
ck_wrap_key(CK_SESSION_HANDLE session,CK_MECHANISM_PTR mechanism,CK_OBJECT_HANDLE wrapping_key,CK_OBJECT_HANDLE key,CK_BYTE_PTR wrapped_key,CK_ULONG_PTR wrapped_key_len)1529 CK_RV ck_wrap_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
1530 		  CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key,
1531 		  CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len)
1532 {
1533 	CK_RV rv = CKR_GENERAL_ERROR;
1534 	TEEC_SharedMemory *ctrl = NULL;
1535 	TEEC_SharedMemory *out_shm = NULL;
1536 	struct serializer smecha = { 0 };
1537 	uint32_t session_handle = session;
1538 	uint32_t wrp_key_handle = wrapping_key;
1539 	uint32_t key_handle = key;
1540 	size_t ctrl_size = 0;
1541 	size_t out_size = 0;
1542 	char *buf = NULL;
1543 
1544 	if (!mechanism || !wrapped_key_len)
1545 		return CKR_ARGUMENTS_BAD;
1546 
1547 	rv = serialize_ck_mecha_params(&smecha, mechanism);
1548 	if (rv)
1549 		return rv;
1550 
1551 	/*
1552 	 * Shm io0: (in/out) ctrl
1553 	 * (in) [session-handle][wrapping-key-handle][key-handle]
1554 	 *      [serialized-mecha]
1555 	 * (out) [status]
1556 	 */
1557 	ctrl_size = sizeof(session_handle) + sizeof(wrp_key_handle) +
1558 		    sizeof(key_handle) + smecha.size;
1559 
1560 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
1561 	if (!ctrl) {
1562 		rv = CKR_HOST_MEMORY;
1563 		goto bail;
1564 	}
1565 
1566 	buf = ctrl->buffer;
1567 
1568 	memcpy(buf, &session_handle, sizeof(session_handle));
1569 	buf += sizeof(session_handle);
1570 
1571 	memcpy(buf, &wrp_key_handle, sizeof(wrp_key_handle));
1572 	buf += sizeof(wrp_key_handle);
1573 
1574 	memcpy(buf, &key_handle, sizeof(key_handle));
1575 	buf += sizeof(key_handle);
1576 
1577 	memcpy(buf, smecha.buffer, smecha.size);
1578 
1579 	/* Shm io2: output buffer reference - wrapped key */
1580 	if (wrapped_key && *wrapped_key_len)
1581 		out_shm = ckteec_register_shm(wrapped_key, *wrapped_key_len,
1582 					      CKTEEC_SHM_OUT);
1583 	else
1584 		/* Query output data size */
1585 		out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT);
1586 
1587 	if (!out_shm) {
1588 		rv = CKR_HOST_MEMORY;
1589 		goto bail;
1590 	}
1591 
1592 	rv = ckteec_invoke_ctrl_out(PKCS11_CMD_WRAP_KEY, ctrl, out_shm,
1593 				    &out_size);
1594 
1595 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
1596 		*wrapped_key_len = out_size;
1597 
1598 	if (rv == CKR_BUFFER_TOO_SMALL && out_size && !wrapped_key)
1599 		rv = CKR_OK;
1600 
1601 bail:
1602 	ckteec_free_shm(out_shm);
1603 	ckteec_free_shm(ctrl);
1604 	release_serial_object(&smecha);
1605 
1606 	return rv;
1607 }
1608 
ck_unwrap_key(CK_SESSION_HANDLE session,CK_MECHANISM_PTR mechanism,CK_OBJECT_HANDLE unwrapping_key,CK_BYTE_PTR wrapped_key,CK_ULONG wrapped_key_len,CK_ATTRIBUTE_PTR attribs,CK_ULONG count,CK_OBJECT_HANDLE_PTR handle)1609 CK_RV ck_unwrap_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
1610 		    CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key,
1611 		    CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR attribs,
1612 		    CK_ULONG count, CK_OBJECT_HANDLE_PTR handle)
1613 {
1614 	CK_RV rv = CKR_GENERAL_ERROR;
1615 	TEEC_SharedMemory *ctrl = NULL;
1616 	TEEC_SharedMemory *in_shm = NULL;
1617 	TEEC_SharedMemory *out_shm = NULL;
1618 	struct serializer smecha = { 0 };
1619 	struct serializer sattr = { 0 };
1620 	uint32_t session_handle = session;
1621 	uint32_t unwrapping_key_handle = unwrapping_key;
1622 	size_t ctrl_size = 0;
1623 	uint32_t key_handle = 0;
1624 	char *buf = NULL;
1625 	size_t out_size = 0;
1626 
1627 	if (!handle || !mechanism || (count && !attribs) ||
1628 	    (wrapped_key_len && !wrapped_key))
1629 		return CKR_ARGUMENTS_BAD;
1630 
1631 	if (!unwrapping_key)
1632 		return CKR_UNWRAPPING_KEY_HANDLE_INVALID;
1633 
1634 	rv = serialize_ck_mecha_params(&smecha, mechanism);
1635 	if (rv)
1636 		return rv;
1637 
1638 	rv = serialize_ck_attributes(&sattr, attribs, count);
1639 	if (rv)
1640 		goto bail;
1641 
1642 	/*
1643 	 * Shm io0: (in/out) ctrl
1644 	 * (in) [session-handle][unwrapping-key-handle][serialized-mecha]
1645 	 *      [serialized-attributes]
1646 	 * (out) [status]
1647 	 */
1648 	ctrl_size = sizeof(session_handle) + sizeof(unwrapping_key_handle) +
1649 		    smecha.size + sattr.size;
1650 
1651 	ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT);
1652 	if (!ctrl) {
1653 		rv = CKR_HOST_MEMORY;
1654 		goto bail;
1655 	}
1656 
1657 	buf = ctrl->buffer;
1658 
1659 	memcpy(buf, &session_handle, sizeof(session_handle));
1660 	buf += sizeof(session_handle);
1661 
1662 	memcpy(buf, &unwrapping_key_handle, sizeof(unwrapping_key_handle));
1663 	buf += sizeof(unwrapping_key_handle);
1664 
1665 	memcpy(buf, smecha.buffer, smecha.size);
1666 	buf += smecha.size;
1667 
1668 	memcpy(buf, sattr.buffer, sattr.size);
1669 
1670 	/* Shm io1: input - wrapped key buffer */
1671 	in_shm = ckteec_register_shm(wrapped_key, wrapped_key_len,
1672 				     CKTEEC_SHM_IN);
1673 	if (!in_shm) {
1674 		rv = CKR_HOST_MEMORY;
1675 		goto bail;
1676 	}
1677 
1678 	/* Shm io2: (out) [object handle] */
1679 	out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT);
1680 	if (!out_shm) {
1681 		rv = CKR_HOST_MEMORY;
1682 		goto bail;
1683 	}
1684 
1685 	rv = ckteec_invoke_ta(PKCS11_CMD_UNWRAP_KEY, ctrl, in_shm, out_shm,
1686 			      &out_size, NULL, NULL);
1687 
1688 	if (rv != CKR_OK || out_size != out_shm->size) {
1689 		if (rv == CKR_OK)
1690 			rv = CKR_DEVICE_ERROR;
1691 		goto bail;
1692 	}
1693 
1694 	memcpy(&key_handle, out_shm->buffer, sizeof(key_handle));
1695 	*handle = key_handle;
1696 
1697 bail:
1698 	ckteec_free_shm(out_shm);
1699 	ckteec_free_shm(in_shm);
1700 	ckteec_free_shm(ctrl);
1701 	release_serial_object(&sattr);
1702 	release_serial_object(&smecha);
1703 
1704 	return rv;
1705 }
1706