]> git.proxmox.com Git - swtpm.git/blob - src/swtpm/cuse_tpm.c
swtpm: Implemented support for PTM_SET_BUFFERSIZE command
[swtpm.git] / src / swtpm / cuse_tpm.c
1 /********************************************************************************/
2 /* */
3 /* CUSE TPM */
4 /* IBM Thomas J. Watson Research Center */
5 /* */
6 /* (c) Copyright IBM Corporation 2014-2015. */
7 /* */
8 /* All rights reserved. */
9 /* */
10 /* Redistribution and use in source and binary forms, with or without */
11 /* modification, are permitted provided that the following conditions are */
12 /* met: */
13 /* */
14 /* Redistributions of source code must retain the above copyright notice, */
15 /* this list of conditions and the following disclaimer. */
16 /* */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in the */
19 /* documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the names of the IBM Corporation nor the names of its */
22 /* contributors may be used to endorse or promote products derived from */
23 /* this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
28 /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
31 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
32 /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
33 /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
34 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
35 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /********************************************************************************/
37
38 /*
39 * Authors:
40 * Eric Richter, erichte@us.ibm.com
41 * Stefan Berger, stefanb@us.ibm.com
42 * David Safford, safford@us.ibm.com
43 */
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <stdbool.h>
48 #include <string.h>
49 #include <getopt.h>
50 #include <pwd.h>
51 #include <grp.h>
52 #include <limits.h>
53 #include <errno.h>
54 #include <arpa/inet.h>
55 #include <dirent.h>
56
57 #include <fuse/cuse_lowlevel.h>
58
59 #include <glib.h>
60
61 #include <libtpms/tpm_library.h>
62 #include <libtpms/tpm_tis.h>
63 #include <libtpms/tpm_error.h>
64 #include <libtpms/tpm_memory.h>
65
66 #include "swtpm.h"
67 #include "common.h"
68 #include "tpmstate.h"
69 #include "pidfile.h"
70 #include "locality.h"
71 #include "logging.h"
72 #include "tpm_ioctl.h"
73 #include "swtpm_nvfile.h"
74 #include "tpmlib.h"
75 #include "main.h"
76 #include "utils.h"
77 #include "threadpool.h"
78
79 /* maximum size of request buffer */
80 #define TPM_REQ_MAX 4096
81
82 /* buffer containing the TPM request */
83 static unsigned char *ptm_request;
84
85 /* buffer containing the TPM response */
86 static unsigned char *ptm_response;
87
88 /* the sizes of the data in the buffers */
89 static uint32_t ptm_req_len, ptm_res_len, ptm_res_tot;
90
91 /* locality applied to TPM commands */
92 static TPM_MODIFIER_INDICATOR locality;
93
94 /* whether the TPM is running (TPM_Init was received) */
95 static bool tpm_running;
96
97 /* flags on how to handle locality */
98 static uint32_t locality_flags;
99
100 #if GLIB_MAJOR_VERSION >= 2
101 # if GLIB_MINOR_VERSION >= 32
102
103 GMutex file_ops_lock;
104 # define FILE_OPS_LOCK &file_ops_lock
105
106 # else
107
108 GMutex *file_ops_lock;
109 # define FILE_OPS_LOCK file_ops_lock
110
111 # endif
112 #else
113
114 #error Unsupport glib version
115
116 #endif
117
118 struct cuse_param {
119 char *runas;
120 char *logging;
121 char *keydata;
122 char *migkeydata;
123 char *piddata;
124 char *tpmstatedata;
125 char *localitydata;
126 };
127
128 /* single message to send to the worker thread */
129 static struct thread_message msg;
130
131 #define min(a,b) ((a) < (b) ? (a) : (b))
132
133 struct stateblob {
134 uint8_t type;
135 uint8_t *data;
136 uint32_t length;
137 TPM_BOOL is_encrypted;
138 };
139
140 typedef struct stateblob_desc {
141 uint32_t blobtype;
142 TPM_BOOL decrypt;
143 TPM_BOOL is_encrypted;
144 unsigned char *data;
145 uint32_t data_length;
146 } stateblob_desc;
147
148 typedef enum tx_state_type {
149 TX_STATE_RW_COMMAND = 1,
150 TX_STATE_SET_STATE_BLOB = 2,
151 TX_STATE_GET_STATE_BLOB = 3,
152 } tx_state_type;
153
154 typedef struct transfer_state {
155 tx_state_type state;
156 /* while in TX_STATE_GET/SET_STATEBLOB */
157 uint32_t blobtype;
158 TPM_BOOL blob_is_encrypted;
159 /* while in TX_STATE_GET */
160 uint32_t offset;
161 } transfer_state;
162
163 typedef struct TPM_Response_Header {
164 uint16_t tag;
165 uint32_t paramSize;
166 uint32_t returnCode;
167 } __attribute__ ((packed)) TPM_Response_Header;
168
169 /*********************************** data *************************************/
170
171 static const char *usage =
172 "usage: %s %s [options]\n"
173 "\n"
174 "The following options are supported:\n"
175 "\n"
176 "-n NAME|--name=NAME : device name (mandatory)\n"
177 "-M MAJ|--maj=MAJ : device major number\n"
178 "-m MIN|--min=MIN : device minor number\n"
179 "--key file=<path>[,mode=aes-cbc][,format=hex|binary][,remove=[true|false]]\n"
180 " : use an AES key for the encryption of the TPM's state\n"
181 " files; use the given mode for the block encryption;\n"
182 " the key is to be provided as a hex string or in binary\n"
183 " format; the keyfile can be automatically removed using\n"
184 " the remove parameter\n"
185 "--key pwdfile=<path>[,mode=aes-cbc][,remove=[true|false]]\n"
186 " : provide a passphrase in a file; the AES key will be\n"
187 " derived from this passphrase\n"
188 "--locality [reject-locality-4][,allow-set-locality]\n"
189 " : reject-locality-4: reject any command in locality 4\n"
190 " allow-set-locality: accept SetLocality command\n"
191 "--migration-key file=<path>[,mode=aes-cbc][,format=hex|binary][,remove=[true|false]]\n"
192 " : use an AES key for the encryption of the TPM's state\n"
193 " when it is retrieved from the TPM via ioctls;\n"
194 " Setting this key ensures that the TPM's state will always\n"
195 " be encrypted when migrated\n"
196 "--migration-key pwdfile=<path>[,mode=aes-cbc][,remove=[true|false]]\n"
197 " : provide a passphrase in a file; the AES key will be\n"
198 " derived from this passphrase\n"
199 "--log file=<path>|fd=<filedescriptor>[,level=n][,prefix=<prefix>]\n"
200 " : write the TPM's log into the given file rather than\n"
201 " to the console; provide '-' for path to avoid logging\n"
202 " log level 5 and higher will enable libtpms logging;\n"
203 " all logged output will be prefixed with prefix\n"
204 "--pid file=<path> : write the process ID into the given file\n"
205 "--tpmstate dir=<dir>\n"
206 " : set the directory where the TPM's state will be written\n"
207 " into; the TPM_PATH environment variable can be used\n"
208 " instead\n"
209 "-r|--runas <user> : after creating the CUSE device, change to the given\n"
210 " user\n"
211 ""
212 "-h|--help : display this help screen and terminate\n"
213 "\n";
214
215 const static unsigned char TPM_ResetEstablishmentBit[] = {
216 0x00, 0xC1, /* TPM Request */
217 0x00, 0x00, 0x00, 0x0A, /* length (10) */
218 0x40, 0x00, 0x00, 0x0B /* TPM_ORD_ResetEstablishmentBit */
219 };
220
221 static TPM_RESULT
222 ptm_io_getlocality(TPM_MODIFIER_INDICATOR *loc, uint32_t tpmnum)
223 {
224 *loc = locality;
225 return TPM_SUCCESS;
226 }
227
228 static struct libtpms_callbacks cbs = {
229 .sizeOfStruct = sizeof(struct libtpms_callbacks),
230 .tpm_nvram_init = SWTPM_NVRAM_Init,
231 .tpm_nvram_loaddata = SWTPM_NVRAM_LoadData,
232 .tpm_nvram_storedata = SWTPM_NVRAM_StoreData,
233 .tpm_nvram_deletename = SWTPM_NVRAM_DeleteName,
234 .tpm_io_getlocality = ptm_io_getlocality,
235 };
236
237 /* the current state the transfer interface is in */
238 static transfer_state tx_state;
239
240 /************************* cached stateblob *********************************/
241
242 static stateblob_desc cached_stateblob;
243
244 /*
245 * cached_stateblob_is_loaded: is the stateblob with the given properties
246 * the one in the cache?
247 */
248 static bool cached_stateblob_is_loaded(uint32_t blobtype,
249 TPM_BOOL decrypt)
250 {
251 return (cached_stateblob.data != NULL) &&
252 (cached_stateblob.blobtype == blobtype) &&
253 (cached_stateblob.decrypt == decrypt);
254 }
255
256 /*
257 * cached_stateblob_free: Free any previously loaded state blob
258 */
259 static void cached_stateblob_free(void)
260 {
261 TPM_Free(cached_stateblob.data);
262 cached_stateblob.data = NULL;
263 cached_stateblob.data_length = 0;
264 }
265
266 /*
267 * cached_stateblob_get_bloblength: get the total length of the cached blob
268 */
269 static uint32_t cached_stateblob_get_bloblength(void)
270 {
271 return cached_stateblob.data_length;
272 }
273
274 /*
275 * cached_statblob_get: get stateblob data without copying them
276 *
277 * @offset: at which offset to get the data
278 * @bufptr: pointer to a buffer pointer used to return buffer start
279 * @length: pointer used to return number of available bytes in returned buffer
280 */
281 static int cached_stateblob_get(uint32_t offset,
282 unsigned char **bufptr, size_t *length)
283 {
284 if (cached_stateblob.data == NULL ||
285 offset > cached_stateblob.data_length)
286 return -1;
287
288 *bufptr = &cached_stateblob.data[offset];
289 *length = cached_stateblob.data_length - offset;
290
291 return 0;
292 }
293
294 /*
295 * cached_stateblob_load: load a state blob into the cache
296 *
297 * blobtype: the type of blob
298 * decrypt: whether the blob is to be decrypted
299 */
300 static TPM_RESULT cached_stateblob_load(uint32_t blobtype, TPM_BOOL decrypt)
301 {
302 TPM_RESULT res = 0;
303 const char *blobname = tpmlib_get_blobname(blobtype);
304 uint32_t tpm_number = 0;
305
306 if (!blobname)
307 return TPM_BAD_PARAMETER;
308
309 cached_stateblob_free();
310
311 if (blobtype == PTM_BLOB_TYPE_VOLATILE)
312 res = SWTPM_NVRAM_Store_Volatile();
313
314 if (res == 0)
315 res = SWTPM_NVRAM_GetStateBlob(&cached_stateblob.data,
316 &cached_stateblob.data_length,
317 tpm_number, blobname, decrypt,
318 &cached_stateblob.is_encrypted);
319
320 /* make sure the volatile state file is gone */
321 if (blobtype == PTM_BLOB_TYPE_VOLATILE)
322 SWTPM_NVRAM_DeleteName(tpm_number, blobname, FALSE);
323
324 if (res == 0) {
325 cached_stateblob.blobtype = blobtype;
326 cached_stateblob.decrypt = decrypt;
327 }
328
329 return res;
330 }
331
332 /*
333 * cached_state_blob_copy: copy the cached state blob to a destination buffer
334 *
335 * dest: destination buffer
336 * destlen: size of the buffer
337 * srcoffset: offset to copy from
338 * copied: variable to return the number of copied bytes
339 * is_encrypted: variable to return whether the blob is encrypted
340 */
341 static int cached_stateblob_copy(void *dest, size_t destlen,
342 uint32_t srcoffset, uint32_t *copied,
343 TPM_BOOL *is_encrypted)
344 {
345 int ret = -1;
346
347 *copied = 0;
348
349 if (cached_stateblob.data != NULL && cached_stateblob.data_length > 0) {
350
351 if (srcoffset < cached_stateblob.data_length) {
352 *copied = min(cached_stateblob.data_length - srcoffset, destlen);
353
354 memcpy(dest, &cached_stateblob.data[srcoffset], *copied);
355
356 *is_encrypted = cached_stateblob.is_encrypted;
357 }
358
359 ret = 0;
360 }
361
362 return ret;
363 }
364
365 /************************* worker thread ************************************/
366
367 /*
368 * worker_thread: the worker thread
369 */
370 static void worker_thread(gpointer data, gpointer user_data)
371 {
372 struct thread_message *msg = (struct thread_message *)data;
373
374 switch (msg->type) {
375 case MESSAGE_TPM_CMD:
376 TPMLIB_Process(&ptm_response, &ptm_res_len, &ptm_res_tot,
377 ptm_request, ptm_req_len);
378 break;
379 case MESSAGE_IOCTL:
380 break;
381 }
382
383 /* results are ready */
384 worker_thread_mark_done();
385 }
386
387 /***************************** utility functions ****************************/
388
389 /* _TPM_IO_TpmEstablished_Reset
390 *
391 * Reset the TPM Established bit by creating a TPM_ResetEstablishmentBit
392 * command and sending it to the TPM; we temporarily switch the locality
393 * to the one provded to this call. We wait until the TPM has processed
394 * the request.
395 */
396 static TPM_RESULT _TPM_IO_TpmEstablished_Reset(fuse_req_t req,
397 TPM_MODIFIER_INDICATOR locty)
398 {
399 TPM_RESULT res = TPM_FAIL;
400 TPM_Response_Header *tpmrh;
401 TPM_MODIFIER_INDICATOR orig_locality = locality;
402
403 locality = locty;
404
405 ptm_req_len = sizeof(TPM_ResetEstablishmentBit);
406 memcpy(ptm_request, TPM_ResetEstablishmentBit, ptm_req_len);
407
408 msg.type = MESSAGE_TPM_CMD;
409
410 worker_thread_mark_busy();
411
412 g_thread_pool_push(pool, &msg, NULL);
413
414 worker_thread_wait_done();
415
416 if (ptm_res_len >= sizeof(TPM_Response_Header)) {
417 tpmrh = (TPM_Response_Header *)ptm_response;
418 res = ntohl(tpmrh->returnCode);
419 }
420
421 locality = orig_locality;
422
423 return res;
424 }
425
426 /*
427 * tpm_start: Start the TPM
428 *
429 * Check whether the TPM's state directory exists and if it does
430 * not exists, try to creat it. Start the thread pool, initilize
431 * libtpms and allocate a global TPM request buffer.
432 *
433 * @flags: libtpms init flags
434 */
435 static int tpm_start(uint32_t flags)
436 {
437 DIR *dir;
438 const char *tpmdir = tpmstate_get_dir();
439
440 dir = opendir(tpmdir);
441 if (dir) {
442 closedir(dir);
443 } else {
444 if (mkdir(tpmdir, 0775)) {
445 logprintf(STDERR_FILENO,
446 "Error: Could not open tpmstate dir %s\n",
447 tpmdir);
448 return -1;
449 }
450 }
451
452 pool = g_thread_pool_new(worker_thread,
453 NULL,
454 1,
455 TRUE,
456 NULL);
457 if (!pool) {
458 logprintf(STDERR_FILENO,
459 "Error: Could not create the thread pool.\n");
460 return -1;
461 }
462
463 if(!ptm_request)
464 ptm_request = malloc(4096);
465 if(!ptm_request) {
466 logprintf(STDERR_FILENO,
467 "Error: Could not allocate memory for request buffer.\n");
468 goto error_del_pool;
469 }
470
471 if (tpmlib_start(&cbs, flags) != TPM_SUCCESS)
472 goto error_del_pool;
473
474 logprintf(STDOUT_FILENO,
475 "CUSE TPM successfully initialized.\n");
476
477 return 0;
478
479 error_del_pool:
480 g_thread_pool_free(pool, TRUE, TRUE);
481 pool = NULL;
482
483 return -1;
484 }
485
486 /*
487 * ptm_write_fatal_error_response: Write fatal error response
488 *
489 * Write a fatal error response into the global ptm_response buffer.
490 */
491 static void ptm_write_fatal_error_response(void)
492 {
493 tpmlib_write_fatal_error_response(&ptm_response,
494 &ptm_res_len,
495 &ptm_res_tot);
496 }
497
498 /************************************ read() support ***************************/
499
500 /*
501 * ptm_read_result: Return the TPM response packet
502 *
503 * @req: the fuse_req_t
504 * @size: the max. number of bytes to return to the requester
505 */
506 static void ptm_read_result(fuse_req_t req, size_t size)
507 {
508 int len;
509
510 if (tpm_running) {
511 /* wait until results are ready */
512 worker_thread_wait_done();
513 }
514
515 len = ptm_res_len;
516
517 if (ptm_res_len > size) {
518 len = size;
519 ptm_res_len -= size;
520 } else {
521 ptm_res_len = 0;
522 }
523
524 fuse_reply_buf(req, (const char *)ptm_response, len);
525 }
526
527 /*
528 * ptm_read_stateblob: get a TPM stateblob via the read() interface
529 *
530 * @req: the fuse_req_t
531 * @size: the number of bytes to read
532 *
533 * The internal offset into the buffer is advanced by the number
534 * of bytes that were copied. We switch back to command read/write
535 * mode if an error occurred or once all bytes were read.
536 */
537 static void ptm_read_stateblob(fuse_req_t req, size_t size)
538 {
539 unsigned char *bufptr = NULL;
540 size_t numbytes;
541 size_t tocopy;
542
543 if (cached_stateblob_get(tx_state.offset, &bufptr, &numbytes) < 0) {
544 fuse_reply_err(req, EIO);
545 tx_state.state = TX_STATE_RW_COMMAND;
546 } else {
547 tocopy = MIN(size, numbytes);
548 tx_state.offset += tocopy;
549
550 fuse_reply_buf(req, (char *)bufptr, tocopy);
551 /* last transfer indicated by less bytes available than requested */
552 if (numbytes < size) {
553 tx_state.state = TX_STATE_RW_COMMAND;
554 }
555 }
556 }
557
558 /*
559 * ptm_read: interface to POSIX read()
560 *
561 * @req: fuse_req_t
562 * @size: number of bytes to read
563 * @off: offset (not used)
564 * @fi: fuse_file_info (not used)
565 *
566 * Depending on the current state of the transfer interface (read/write)
567 * return either the results of TPM commands or a data of a TPM state blob.
568 */
569 static void ptm_read(fuse_req_t req, size_t size, off_t off,
570 struct fuse_file_info *fi)
571 {
572 switch (tx_state.state) {
573 case TX_STATE_RW_COMMAND:
574 ptm_read_result(req, size);
575 break;
576 case TX_STATE_SET_STATE_BLOB:
577 fuse_reply_err(req, EIO);
578 tx_state.state = TX_STATE_RW_COMMAND;
579 break;
580 case TX_STATE_GET_STATE_BLOB:
581 ptm_read_stateblob(req, size);
582 break;
583 }
584 }
585
586 /*************************read/write stateblob support ***********************/
587
588 /*
589 * ptm_set_stateblob_append: Append a piece of TPM state blob and transfer to TPM
590 *
591 * blobtype: the type of blob
592 * data: the data to append
593 * length: length of the data
594 * is_encrypted: whether the blob is encrypted
595 * is_last: whether this is the last part of the TPM state blob; if it is, the TPM
596 * state blob will then be transferred to the TPM
597 */
598 static TPM_RESULT
599 ptm_set_stateblob_append(uint32_t blobtype,
600 const unsigned char *data, uint32_t length,
601 bool is_encrypted, bool is_last)
602 {
603 const char *blobname;
604 TPM_RESULT res = 0;
605 static struct stateblob stateblob;
606
607 if (stateblob.type != blobtype) {
608 /* new blob; clear old data */
609 TPM_Free(stateblob.data);
610 stateblob.data = NULL;
611 stateblob.length = 0;
612 stateblob.type = blobtype;
613 stateblob.is_encrypted = is_encrypted;
614
615 /*
616 * on the first call for a new state blob we allow 0 bytes to be written
617 * this allows the user to transfer via write()
618 */
619 if (length == 0)
620 return 0;
621 }
622
623 /* append */
624 res = TPM_Realloc(&stateblob.data, stateblob.length + length);
625 if (res != 0) {
626 /* error */
627 TPM_Free(stateblob.data);
628 stateblob.data = NULL;
629 stateblob.length = 0;
630 stateblob.type = 0;
631
632 return res;
633 }
634
635 memcpy(&stateblob.data[stateblob.length], data, length);
636 stateblob.length += length;
637
638 if (!is_last) {
639 /* full packet -- expecting more data */
640 return res;
641 }
642 blobname = tpmlib_get_blobname(blobtype);
643
644 if (blobname) {
645 res = SWTPM_NVRAM_SetStateBlob(stateblob.data,
646 stateblob.length,
647 stateblob.is_encrypted,
648 0 /* tpm_number */,
649 blobname);
650 } else {
651 res = TPM_BAD_PARAMETER;
652 }
653
654 TPM_Free(stateblob.data);
655 stateblob.data = NULL;
656 stateblob.length = 0;
657 stateblob.type = 0;
658
659 /* transfer of blob is complete */
660 tx_state.state = TX_STATE_RW_COMMAND;
661
662 return res;
663 }
664
665 /*
666 * ptm_set_stateblob: set part of a TPM state blob
667 *
668 * @req: fuse_req_t
669 * pss: ptm_setstate provided via ioctl()
670 */
671 static void
672 ptm_set_stateblob(fuse_req_t req, ptm_setstate *pss)
673 {
674 TPM_RESULT res = 0;
675 TPM_BOOL is_encrypted =
676 ((pss->u.req.state_flags & PTM_STATE_FLAG_ENCRYPTED) != 0);
677 bool is_last = (sizeof(pss->u.req.data) != pss->u.req.length);
678
679 if (pss->u.req.length > sizeof(pss->u.req.data)) {
680 res = TPM_BAD_PARAMETER;
681 goto send_response;
682 }
683
684 /* transfer of blob initiated */
685 tx_state.state = TX_STATE_SET_STATE_BLOB;
686 tx_state.blobtype = pss->u.req.type;
687 tx_state.blob_is_encrypted = is_encrypted;
688 tx_state.offset = 0;
689
690 res = ptm_set_stateblob_append(pss->u.req.type,
691 pss->u.req.data,
692 pss->u.req.length,
693 is_encrypted,
694 is_last);
695
696 if (res)
697 tx_state.state = TX_STATE_RW_COMMAND;
698
699 send_response:
700 pss->u.resp.tpm_result = res;
701
702 fuse_reply_ioctl(req, 0, pss, sizeof(*pss));
703 }
704
705 /*
706 * ptm_get_stateblob_part: get part of a state blob
707 *
708 * @blobtype: the type of blob to get
709 * @buffer: the buffer this function will write the blob into
710 * @buffer_size: the size of the buffer
711 * @offset: the offset into the state blob
712 * @copied: pointer to int to indicate the number of bytes that were copied
713 * @is_encryped: returns whether the state blob is encrypted
714 */
715 static TPM_RESULT
716 ptm_get_stateblob_part(uint32_t blobtype,
717 unsigned char *buffer, size_t buffer_size,
718 uint32_t offset, uint32_t *copied,
719 TPM_BOOL decrypt, TPM_BOOL *is_encrypted)
720 {
721 TPM_RESULT res = 0;
722
723 if (!cached_stateblob_is_loaded(blobtype, decrypt)) {
724 res = cached_stateblob_load(blobtype, decrypt);
725 }
726
727 if (res == 0) {
728 cached_stateblob_copy(buffer, buffer_size,
729 offset, copied, is_encrypted);
730 }
731
732 return res;
733 }
734
735 /*
736 * ptm_get_stateblob: Get the state blob from the TPM using ioctl()
737 */
738 static void
739 ptm_get_stateblob(fuse_req_t req, ptm_getstate *pgs)
740 {
741 TPM_RESULT res = 0;
742 uint32_t blobtype = pgs->u.req.type;
743 TPM_BOOL decrypt =
744 ((pgs->u.req.state_flags & PTM_STATE_FLAG_DECRYPTED) != 0);
745 TPM_BOOL is_encrypted = FALSE;
746 uint32_t copied = 0;
747 uint32_t offset = pgs->u.req.offset;
748 uint32_t totlength;
749
750 res = ptm_get_stateblob_part(blobtype,
751 pgs->u.resp.data, sizeof(pgs->u.resp.data),
752 pgs->u.req.offset, &copied,
753 decrypt, &is_encrypted);
754
755 totlength = cached_stateblob_get_bloblength();
756
757 pgs->u.resp.state_flags = 0;
758 if (is_encrypted)
759 pgs->u.resp.state_flags |= PTM_STATE_FLAG_ENCRYPTED;
760
761 pgs->u.resp.length = copied;
762 pgs->u.resp.totlength = totlength;
763 pgs->u.resp.tpm_result = res;
764
765 if (res == 0) {
766 if (offset + copied < totlength) {
767 /* last byte was not copied */
768 tx_state.state = TX_STATE_GET_STATE_BLOB;
769 tx_state.blobtype = pgs->u.req.type;
770 tx_state.blob_is_encrypted = is_encrypted;
771 tx_state.offset = copied;
772 } else {
773 /* last byte was copied */
774 tx_state.state = TX_STATE_RW_COMMAND;
775 }
776 } else {
777 /* error occurred */
778 tx_state.state = TX_STATE_RW_COMMAND;
779 }
780
781 fuse_reply_ioctl(req, 0, pgs, sizeof(pgs->u.resp));
782 }
783
784 /*********************************** write() support *************************/
785
786 /*
787 * ptm_write_stateblob: Write the state blob using the write() interface
788 *
789 * @req: the fuse_req_t
790 * @buf: the buffer with the data
791 * @size: the number of bytes in the buffer
792 *
793 * The data are appended to an existing buffer that was created with the
794 * initial ioctl().
795 */
796 static void ptm_write_stateblob(fuse_req_t req, const char *buf, size_t size)
797 {
798 TPM_RESULT res;
799
800 res = ptm_set_stateblob_append(tx_state.blobtype,
801 (unsigned char *)buf, size,
802 tx_state.blob_is_encrypted,
803 (size == 0));
804 if (res) {
805 tx_state.state = TX_STATE_RW_COMMAND;
806 fuse_reply_err(req, EIO);
807 } else {
808 fuse_reply_write(req, size);
809 }
810 }
811
812 /*
813 * ptm_write_cmd: User writing a TPM command
814 *
815 * req: fuse_req_t
816 * buf: the buffer containing the TPM command
817 * size: the size of the buffer
818 */
819 static void ptm_write_cmd(fuse_req_t req, const char *buf, size_t size)
820 {
821 ptm_req_len = size;
822 ptm_res_len = 0;
823
824 /* prevent other threads from writing or doing ioctls */
825 g_mutex_lock(FILE_OPS_LOCK);
826
827 if (tpm_running) {
828 /* ensure that we only ever work on one TPM command */
829 if (worker_thread_is_busy()) {
830 fuse_reply_err(req, EBUSY);
831 goto cleanup;
832 }
833
834 if (ptm_req_len > TPM_REQ_MAX)
835 ptm_req_len = TPM_REQ_MAX;
836
837 /* process SetLocality command, if */
838 tpmlib_process(&ptm_response, &ptm_res_len, &ptm_res_tot,
839 (unsigned char *)buf, ptm_req_len,
840 locality_flags, &locality);
841 if (ptm_res_len)
842 goto skip_process;
843
844 if (tpmlib_is_request_cancelable(ptm_request, ptm_req_len)) {
845 /* have command processed by thread pool */
846 memcpy(ptm_request, buf, ptm_req_len);
847
848 msg.type = MESSAGE_TPM_CMD;
849
850 worker_thread_mark_busy();
851
852 g_thread_pool_push(pool, &msg, NULL);
853 } else {
854 /* direct processing */
855 TPMLIB_Process(&ptm_response, &ptm_res_len, &ptm_res_tot,
856 (unsigned char *)buf, ptm_req_len);
857 }
858 } else {
859 /* TPM not initialized; return error */
860 ptm_write_fatal_error_response();
861 }
862
863 skip_process:
864 fuse_reply_write(req, ptm_req_len);
865
866 cleanup:
867 g_mutex_unlock(FILE_OPS_LOCK);
868
869 return;
870 }
871
872 /*
873 * ptm_write: low-level write() interface; calls approriate function depending
874 * on what is being transferred using the write()
875 */
876 static void ptm_write(fuse_req_t req, const char *buf, size_t size,
877 off_t off, struct fuse_file_info *fi)
878 {
879 switch (tx_state.state) {
880 case TX_STATE_RW_COMMAND:
881 ptm_write_cmd(req, buf, size);
882 break;
883 case TX_STATE_GET_STATE_BLOB:
884 fuse_reply_err(req, EIO);
885 tx_state.state = TX_STATE_RW_COMMAND;
886 break;
887 case TX_STATE_SET_STATE_BLOB:
888 ptm_write_stateblob(req, buf, size);
889 break;
890 }
891 }
892
893 /*
894 * ptm_open: interface to POSIX open()
895 */
896 static void ptm_open(fuse_req_t req, struct fuse_file_info *fi)
897 {
898 tx_state.state = TX_STATE_RW_COMMAND;
899
900 fuse_reply_open(req, fi);
901 }
902
903 /*
904 * ptm_ioctl : ioctl execution
905 *
906 * req: the fuse_req_t used to send response with
907 * cmd: the ioctl request code
908 * arg: the pointer the application used for calling the ioctl (3rd param)
909 * fi:
910 * flags: some flags provided by fuse
911 * in_buf: the copy of the input buffer
912 * in_bufsz: size of the input buffer; provided by fuse and has size of
913 * needed buffer
914 * out_bufsz: size of the output buffer; provided by fuse and has size of
915 * needed buffer
916 */
917 static void ptm_ioctl(fuse_req_t req, int cmd, void *arg,
918 struct fuse_file_info *fi, unsigned flags,
919 const void *in_buf, size_t in_bufsz, size_t out_bufsz)
920 {
921 TPM_RESULT res = TPM_FAIL;
922 bool exit_prg = FALSE;
923 ptm_init *init_p;
924
925 /* some commands have to wait until the worker thread is done */
926 switch(cmd) {
927 case PTM_GET_CAPABILITY:
928 case PTM_SET_LOCALITY:
929 case PTM_CANCEL_TPM_CMD:
930 case PTM_GET_CONFIG:
931 case PTM_SET_BUFFERSIZE:
932 /* no need to wait */
933 break;
934 case PTM_INIT:
935 case PTM_SHUTDOWN:
936 case PTM_GET_TPMESTABLISHED:
937 case PTM_RESET_TPMESTABLISHED:
938 case PTM_HASH_START:
939 case PTM_HASH_DATA:
940 case PTM_HASH_END:
941 case PTM_STORE_VOLATILE:
942 case PTM_GET_STATEBLOB:
943 case PTM_SET_STATEBLOB:
944 if (tpm_running)
945 worker_thread_wait_done();
946 break;
947 }
948
949 /* prevent other threads from writing or doing ioctls */
950 g_mutex_lock(FILE_OPS_LOCK);
951
952 switch (cmd) {
953 case PTM_GET_CAPABILITY:
954 if (out_bufsz != sizeof(ptm_cap)) {
955 struct iovec iov = { arg, sizeof(uint8_t) };
956 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
957 } else {
958 ptm_cap ptm_caps;
959 ptm_caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN
960 | PTM_CAP_GET_TPMESTABLISHED
961 | PTM_CAP_SET_LOCALITY
962 | PTM_CAP_HASHING
963 | PTM_CAP_CANCEL_TPM_CMD
964 | PTM_CAP_STORE_VOLATILE
965 | PTM_CAP_RESET_TPMESTABLISHED
966 | PTM_CAP_GET_STATEBLOB
967 | PTM_CAP_SET_STATEBLOB
968 | PTM_CAP_STOP
969 | PTM_CAP_GET_CONFIG
970 | PTM_CAP_SET_BUFFERSIZE;
971 fuse_reply_ioctl(req, 0, &ptm_caps, sizeof(ptm_caps));
972 }
973 break;
974
975 case PTM_INIT:
976 if (in_bufsz != sizeof(ptm_init)) {
977 struct iovec iov = { arg, sizeof(uint8_t) };
978 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
979 } else {
980 init_p = (ptm_init *)in_buf;
981
982 worker_thread_end();
983
984 TPMLIB_Terminate();
985
986 tpm_running = false;
987 if (tpm_start(init_p->u.req.init_flags) < 0) {
988 res = TPM_FAIL;
989 logprintf(STDERR_FILENO,
990 "Error: Could not initialize the TPM.\n");
991 } else {
992 res = TPM_SUCCESS;
993 tpm_running = true;
994 }
995 init_p->u.resp.tpm_result = res;
996 fuse_reply_ioctl(req, 0, init_p, sizeof(*init_p));
997 }
998 break;
999
1000 case PTM_STOP:
1001 worker_thread_end();
1002
1003 res = TPM_SUCCESS;
1004 TPMLIB_Terminate();
1005
1006 tpm_running = false;
1007
1008 TPM_Free(ptm_response);
1009 ptm_response = NULL;
1010
1011 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1012
1013 break;
1014
1015 case PTM_SHUTDOWN:
1016 worker_thread_end();
1017
1018 res = TPM_SUCCESS;
1019 TPMLIB_Terminate();
1020
1021 TPM_Free(ptm_response);
1022 ptm_response = NULL;
1023
1024 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1025 exit_prg = TRUE;
1026
1027 break;
1028
1029 case PTM_GET_TPMESTABLISHED:
1030 if (!tpm_running)
1031 goto error_not_running;
1032
1033 if (out_bufsz != sizeof(ptm_est)) {
1034 struct iovec iov = { arg, sizeof(uint8_t) };
1035 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1036 } else {
1037 ptm_est te;
1038 te.u.resp.tpm_result = TPM_IO_TpmEstablished_Get(&te.u.resp.bit);
1039 fuse_reply_ioctl(req, 0, &te, sizeof(te));
1040 }
1041 break;
1042
1043 case PTM_RESET_TPMESTABLISHED:
1044 if (!tpm_running)
1045 goto error_not_running;
1046
1047 if (in_bufsz != sizeof(ptm_reset_est)) {
1048 struct iovec iov = { arg, sizeof(uint32_t) };
1049 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1050 } else {
1051 ptm_reset_est *re = (ptm_reset_est *)in_buf;
1052 if (re->u.req.loc > 4) {
1053 res = TPM_BAD_LOCALITY;
1054 } else {
1055 res = _TPM_IO_TpmEstablished_Reset(req, re->u.req.loc);
1056 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1057 }
1058 }
1059 break;
1060
1061 case PTM_SET_LOCALITY:
1062 if (in_bufsz != sizeof(ptm_loc)) {
1063 struct iovec iov = { arg, sizeof(uint32_t) };
1064 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1065 } else {
1066 ptm_loc *l = (ptm_loc *)in_buf;
1067 if (l->u.req.loc > 4 ||
1068 (l->u.req.loc == 4 &&
1069 locality_flags & LOCALITY_FLAG_REJECT_LOCALITY_4)) {
1070 res = TPM_BAD_LOCALITY;
1071 } else {
1072 res = TPM_SUCCESS;
1073 locality = l->u.req.loc;
1074 }
1075 l->u.resp.tpm_result = res;
1076 fuse_reply_ioctl(req, 0, l, sizeof(*l));
1077 }
1078 break;
1079
1080 case PTM_HASH_START:
1081 if (!tpm_running)
1082 goto error_not_running;
1083
1084 res = TPM_IO_Hash_Start();
1085 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1086 break;
1087
1088 case PTM_HASH_DATA:
1089 if (!tpm_running)
1090 goto error_not_running;
1091
1092 if (in_bufsz != sizeof(ptm_hdata)) {
1093 struct iovec iov = { arg, sizeof(uint32_t) };
1094 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1095 } else {
1096 ptm_hdata *data = (ptm_hdata *)in_buf;
1097 if (data->u.req.length <= sizeof(data->u.req.data)) {
1098 res = TPM_IO_Hash_Data(data->u.req.data,
1099 data->u.req.length);
1100 } else {
1101 res = TPM_FAIL;
1102 }
1103 data->u.resp.tpm_result = res;
1104 fuse_reply_ioctl(req, 0, data, sizeof(*data));
1105 }
1106 break;
1107
1108 case PTM_HASH_END:
1109 if (!tpm_running)
1110 goto error_not_running;
1111
1112 res = TPM_IO_Hash_End();
1113 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1114 break;
1115
1116 case PTM_CANCEL_TPM_CMD:
1117 if (!tpm_running)
1118 goto error_not_running;
1119
1120 /* for cancellation to work, the TPM would have to
1121 * execute in another thread that polls on a cancel
1122 * flag
1123 */
1124 res = TPM_FAIL;
1125 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1126 break;
1127
1128 case PTM_STORE_VOLATILE:
1129 if (!tpm_running)
1130 goto error_not_running;
1131
1132 res = SWTPM_NVRAM_Store_Volatile();
1133 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1134
1135 cached_stateblob_free();
1136 break;
1137
1138 case PTM_GET_STATEBLOB:
1139 if (!tpm_running)
1140 goto error_not_running;
1141
1142 if (in_bufsz != sizeof(ptm_getstate)) {
1143 struct iovec iov = { arg, sizeof(uint32_t) };
1144 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1145 } else {
1146 ptm_get_stateblob(req, (ptm_getstate *)in_buf);
1147 }
1148 break;
1149
1150 case PTM_SET_STATEBLOB:
1151 if (tpm_running)
1152 goto error_running;
1153
1154 /* tpm state dir must be set */
1155 SWTPM_NVRAM_Init();
1156
1157 if (in_bufsz != sizeof(ptm_setstate)) {
1158 struct iovec iov = { arg, sizeof(uint32_t) };
1159 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1160 } else {
1161 ptm_set_stateblob(req, (ptm_setstate *)in_buf);
1162 }
1163 break;
1164
1165 case PTM_GET_CONFIG:
1166 if (out_bufsz != sizeof(ptm_getconfig)) {
1167 struct iovec iov = { arg, sizeof(uint32_t) };
1168 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1169 } else {
1170 ptm_getconfig pgs;
1171 pgs.u.resp.tpm_result = 0;
1172 pgs.u.resp.flags = 0;
1173 if (SWTPM_NVRAM_Has_FileKey())
1174 pgs.u.resp.flags |= PTM_CONFIG_FLAG_FILE_KEY;
1175 if (SWTPM_NVRAM_Has_MigrationKey())
1176 pgs.u.resp.flags |= PTM_CONFIG_FLAG_MIGRATION_KEY;
1177 fuse_reply_ioctl(req, 0, &pgs, sizeof(pgs));
1178 }
1179 break;
1180
1181 case PTM_SET_BUFFERSIZE:
1182 if (out_bufsz != sizeof(ptm_setbuffersize)) {
1183 struct iovec iov = { arg, sizeof(uint32_t) };
1184 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1185 } else {
1186 ptm_setbuffersize *in_psbs = (ptm_setbuffersize *)in_buf;
1187 ptm_setbuffersize out_psbs;
1188 uint32_t buffersize, minsize, maxsize;
1189
1190 buffersize = in_psbs->u.req.buffersize;
1191
1192 if (buffersize > 0 && tpm_running)
1193 goto error_running;
1194
1195 buffersize = TPMLIB_SetBufferSize(buffersize,
1196 &minsize,
1197 &maxsize);
1198
1199 out_psbs.u.resp.tpm_result = TPM_SUCCESS;
1200 out_psbs.u.resp.buffersize = buffersize;
1201 out_psbs.u.resp.minsize = minsize;
1202 out_psbs.u.resp.maxsize = maxsize;
1203 fuse_reply_ioctl(req, 0, &out_psbs, sizeof(out_psbs));
1204 }
1205 break;
1206
1207 default:
1208 fuse_reply_err(req, EINVAL);
1209 }
1210
1211 cleanup:
1212 g_mutex_unlock(FILE_OPS_LOCK);
1213
1214 if (exit_prg) {
1215 logprintf(STDOUT_FILENO, "CUSE TPM is shutting down.\n");
1216 pidfile_remove();
1217
1218 exit(0);
1219 }
1220
1221 return;
1222
1223 error_running:
1224 error_not_running:
1225 res = TPM_BAD_ORDINAL;
1226 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1227
1228 goto cleanup;
1229 }
1230
1231 static void ptm_init_done(void *userdata)
1232 {
1233 struct cuse_param *param = userdata;
1234 int ret;
1235
1236 /* at this point the entry in /dev/ is available */
1237 if (pidfile_write(getpid()) < 0) {
1238 exit(-13);
1239 }
1240
1241 if (param->runas) {
1242 ret = change_process_owner(param->runas);
1243 if (ret)
1244 exit(ret);
1245 }
1246 }
1247
1248 static const struct cuse_lowlevel_ops clops = {
1249 .open = ptm_open,
1250 .read = ptm_read,
1251 .write = ptm_write,
1252 .ioctl = ptm_ioctl,
1253 .init_done = ptm_init_done,
1254 };
1255
1256 #ifndef HAVE_SWTPM_CUSE_MAIN
1257 int main(int argc, char **argv)
1258 {
1259 const char *prgname = argv[0];
1260 const char *iface = "";
1261 #else
1262 int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *iface)
1263 {
1264 #endif
1265 int opt, longindex = 0;
1266 static struct option longopts[] = {
1267 {"maj" , required_argument, 0, 'M'},
1268 {"min" , required_argument, 0, 'm'},
1269 {"name" , required_argument, 0, 'n'},
1270 {"runas" , required_argument, 0, 'r'},
1271 {"log" , required_argument, 0, 'l'},
1272 {"locality" , required_argument, 0, 'L'},
1273 {"key" , required_argument, 0, 'k'},
1274 {"migration-key" , required_argument, 0, 'K'},
1275 {"pid" , required_argument, 0, 'p'},
1276 {"tpmstate" , required_argument, 0, 's'},
1277 {"help" , no_argument, 0, 'h'},
1278 {"version" , no_argument, 0, 'v'},
1279 {NULL , 0 , 0, 0 },
1280 };
1281 struct cuse_info cinfo;
1282 struct cuse_param param;
1283 const char *devname = NULL;
1284 char *cinfo_argv[1];
1285 unsigned int num;
1286 struct passwd *passwd;
1287 const char *tpmdir;
1288 int n, tpmfd;
1289 char path[PATH_MAX];
1290
1291 memset(&cinfo, 0, sizeof(cinfo));
1292 memset(&param, 0, sizeof(param));
1293
1294 log_set_prefix("swtpm: ");
1295
1296 while (true) {
1297 opt = getopt_long(argc, argv, "M:m:n:r:hv", longopts, &longindex);
1298
1299 if (opt == -1)
1300 break;
1301
1302 switch (opt) {
1303 case 'M': /* major */
1304 if (sscanf(optarg, "%u", &num) != 1) {
1305 logprintf(STDERR_FILENO, "Could not parse major number\n");
1306 return -1;
1307 }
1308 if (num > 65535) {
1309 logprintf(STDERR_FILENO,
1310 "Major number outside valid range [0 - 65535]\n");
1311 return -1;
1312 }
1313 cinfo.dev_major = num;
1314 break;
1315 case 'm': /* minor */
1316 if (sscanf(optarg, "%u", &num) != 1) {
1317 logprintf(STDERR_FILENO, "Could not parse major number\n");
1318 return -1;
1319 }
1320 if (num > 65535) {
1321 logprintf(STDERR_FILENO,
1322 "Major number outside valid range [0 - 65535]\n");
1323 return -1;
1324 }
1325 cinfo.dev_minor = num;
1326 break;
1327 case 'n': /* name */
1328 if (!cinfo.dev_info_argc) {
1329 cinfo_argv[0] = calloc(1, strlen("DEVNAME=") + strlen(optarg) + 1);
1330 if (!cinfo_argv[0]) {
1331 logprintf(STDERR_FILENO, "Out of memory\n");
1332 return -1;
1333 }
1334 devname = optarg;
1335
1336 strcpy(cinfo_argv[0], "DEVNAME=");
1337 strcat(cinfo_argv[0], optarg);
1338
1339 cinfo.dev_info_argc = 1;
1340 cinfo.dev_info_argv = (const char **)cinfo_argv;
1341 }
1342 break;
1343 case 'r': /* runas */
1344 param.runas = optarg;
1345 break;
1346 case 'l': /* log */
1347 param.logging = optarg;
1348 break;
1349 case 'k': /* key */
1350 param.keydata = optarg;
1351 break;
1352 case 'K': /* migration-key */
1353 param.migkeydata = optarg;
1354 break;
1355 case 'p': /* pid */
1356 param.piddata = optarg;
1357 break;
1358 case 's': /* tpmstate */
1359 param.tpmstatedata = optarg;
1360 break;
1361 case 'L':
1362 param.localitydata = optarg;
1363 break;
1364 case 'h': /* help */
1365 fprintf(stdout, usage, prgname, iface);
1366 return 0;
1367 case 'v': /* version */
1368 fprintf(stdout, "TPM emulator CUSE interface version %d.%d.%d, "
1369 "Copyright (c) 2014-2015 IBM Corp.\n",
1370 SWTPM_VER_MAJOR,
1371 SWTPM_VER_MINOR,
1372 SWTPM_VER_MICRO);
1373 return 0;
1374 }
1375 }
1376
1377 if (optind < argc) {
1378 logprintf(STDERR_FILENO,
1379 "Unknown parameter '%s'\n", argv[optind]);
1380 return EXIT_FAILURE;
1381 }
1382
1383 if (!cinfo.dev_info_argv) {
1384 logprintf(STDERR_FILENO, "Error: device name missing\n");
1385 return -2;
1386 }
1387
1388 if (handle_log_options(param.logging) < 0 ||
1389 handle_key_options(param.keydata) < 0 ||
1390 handle_migration_key_options(param.migkeydata) < 0 ||
1391 handle_pid_options(param.piddata) < 0 ||
1392 handle_tpmstate_options(param.tpmstatedata) < 0 ||
1393 handle_locality_options(param.localitydata, &locality_flags) < 0)
1394 return -3;
1395
1396 if (setuid(0)) {
1397 logprintf(STDERR_FILENO, "Error: Unable to setuid root. uid = %d, "
1398 "euid = %d, gid = %d\n", getuid(), geteuid(), getgid());
1399 return -4;
1400 }
1401
1402 if (param.runas) {
1403 if (!(passwd = getpwnam(param.runas))) {
1404 logprintf(STDERR_FILENO, "User '%s' does not exist\n",
1405 param.runas);
1406 return -5;
1407 }
1408 }
1409
1410 tpmdir = tpmstate_get_dir();
1411 if (tpmdir == NULL) {
1412 logprintf(STDERR_FILENO,
1413 "Error: No TPM state directory is defined; "
1414 "TPM_PATH is not set\n");
1415 return -1;
1416 }
1417
1418 n = snprintf(path, sizeof(path), "/dev/%s", devname);
1419 if (n < 0) {
1420 logprintf(STDERR_FILENO,
1421 "Error: Could not create device file name\n");
1422 return -1;
1423 }
1424 if (n >= (int)sizeof(path)) {
1425 logprintf(STDERR_FILENO,
1426 "Error: Buffer too small to create device file name\n");
1427 return -1;
1428 }
1429
1430 tpmfd = open(path, O_RDWR);
1431 if (tpmfd >= 0) {
1432 close(tpmfd);
1433 logprintf(STDERR_FILENO,
1434 "Error: A device '%s' already exists.\n",
1435 path);
1436 return -1;
1437 }
1438
1439 worker_thread_init();
1440
1441 #if GLIB_MINOR_VERSION >= 32
1442 g_mutex_init(FILE_OPS_LOCK);
1443 #else
1444 FILE_OPS_LOCK = g_mutex_new();
1445 #endif
1446
1447 return cuse_lowlevel_main(1, argv, &cinfo, &clops, &param);
1448 }