]> git.proxmox.com Git - swtpm.git/blob - src/swtpm/cuse_tpm.c
swtpm: get rid of TPM_Malloc/TPM_Free/TPM_Realloc
[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 struct stateblob {
132 uint8_t type;
133 uint8_t *data;
134 uint32_t length;
135 TPM_BOOL is_encrypted;
136 };
137
138 typedef struct stateblob_desc {
139 uint32_t blobtype;
140 TPM_BOOL decrypt;
141 TPM_BOOL is_encrypted;
142 unsigned char *data;
143 uint32_t data_length;
144 } stateblob_desc;
145
146 typedef enum tx_state_type {
147 TX_STATE_RW_COMMAND = 1,
148 TX_STATE_SET_STATE_BLOB = 2,
149 TX_STATE_GET_STATE_BLOB = 3,
150 } tx_state_type;
151
152 typedef struct transfer_state {
153 tx_state_type state;
154 /* while in TX_STATE_GET/SET_STATEBLOB */
155 uint32_t blobtype;
156 TPM_BOOL blob_is_encrypted;
157 /* while in TX_STATE_GET */
158 uint32_t offset;
159 } transfer_state;
160
161 typedef struct TPM_Response_Header {
162 uint16_t tag;
163 uint32_t paramSize;
164 uint32_t returnCode;
165 } __attribute__ ((packed)) TPM_Response_Header;
166
167 /*********************************** data *************************************/
168
169 static const char *usage =
170 "usage: %s %s [options]\n"
171 "\n"
172 "The following options are supported:\n"
173 "\n"
174 "-n NAME|--name=NAME : device name (mandatory)\n"
175 "-M MAJ|--maj=MAJ : device major number\n"
176 "-m MIN|--min=MIN : device minor number\n"
177 "--key file=<path>[,mode=aes-cbc][,format=hex|binary][,remove=[true|false]]\n"
178 " : use an AES key for the encryption of the TPM's state\n"
179 " files; use the given mode for the block encryption;\n"
180 " the key is to be provided as a hex string or in binary\n"
181 " format; the keyfile can be automatically removed using\n"
182 " the remove parameter\n"
183 "--key pwdfile=<path>[,mode=aes-cbc][,remove=[true|false]]\n"
184 " : provide a passphrase in a file; the AES key will be\n"
185 " derived from this passphrase\n"
186 "--locality [reject-locality-4][,allow-set-locality]\n"
187 " : reject-locality-4: reject any command in locality 4\n"
188 " allow-set-locality: accept SetLocality command\n"
189 "--migration-key file=<path>[,mode=aes-cbc][,format=hex|binary][,remove=[true|false]]\n"
190 " : use an AES key for the encryption of the TPM's state\n"
191 " when it is retrieved from the TPM via ioctls;\n"
192 " Setting this key ensures that the TPM's state will always\n"
193 " be encrypted when migrated\n"
194 "--migration-key pwdfile=<path>[,mode=aes-cbc][,remove=[true|false]]\n"
195 " : provide a passphrase in a file; the AES key will be\n"
196 " derived from this passphrase\n"
197 "--log file=<path>|fd=<filedescriptor>[,level=n][,prefix=<prefix>][,truncate]\n"
198 " : write the TPM's log into the given file rather than\n"
199 " to the console; provide '-' for path to avoid logging\n"
200 " log level 5 and higher will enable libtpms logging;\n"
201 " all logged output will be prefixed with prefix;\n"
202 " the log file can be reset (truncate)\n"
203 "--pid file=<path>|fd=<filedescriptor>\n"
204 " : write the process ID into the given file\n"
205 "--tpmstate dir=<dir>[,mode=0...]\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 " mode allows to set the file mode bits of the state\n"
210 " files; the default mode is 0640;\n"
211 "-r|--runas <user> : after creating the CUSE device, change to the given\n"
212 " user\n"
213 ""
214 "-h|--help : display this help screen and terminate\n"
215 "\n";
216
217 const static unsigned char TPM_ResetEstablishmentBit[] = {
218 0x00, 0xC1, /* TPM Request */
219 0x00, 0x00, 0x00, 0x0A, /* length (10) */
220 0x40, 0x00, 0x00, 0x0B /* TPM_ORD_ResetEstablishmentBit */
221 };
222
223 static TPM_RESULT
224 ptm_io_getlocality(TPM_MODIFIER_INDICATOR *loc, uint32_t tpmnum)
225 {
226 *loc = locality;
227 return TPM_SUCCESS;
228 }
229
230 static struct libtpms_callbacks cbs = {
231 .sizeOfStruct = sizeof(struct libtpms_callbacks),
232 .tpm_nvram_init = SWTPM_NVRAM_Init,
233 .tpm_nvram_loaddata = SWTPM_NVRAM_LoadData,
234 .tpm_nvram_storedata = SWTPM_NVRAM_StoreData,
235 .tpm_nvram_deletename = SWTPM_NVRAM_DeleteName,
236 .tpm_io_getlocality = ptm_io_getlocality,
237 };
238
239 /* the current state the transfer interface is in */
240 static transfer_state tx_state;
241
242 /************************* cached stateblob *********************************/
243
244 static stateblob_desc cached_stateblob;
245
246 /*
247 * cached_stateblob_is_loaded: is the stateblob with the given properties
248 * the one in the cache?
249 */
250 static bool cached_stateblob_is_loaded(uint32_t blobtype,
251 TPM_BOOL decrypt)
252 {
253 return (cached_stateblob.data != NULL) &&
254 (cached_stateblob.blobtype == blobtype) &&
255 (cached_stateblob.decrypt == decrypt);
256 }
257
258 /*
259 * cached_stateblob_free: Free any previously loaded state blob
260 */
261 static void cached_stateblob_free(void)
262 {
263 free(cached_stateblob.data);
264 cached_stateblob.data = NULL;
265 cached_stateblob.data_length = 0;
266 }
267
268 /*
269 * cached_stateblob_get_bloblength: get the total length of the cached blob
270 */
271 static uint32_t cached_stateblob_get_bloblength(void)
272 {
273 return cached_stateblob.data_length;
274 }
275
276 /*
277 * cached_statblob_get: get stateblob data without copying them
278 *
279 * @offset: at which offset to get the data
280 * @bufptr: pointer to a buffer pointer used to return buffer start
281 * @length: pointer used to return number of available bytes in returned buffer
282 */
283 static int cached_stateblob_get(uint32_t offset,
284 unsigned char **bufptr, size_t *length)
285 {
286 if (cached_stateblob.data == NULL ||
287 offset > cached_stateblob.data_length)
288 return -1;
289
290 *bufptr = &cached_stateblob.data[offset];
291 *length = cached_stateblob.data_length - offset;
292
293 return 0;
294 }
295
296 /*
297 * cached_stateblob_load: load a state blob into the cache
298 *
299 * blobtype: the type of blob
300 * decrypt: whether the blob is to be decrypted
301 */
302 static TPM_RESULT cached_stateblob_load(uint32_t blobtype, TPM_BOOL decrypt)
303 {
304 TPM_RESULT res = 0;
305 const char *blobname = tpmlib_get_blobname(blobtype);
306 uint32_t tpm_number = 0;
307
308 if (!blobname)
309 return TPM_BAD_PARAMETER;
310
311 cached_stateblob_free();
312
313 if (blobtype == PTM_BLOB_TYPE_VOLATILE)
314 res = SWTPM_NVRAM_Store_Volatile();
315
316 if (res == 0)
317 res = SWTPM_NVRAM_GetStateBlob(&cached_stateblob.data,
318 &cached_stateblob.data_length,
319 tpm_number, blobname, decrypt,
320 &cached_stateblob.is_encrypted);
321
322 /* make sure the volatile state file is gone */
323 if (blobtype == PTM_BLOB_TYPE_VOLATILE)
324 SWTPM_NVRAM_DeleteName(tpm_number, blobname, FALSE);
325
326 if (res == 0) {
327 cached_stateblob.blobtype = blobtype;
328 cached_stateblob.decrypt = decrypt;
329 }
330
331 return res;
332 }
333
334 /*
335 * cached_state_blob_copy: copy the cached state blob to a destination buffer
336 *
337 * dest: destination buffer
338 * destlen: size of the buffer
339 * srcoffset: offset to copy from
340 * copied: variable to return the number of copied bytes
341 * is_encrypted: variable to return whether the blob is encrypted
342 */
343 static int cached_stateblob_copy(void *dest, size_t destlen,
344 uint32_t srcoffset, uint32_t *copied,
345 TPM_BOOL *is_encrypted)
346 {
347 int ret = -1;
348
349 *copied = 0;
350
351 if (cached_stateblob.data != NULL && cached_stateblob.data_length > 0) {
352
353 if (srcoffset < cached_stateblob.data_length) {
354 *copied = min(cached_stateblob.data_length - srcoffset, destlen);
355
356 memcpy(dest, &cached_stateblob.data[srcoffset], *copied);
357
358 *is_encrypted = cached_stateblob.is_encrypted;
359 }
360
361 ret = 0;
362 }
363
364 return ret;
365 }
366
367 /************************* worker thread ************************************/
368
369 /*
370 * worker_thread: the worker thread
371 */
372 static void worker_thread(gpointer data, gpointer user_data)
373 {
374 struct thread_message *msg = (struct thread_message *)data;
375
376 switch (msg->type) {
377 case MESSAGE_TPM_CMD:
378 TPMLIB_Process(&ptm_response, &ptm_res_len, &ptm_res_tot,
379 ptm_request, ptm_req_len);
380 break;
381 case MESSAGE_IOCTL:
382 break;
383 }
384
385 /* results are ready */
386 worker_thread_mark_done();
387 }
388
389 /***************************** utility functions ****************************/
390
391 /* _TPM_IO_TpmEstablished_Reset
392 *
393 * Reset the TPM Established bit by creating a TPM_ResetEstablishmentBit
394 * command and sending it to the TPM; we temporarily switch the locality
395 * to the one provded to this call. We wait until the TPM has processed
396 * the request.
397 */
398 static TPM_RESULT _TPM_IO_TpmEstablished_Reset(fuse_req_t req,
399 TPM_MODIFIER_INDICATOR locty)
400 {
401 TPM_RESULT res = TPM_FAIL;
402 TPM_Response_Header *tpmrh;
403 TPM_MODIFIER_INDICATOR orig_locality = locality;
404
405 locality = locty;
406
407 ptm_req_len = sizeof(TPM_ResetEstablishmentBit);
408 memcpy(ptm_request, TPM_ResetEstablishmentBit, ptm_req_len);
409
410 msg.type = MESSAGE_TPM_CMD;
411
412 worker_thread_mark_busy();
413
414 g_thread_pool_push(pool, &msg, NULL);
415
416 worker_thread_wait_done();
417
418 if (ptm_res_len >= sizeof(TPM_Response_Header)) {
419 tpmrh = (TPM_Response_Header *)ptm_response;
420 res = ntohl(tpmrh->returnCode);
421 }
422
423 locality = orig_locality;
424
425 return res;
426 }
427
428 /*
429 * tpm_start: Start the TPM
430 *
431 * Check whether the TPM's state directory exists and if it does
432 * not exists, try to creat it. Start the thread pool, initilize
433 * libtpms and allocate a global TPM request buffer.
434 *
435 * @flags: libtpms init flags
436 */
437 static int tpm_start(uint32_t flags)
438 {
439 DIR *dir;
440 const char *tpmdir = tpmstate_get_dir();
441
442 dir = opendir(tpmdir);
443 if (dir) {
444 closedir(dir);
445 } else {
446 if (mkdir(tpmdir, 0775)) {
447 logprintf(STDERR_FILENO,
448 "Error: Could not open tpmstate dir %s\n",
449 tpmdir);
450 return -1;
451 }
452 }
453
454 pool = g_thread_pool_new(worker_thread,
455 NULL,
456 1,
457 TRUE,
458 NULL);
459 if (!pool) {
460 logprintf(STDERR_FILENO,
461 "Error: Could not create the thread pool.\n");
462 return -1;
463 }
464
465 if(!ptm_request)
466 ptm_request = malloc(4096);
467 if(!ptm_request) {
468 logprintf(STDERR_FILENO,
469 "Error: Could not allocate memory for request buffer.\n");
470 goto error_del_pool;
471 }
472
473 if (tpmlib_start(flags) != TPM_SUCCESS)
474 goto error_del_pool;
475
476 logprintf(STDOUT_FILENO,
477 "CUSE TPM successfully initialized.\n");
478
479 return 0;
480
481 error_del_pool:
482 g_thread_pool_free(pool, TRUE, TRUE);
483 pool = NULL;
484
485 return -1;
486 }
487
488 /*
489 * ptm_write_fatal_error_response: Write fatal error response
490 *
491 * Write a fatal error response into the global ptm_response buffer.
492 */
493 static void ptm_write_fatal_error_response(void)
494 {
495 tpmlib_write_fatal_error_response(&ptm_response,
496 &ptm_res_len,
497 &ptm_res_tot);
498 }
499
500 /************************************ read() support ***************************/
501
502 /*
503 * ptm_read_result: Return the TPM response packet
504 *
505 * @req: the fuse_req_t
506 * @size: the max. number of bytes to return to the requester
507 */
508 static void ptm_read_result(fuse_req_t req, size_t size)
509 {
510 int len;
511
512 if (tpm_running) {
513 /* wait until results are ready */
514 worker_thread_wait_done();
515 }
516
517 len = ptm_res_len;
518
519 if (ptm_res_len > size) {
520 len = size;
521 ptm_res_len -= size;
522 } else {
523 ptm_res_len = 0;
524 }
525
526 fuse_reply_buf(req, (const char *)ptm_response, len);
527 }
528
529 /*
530 * ptm_read_stateblob: get a TPM stateblob via the read() interface
531 *
532 * @req: the fuse_req_t
533 * @size: the number of bytes to read
534 *
535 * The internal offset into the buffer is advanced by the number
536 * of bytes that were copied. We switch back to command read/write
537 * mode if an error occurred or once all bytes were read.
538 */
539 static void ptm_read_stateblob(fuse_req_t req, size_t size)
540 {
541 unsigned char *bufptr = NULL;
542 size_t numbytes;
543 size_t tocopy;
544
545 if (cached_stateblob_get(tx_state.offset, &bufptr, &numbytes) < 0) {
546 fuse_reply_err(req, EIO);
547 tx_state.state = TX_STATE_RW_COMMAND;
548 } else {
549 tocopy = MIN(size, numbytes);
550 tx_state.offset += tocopy;
551
552 fuse_reply_buf(req, (char *)bufptr, tocopy);
553 /* last transfer indicated by less bytes available than requested */
554 if (numbytes < size) {
555 tx_state.state = TX_STATE_RW_COMMAND;
556 }
557 }
558 }
559
560 /*
561 * ptm_read: interface to POSIX read()
562 *
563 * @req: fuse_req_t
564 * @size: number of bytes to read
565 * @off: offset (not used)
566 * @fi: fuse_file_info (not used)
567 *
568 * Depending on the current state of the transfer interface (read/write)
569 * return either the results of TPM commands or a data of a TPM state blob.
570 */
571 static void ptm_read(fuse_req_t req, size_t size, off_t off,
572 struct fuse_file_info *fi)
573 {
574 switch (tx_state.state) {
575 case TX_STATE_RW_COMMAND:
576 ptm_read_result(req, size);
577 break;
578 case TX_STATE_SET_STATE_BLOB:
579 fuse_reply_err(req, EIO);
580 tx_state.state = TX_STATE_RW_COMMAND;
581 break;
582 case TX_STATE_GET_STATE_BLOB:
583 ptm_read_stateblob(req, size);
584 break;
585 }
586 }
587
588 /*************************read/write stateblob support ***********************/
589
590 /*
591 * ptm_set_stateblob_append: Append a piece of TPM state blob and transfer to TPM
592 *
593 * blobtype: the type of blob
594 * data: the data to append
595 * length: length of the data
596 * is_encrypted: whether the blob is encrypted
597 * is_last: whether this is the last part of the TPM state blob; if it is, the TPM
598 * state blob will then be transferred to the TPM
599 */
600 static TPM_RESULT
601 ptm_set_stateblob_append(uint32_t blobtype,
602 const unsigned char *data, uint32_t length,
603 bool is_encrypted, bool is_last)
604 {
605 TPM_RESULT res = 0;
606 static struct stateblob stateblob;
607 unsigned char *tmp;
608
609 if (stateblob.type != blobtype) {
610 /* new blob; clear old data */
611 free(stateblob.data);
612 stateblob.data = NULL;
613 stateblob.length = 0;
614 stateblob.type = blobtype;
615 stateblob.is_encrypted = is_encrypted;
616
617 /*
618 * on the first call for a new state blob we allow 0 bytes to be written
619 * this allows the user to transfer via write()
620 */
621 if (length == 0)
622 return 0;
623 }
624
625 /* append */
626 tmp = realloc(stateblob.data, stateblob.length + length);
627 if (!tmp) {
628 logprintf(STDERR_FILENO,
629 "Could not allocate %u bytes.\n", stateblob.length + length);
630 /* error */
631 free(stateblob.data);
632 stateblob.data = NULL;
633 stateblob.length = 0;
634 stateblob.type = 0;
635
636 return TPM_FAIL;
637 } else
638 stateblob.data = tmp;
639
640 memcpy(&stateblob.data[stateblob.length], data, length);
641 stateblob.length += length;
642
643 if (!is_last) {
644 /* full packet -- expecting more data */
645 return res;
646 }
647
648 res = SWTPM_NVRAM_SetStateBlob(stateblob.data,
649 stateblob.length,
650 stateblob.is_encrypted,
651 0 /* tpm_number */,
652 blobtype);
653
654 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 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 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 case PTM_GET_INFO:
1208 if (out_bufsz != sizeof(ptm_getinfo)) {
1209 struct iovec iov = { arg, sizeof(uint32_t) };
1210 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1211 } else {
1212 ptm_getinfo *in_pgi = (ptm_getinfo *)in_buf;
1213 ptm_getinfo out_pgi;
1214 char *info_data;
1215 uint32_t length, offset;
1216
1217 info_data = TPMLIB_GetInfo(in_pgi->u.req.flags);
1218 if (!info_data)
1219 goto error_memory;
1220
1221 offset = in_pgi->u.req.offset;
1222 if (offset >= strlen(info_data)) {
1223 free(info_data);
1224 goto error_bad_input;
1225 }
1226
1227 length = min(strlen(info_data) + 1 - offset,
1228 sizeof(out_pgi.u.resp.buffer));
1229
1230 out_pgi.u.resp.tpm_result = 0;
1231 out_pgi.u.resp.totlength = strlen(info_data) + 1;
1232 out_pgi.u.resp.length = length;
1233 /* client has to collect whole string in case buffer is too small */
1234 memcpy(out_pgi.u.resp.buffer, &info_data[offset], length);
1235 free(info_data);
1236
1237 fuse_reply_ioctl(req, 0, &out_pgi, sizeof(out_pgi));
1238 }
1239 break;
1240
1241 default:
1242 fuse_reply_err(req, EINVAL);
1243 }
1244
1245 cleanup:
1246 g_mutex_unlock(FILE_OPS_LOCK);
1247
1248 if (exit_prg) {
1249 logprintf(STDOUT_FILENO, "CUSE TPM is shutting down.\n");
1250 pidfile_remove();
1251
1252 exit(0);
1253 }
1254
1255 return;
1256
1257 error_bad_input:
1258 res = TPM_BAD_PARAMETER;
1259 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1260
1261 goto cleanup;
1262
1263 error_running:
1264 error_not_running:
1265 res = TPM_BAD_ORDINAL;
1266 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1267
1268 goto cleanup;
1269
1270 error_memory:
1271 res = TPM_SIZE;
1272 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1273
1274 goto cleanup;
1275 }
1276
1277 static void ptm_init_done(void *userdata)
1278 {
1279 struct cuse_param *param = userdata;
1280 int ret;
1281
1282 /* at this point the entry in /dev/ is available */
1283 if (pidfile_write(getpid()) < 0) {
1284 exit(-13);
1285 }
1286
1287 if (param->runas) {
1288 ret = change_process_owner(param->runas);
1289 if (ret)
1290 exit(ret);
1291 }
1292 }
1293
1294 static const struct cuse_lowlevel_ops clops = {
1295 .open = ptm_open,
1296 .read = ptm_read,
1297 .write = ptm_write,
1298 .ioctl = ptm_ioctl,
1299 .init_done = ptm_init_done,
1300 };
1301
1302 #ifndef HAVE_SWTPM_CUSE_MAIN
1303 int main(int argc, char **argv)
1304 {
1305 const char *prgname = argv[0];
1306 const char *iface = "";
1307 #else
1308 int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *iface)
1309 {
1310 #endif
1311 int opt, longindex = 0;
1312 static struct option longopts[] = {
1313 {"maj" , required_argument, 0, 'M'},
1314 {"min" , required_argument, 0, 'm'},
1315 {"name" , required_argument, 0, 'n'},
1316 {"runas" , required_argument, 0, 'r'},
1317 {"log" , required_argument, 0, 'l'},
1318 {"locality" , required_argument, 0, 'L'},
1319 {"key" , required_argument, 0, 'k'},
1320 {"migration-key" , required_argument, 0, 'K'},
1321 {"pid" , required_argument, 0, 'p'},
1322 {"tpmstate" , required_argument, 0, 's'},
1323 {"help" , no_argument, 0, 'h'},
1324 {"version" , no_argument, 0, 'v'},
1325 {NULL , 0 , 0, 0 },
1326 };
1327 struct cuse_info cinfo;
1328 struct cuse_param param;
1329 const char *devname = NULL;
1330 char *cinfo_argv[1];
1331 unsigned int num;
1332 struct passwd *passwd;
1333 const char *tpmdir;
1334 int n, tpmfd;
1335 char path[PATH_MAX];
1336
1337 memset(&cinfo, 0, sizeof(cinfo));
1338 memset(&param, 0, sizeof(param));
1339
1340 log_set_prefix("swtpm: ");
1341
1342 while (true) {
1343 opt = getopt_long(argc, argv, "M:m:n:r:hv", longopts, &longindex);
1344
1345 if (opt == -1)
1346 break;
1347
1348 switch (opt) {
1349 case 'M': /* major */
1350 if (sscanf(optarg, "%u", &num) != 1) {
1351 logprintf(STDERR_FILENO, "Could not parse major number\n");
1352 return -1;
1353 }
1354 if (num > 65535) {
1355 logprintf(STDERR_FILENO,
1356 "Major number outside valid range [0 - 65535]\n");
1357 return -1;
1358 }
1359 cinfo.dev_major = num;
1360 break;
1361 case 'm': /* minor */
1362 if (sscanf(optarg, "%u", &num) != 1) {
1363 logprintf(STDERR_FILENO, "Could not parse major number\n");
1364 return -1;
1365 }
1366 if (num > 65535) {
1367 logprintf(STDERR_FILENO,
1368 "Major number outside valid range [0 - 65535]\n");
1369 return -1;
1370 }
1371 cinfo.dev_minor = num;
1372 break;
1373 case 'n': /* name */
1374 if (!cinfo.dev_info_argc) {
1375 cinfo_argv[0] = calloc(1, strlen("DEVNAME=") + strlen(optarg) + 1);
1376 if (!cinfo_argv[0]) {
1377 logprintf(STDERR_FILENO, "Out of memory\n");
1378 return -1;
1379 }
1380 devname = optarg;
1381
1382 strcpy(cinfo_argv[0], "DEVNAME=");
1383 strcat(cinfo_argv[0], optarg);
1384
1385 cinfo.dev_info_argc = 1;
1386 cinfo.dev_info_argv = (const char **)cinfo_argv;
1387 }
1388 break;
1389 case 'r': /* runas */
1390 param.runas = optarg;
1391 break;
1392 case 'l': /* log */
1393 param.logging = optarg;
1394 break;
1395 case 'k': /* key */
1396 param.keydata = optarg;
1397 break;
1398 case 'K': /* migration-key */
1399 param.migkeydata = optarg;
1400 break;
1401 case 'p': /* pid */
1402 param.piddata = optarg;
1403 break;
1404 case 's': /* tpmstate */
1405 param.tpmstatedata = optarg;
1406 break;
1407 case 'L':
1408 param.localitydata = optarg;
1409 break;
1410 case 'h': /* help */
1411 fprintf(stdout, usage, prgname, iface);
1412 return 0;
1413 case 'v': /* version */
1414 fprintf(stdout, "TPM emulator CUSE interface version %d.%d.%d, "
1415 "Copyright (c) 2014-2015 IBM Corp.\n",
1416 SWTPM_VER_MAJOR,
1417 SWTPM_VER_MINOR,
1418 SWTPM_VER_MICRO);
1419 return 0;
1420 }
1421 }
1422
1423 if (optind < argc) {
1424 logprintf(STDERR_FILENO,
1425 "Unknown parameter '%s'\n", argv[optind]);
1426 return EXIT_FAILURE;
1427 }
1428
1429 if (!cinfo.dev_info_argv) {
1430 logprintf(STDERR_FILENO, "Error: device name missing\n");
1431 return -2;
1432 }
1433
1434 if (handle_log_options(param.logging) < 0 ||
1435 handle_key_options(param.keydata) < 0 ||
1436 handle_migration_key_options(param.migkeydata) < 0 ||
1437 handle_pid_options(param.piddata) < 0 ||
1438 handle_tpmstate_options(param.tpmstatedata) < 0 ||
1439 handle_locality_options(param.localitydata, &locality_flags) < 0)
1440 return -3;
1441
1442 if (setuid(0)) {
1443 logprintf(STDERR_FILENO, "Error: Unable to setuid root. uid = %d, "
1444 "euid = %d, gid = %d\n", getuid(), geteuid(), getgid());
1445 return -4;
1446 }
1447
1448 if (param.runas) {
1449 if (!(passwd = getpwnam(param.runas))) {
1450 logprintf(STDERR_FILENO, "User '%s' does not exist\n",
1451 param.runas);
1452 return -5;
1453 }
1454 }
1455
1456 tpmdir = tpmstate_get_dir();
1457 if (tpmdir == NULL) {
1458 logprintf(STDERR_FILENO,
1459 "Error: No TPM state directory is defined; "
1460 "TPM_PATH is not set\n");
1461 return -1;
1462 }
1463
1464 n = snprintf(path, sizeof(path), "/dev/%s", devname);
1465 if (n < 0) {
1466 logprintf(STDERR_FILENO,
1467 "Error: Could not create device file name\n");
1468 return -1;
1469 }
1470 if (n >= (int)sizeof(path)) {
1471 logprintf(STDERR_FILENO,
1472 "Error: Buffer too small to create device file name\n");
1473 return -1;
1474 }
1475
1476 tpmfd = open(path, O_RDWR);
1477 if (tpmfd >= 0) {
1478 close(tpmfd);
1479 logprintf(STDERR_FILENO,
1480 "Error: A device '%s' already exists.\n",
1481 path);
1482 return -1;
1483 }
1484
1485 if (tpmlib_register_callbacks(&cbs) != TPM_SUCCESS)
1486 return -1;
1487
1488 worker_thread_init();
1489
1490 #if GLIB_MINOR_VERSION >= 32
1491 g_mutex_init(FILE_OPS_LOCK);
1492 #else
1493 FILE_OPS_LOCK = g_mutex_new();
1494 #endif
1495
1496 return cuse_lowlevel_main(1, argv, &cinfo, &clops, &param);
1497 }