]> git.proxmox.com Git - swtpm.git/blob - src/swtpm/cuse_tpm.c
swtpm: fix memory leak related to tpmstate directory
[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 /* version of the TPM (1.2 or 2) */
83 static TPMLIB_TPMVersion tpmversion;
84
85 /* buffer containing the TPM request */
86 static unsigned char *ptm_request;
87
88 /* buffer containing the TPM response */
89 static unsigned char *ptm_response;
90
91 /* the sizes of the data in the buffers */
92 static uint32_t ptm_req_len, ptm_res_len, ptm_res_tot;
93
94 /* locality applied to TPM commands */
95 static TPM_MODIFIER_INDICATOR locality;
96
97 /* whether the TPM is running (TPM_Init was received) */
98 static bool tpm_running;
99
100 /* flags on how to handle locality */
101 static uint32_t locality_flags;
102
103 #if GLIB_MAJOR_VERSION >= 2
104 # if GLIB_MINOR_VERSION >= 32
105
106 GMutex file_ops_lock;
107 # define FILE_OPS_LOCK &file_ops_lock
108
109 # else
110
111 GMutex *file_ops_lock;
112 # define FILE_OPS_LOCK file_ops_lock
113
114 # endif
115 #else
116
117 #error Unsupport glib version
118
119 #endif
120
121 struct cuse_param {
122 char *runas;
123 char *logging;
124 char *keydata;
125 char *migkeydata;
126 char *piddata;
127 char *tpmstatedata;
128 char *localitydata;
129 };
130
131 /* single message to send to the worker thread */
132 static struct thread_message msg;
133
134 struct stateblob {
135 uint8_t type;
136 uint8_t *data;
137 uint32_t length;
138 TPM_BOOL is_encrypted;
139 };
140
141 typedef struct stateblob_desc {
142 uint32_t blobtype;
143 TPM_BOOL decrypt;
144 TPM_BOOL is_encrypted;
145 unsigned char *data;
146 uint32_t data_length;
147 } stateblob_desc;
148
149 typedef enum tx_state_type {
150 TX_STATE_RW_COMMAND = 1,
151 TX_STATE_SET_STATE_BLOB = 2,
152 TX_STATE_GET_STATE_BLOB = 3,
153 } tx_state_type;
154
155 typedef struct transfer_state {
156 tx_state_type state;
157 /* while in TX_STATE_GET/SET_STATEBLOB */
158 uint32_t blobtype;
159 TPM_BOOL blob_is_encrypted;
160 /* while in TX_STATE_GET */
161 uint32_t offset;
162 } transfer_state;
163
164 typedef struct TPM_Response_Header {
165 uint16_t tag;
166 uint32_t paramSize;
167 uint32_t returnCode;
168 } __attribute__ ((packed)) TPM_Response_Header;
169
170 /*********************************** data *************************************/
171
172 static const char *usage =
173 "usage: %s %s [options]\n"
174 "\n"
175 "The following options are supported:\n"
176 "\n"
177 "-n NAME|--name=NAME : device name (mandatory)\n"
178 "-M MAJ|--maj=MAJ : device major number\n"
179 "-m MIN|--min=MIN : device minor number\n"
180 "--key file=<path>[,mode=aes-cbc][,format=hex|binary][,remove=[true|false]]\n"
181 " : use an AES key for the encryption of the TPM's state\n"
182 " files; use the given mode for the block encryption;\n"
183 " the key is to be provided as a hex string or in binary\n"
184 " format; the keyfile can be automatically removed using\n"
185 " the remove parameter\n"
186 "--key pwdfile=<path>[,mode=aes-cbc][,remove=[true|false]]\n"
187 " : provide a passphrase in a file; the AES key will be\n"
188 " derived from this passphrase\n"
189 "--locality [reject-locality-4][,allow-set-locality]\n"
190 " : reject-locality-4: reject any command in locality 4\n"
191 " allow-set-locality: accept SetLocality command\n"
192 "--migration-key file=<path>[,mode=aes-cbc][,format=hex|binary][,remove=[true|false]]\n"
193 " : use an AES key for the encryption of the TPM's state\n"
194 " when it is retrieved from the TPM via ioctls;\n"
195 " Setting this key ensures that the TPM's state will always\n"
196 " be encrypted when migrated\n"
197 "--migration-key pwdfile=<path>[,mode=aes-cbc][,remove=[true|false]]\n"
198 " : provide a passphrase in a file; the AES key will be\n"
199 " derived from this passphrase\n"
200 "--log file=<path>|fd=<filedescriptor>[,level=n][,prefix=<prefix>][,truncate]\n"
201 " : write the TPM's log into the given file rather than\n"
202 " to the console; provide '-' for path to avoid logging\n"
203 " log level 5 and higher will enable libtpms logging;\n"
204 " all logged output will be prefixed with prefix;\n"
205 " the log file can be reset (truncate)\n"
206 "--pid file=<path>|fd=<filedescriptor>\n"
207 " : write the process ID into the given file\n"
208 "--tpmstate dir=<dir>[,mode=0...]\n"
209 " : set the directory where the TPM's state will be written\n"
210 " into; the TPM_PATH environment variable can be used\n"
211 " instead;\n"
212 " mode allows to set the file mode bits of the state\n"
213 " files; the default mode is 0640;\n"
214 "-r|--runas <user> : after creating the CUSE device, change to the given\n"
215 " user\n"
216 "--tpm2 : choose TPM2 functionality\n"
217 "-h|--help : display this help screen and terminate\n"
218 "\n";
219
220 static TPM_RESULT
221 ptm_io_getlocality(TPM_MODIFIER_INDICATOR *loc, uint32_t tpmnum)
222 {
223 *loc = locality;
224 return TPM_SUCCESS;
225 }
226
227 static struct libtpms_callbacks cbs = {
228 .sizeOfStruct = sizeof(struct libtpms_callbacks),
229 .tpm_nvram_init = SWTPM_NVRAM_Init,
230 .tpm_nvram_loaddata = SWTPM_NVRAM_LoadData,
231 .tpm_nvram_storedata = SWTPM_NVRAM_StoreData,
232 .tpm_nvram_deletename = SWTPM_NVRAM_DeleteName,
233 .tpm_io_getlocality = ptm_io_getlocality,
234 };
235
236 /* the current state the transfer interface is in */
237 static transfer_state tx_state;
238
239 /* function prototypes */
240 static void ptm_cleanup(void);
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 /*
392 * tpm_start: Start the TPM
393 *
394 * Check whether the TPM's state directory exists and if it does
395 * not exists, try to creat it. Start the thread pool, initilize
396 * libtpms and allocate a global TPM request buffer.
397 *
398 * @flags: libtpms init flags
399 */
400 static int tpm_start(uint32_t flags, TPMLIB_TPMVersion l_tpmversion)
401 {
402 DIR *dir;
403 const char *tpmdir = tpmstate_get_dir();
404
405 dir = opendir(tpmdir);
406 if (dir) {
407 closedir(dir);
408 } else {
409 if (mkdir(tpmdir, 0775)) {
410 logprintf(STDERR_FILENO,
411 "Error: Could not open tpmstate dir %s\n",
412 tpmdir);
413 return -1;
414 }
415 }
416
417 pool = g_thread_pool_new(worker_thread,
418 NULL,
419 1,
420 TRUE,
421 NULL);
422 if (!pool) {
423 logprintf(STDERR_FILENO,
424 "Error: Could not create the thread pool.\n");
425 return -1;
426 }
427
428 if(!ptm_request)
429 ptm_request = malloc(4096);
430 if(!ptm_request) {
431 logprintf(STDERR_FILENO,
432 "Error: Could not allocate memory for request buffer.\n");
433 goto error_del_pool;
434 }
435
436 if (tpmlib_start(flags, l_tpmversion) != TPM_SUCCESS)
437 goto error_del_pool;
438
439 logprintf(STDOUT_FILENO,
440 "CUSE TPM successfully initialized.\n");
441
442 return 0;
443
444 error_del_pool:
445 g_thread_pool_free(pool, TRUE, TRUE);
446 pool = NULL;
447
448 return -1;
449 }
450
451 /*
452 * ptm_write_fatal_error_response: Write fatal error response
453 *
454 * Write a fatal error response into the global ptm_response buffer.
455 */
456 static void ptm_write_fatal_error_response(TPMLIB_TPMVersion l_tpmversion)
457 {
458 tpmlib_write_fatal_error_response(&ptm_response,
459 &ptm_res_len,
460 &ptm_res_tot,
461 l_tpmversion);
462 }
463
464 /************************************ read() support ***************************/
465
466 /*
467 * ptm_read_result: Return the TPM response packet
468 *
469 * @req: the fuse_req_t
470 * @size: the max. number of bytes to return to the requester
471 */
472 static void ptm_read_result(fuse_req_t req, size_t size)
473 {
474 int len;
475
476 if (tpm_running) {
477 /* wait until results are ready */
478 worker_thread_wait_done();
479 }
480
481 len = ptm_res_len;
482
483 if (ptm_res_len > size) {
484 len = size;
485 ptm_res_len -= size;
486 } else {
487 ptm_res_len = 0;
488 }
489
490 fuse_reply_buf(req, (const char *)ptm_response, len);
491 }
492
493 /*
494 * ptm_read_stateblob: get a TPM stateblob via the read() interface
495 *
496 * @req: the fuse_req_t
497 * @size: the number of bytes to read
498 *
499 * The internal offset into the buffer is advanced by the number
500 * of bytes that were copied. We switch back to command read/write
501 * mode if an error occurred or once all bytes were read.
502 */
503 static void ptm_read_stateblob(fuse_req_t req, size_t size)
504 {
505 unsigned char *bufptr = NULL;
506 size_t numbytes;
507 size_t tocopy;
508
509 if (cached_stateblob_get(tx_state.offset, &bufptr, &numbytes) < 0) {
510 fuse_reply_err(req, EIO);
511 tx_state.state = TX_STATE_RW_COMMAND;
512 } else {
513 tocopy = MIN(size, numbytes);
514 tx_state.offset += tocopy;
515
516 fuse_reply_buf(req, (char *)bufptr, tocopy);
517 /* last transfer indicated by less bytes available than requested */
518 if (numbytes < size) {
519 tx_state.state = TX_STATE_RW_COMMAND;
520 }
521 }
522 }
523
524 /*
525 * ptm_read: interface to POSIX read()
526 *
527 * @req: fuse_req_t
528 * @size: number of bytes to read
529 * @off: offset (not used)
530 * @fi: fuse_file_info (not used)
531 *
532 * Depending on the current state of the transfer interface (read/write)
533 * return either the results of TPM commands or a data of a TPM state blob.
534 */
535 static void ptm_read(fuse_req_t req, size_t size, off_t off,
536 struct fuse_file_info *fi)
537 {
538 switch (tx_state.state) {
539 case TX_STATE_RW_COMMAND:
540 ptm_read_result(req, size);
541 break;
542 case TX_STATE_SET_STATE_BLOB:
543 fuse_reply_err(req, EIO);
544 tx_state.state = TX_STATE_RW_COMMAND;
545 break;
546 case TX_STATE_GET_STATE_BLOB:
547 ptm_read_stateblob(req, size);
548 break;
549 }
550 }
551
552 /*************************read/write stateblob support ***********************/
553
554 /*
555 * ptm_set_stateblob_append: Append a piece of TPM state blob and transfer to TPM
556 *
557 * blobtype: the type of blob
558 * data: the data to append
559 * length: length of the data
560 * is_encrypted: whether the blob is encrypted
561 * is_last: whether this is the last part of the TPM state blob; if it is, the TPM
562 * state blob will then be transferred to the TPM
563 */
564 static TPM_RESULT
565 ptm_set_stateblob_append(uint32_t blobtype,
566 const unsigned char *data, uint32_t length,
567 bool is_encrypted, bool is_last)
568 {
569 TPM_RESULT res = 0;
570 static struct stateblob stateblob;
571 unsigned char *tmp;
572
573 if (stateblob.type != blobtype) {
574 /* new blob; clear old data */
575 free(stateblob.data);
576 stateblob.data = NULL;
577 stateblob.length = 0;
578 stateblob.type = blobtype;
579 stateblob.is_encrypted = is_encrypted;
580
581 /*
582 * on the first call for a new state blob we allow 0 bytes to be written
583 * this allows the user to transfer via write()
584 */
585 if (length == 0)
586 return 0;
587 }
588
589 /* append */
590 tmp = realloc(stateblob.data, stateblob.length + length);
591 if (!tmp) {
592 logprintf(STDERR_FILENO,
593 "Could not allocate %u bytes.\n", stateblob.length + length);
594 /* error */
595 free(stateblob.data);
596 stateblob.data = NULL;
597 stateblob.length = 0;
598 stateblob.type = 0;
599
600 return TPM_FAIL;
601 } else
602 stateblob.data = tmp;
603
604 memcpy(&stateblob.data[stateblob.length], data, length);
605 stateblob.length += length;
606
607 if (!is_last) {
608 /* full packet -- expecting more data */
609 return res;
610 }
611
612 res = SWTPM_NVRAM_SetStateBlob(stateblob.data,
613 stateblob.length,
614 stateblob.is_encrypted,
615 0 /* tpm_number */,
616 blobtype);
617
618 logprintf(STDERR_FILENO,
619 "Deserialized state type %d (%s), length=%d, res=%d\n",
620 blobtype, tpmlib_get_blobname(blobtype),
621 stateblob.length, res);
622
623 free(stateblob.data);
624 stateblob.data = NULL;
625 stateblob.length = 0;
626 stateblob.type = 0;
627
628 /* transfer of blob is complete */
629 tx_state.state = TX_STATE_RW_COMMAND;
630
631 return res;
632 }
633
634 /*
635 * ptm_set_stateblob: set part of a TPM state blob
636 *
637 * @req: fuse_req_t
638 * pss: ptm_setstate provided via ioctl()
639 */
640 static void
641 ptm_set_stateblob(fuse_req_t req, ptm_setstate *pss)
642 {
643 TPM_RESULT res = 0;
644 TPM_BOOL is_encrypted =
645 ((pss->u.req.state_flags & PTM_STATE_FLAG_ENCRYPTED) != 0);
646 bool is_last = (sizeof(pss->u.req.data) != pss->u.req.length);
647
648 if (pss->u.req.length > sizeof(pss->u.req.data)) {
649 res = TPM_BAD_PARAMETER;
650 goto send_response;
651 }
652
653 /* transfer of blob initiated */
654 tx_state.state = TX_STATE_SET_STATE_BLOB;
655 tx_state.blobtype = pss->u.req.type;
656 tx_state.blob_is_encrypted = is_encrypted;
657 tx_state.offset = 0;
658
659 res = ptm_set_stateblob_append(pss->u.req.type,
660 pss->u.req.data,
661 pss->u.req.length,
662 is_encrypted,
663 is_last);
664
665 if (res)
666 tx_state.state = TX_STATE_RW_COMMAND;
667
668 send_response:
669 pss->u.resp.tpm_result = res;
670
671 fuse_reply_ioctl(req, 0, pss, sizeof(*pss));
672 }
673
674 /*
675 * ptm_get_stateblob_part: get part of a state blob
676 *
677 * @blobtype: the type of blob to get
678 * @buffer: the buffer this function will write the blob into
679 * @buffer_size: the size of the buffer
680 * @offset: the offset into the state blob
681 * @copied: pointer to int to indicate the number of bytes that were copied
682 * @is_encryped: returns whether the state blob is encrypted
683 */
684 static TPM_RESULT
685 ptm_get_stateblob_part(uint32_t blobtype,
686 unsigned char *buffer, size_t buffer_size,
687 uint32_t offset, uint32_t *copied,
688 TPM_BOOL decrypt, TPM_BOOL *is_encrypted)
689 {
690 TPM_RESULT res = 0;
691
692 if (!cached_stateblob_is_loaded(blobtype, decrypt)) {
693 res = cached_stateblob_load(blobtype, decrypt);
694 }
695
696 if (res == 0) {
697 cached_stateblob_copy(buffer, buffer_size,
698 offset, copied, is_encrypted);
699 }
700
701 return res;
702 }
703
704 /*
705 * ptm_get_stateblob: Get the state blob from the TPM using ioctl()
706 */
707 static void
708 ptm_get_stateblob(fuse_req_t req, ptm_getstate *pgs)
709 {
710 TPM_RESULT res = 0;
711 uint32_t blobtype = pgs->u.req.type;
712 TPM_BOOL decrypt =
713 ((pgs->u.req.state_flags & PTM_STATE_FLAG_DECRYPTED) != 0);
714 TPM_BOOL is_encrypted = FALSE;
715 uint32_t copied = 0;
716 uint32_t offset = pgs->u.req.offset;
717 uint32_t totlength;
718
719 res = ptm_get_stateblob_part(blobtype,
720 pgs->u.resp.data, sizeof(pgs->u.resp.data),
721 pgs->u.req.offset, &copied,
722 decrypt, &is_encrypted);
723
724 totlength = cached_stateblob_get_bloblength();
725
726 pgs->u.resp.state_flags = 0;
727 if (is_encrypted)
728 pgs->u.resp.state_flags |= PTM_STATE_FLAG_ENCRYPTED;
729
730 pgs->u.resp.length = copied;
731 pgs->u.resp.totlength = totlength;
732 pgs->u.resp.tpm_result = res;
733 logprintf(STDERR_FILENO,
734 "Serialized state type %d, length=%d, totlength=%d, res=%d\n",
735 blobtype, copied, totlength, res);
736
737 if (res == 0) {
738 if (offset + copied < totlength) {
739 /* last byte was not copied */
740 tx_state.state = TX_STATE_GET_STATE_BLOB;
741 tx_state.blobtype = pgs->u.req.type;
742 tx_state.blob_is_encrypted = is_encrypted;
743 tx_state.offset = copied;
744 } else {
745 /* last byte was copied */
746 tx_state.state = TX_STATE_RW_COMMAND;
747 }
748 } else {
749 /* error occurred */
750 tx_state.state = TX_STATE_RW_COMMAND;
751 }
752
753 fuse_reply_ioctl(req, 0, pgs, sizeof(pgs->u.resp));
754 }
755
756 /*********************************** write() support *************************/
757
758 /*
759 * ptm_write_stateblob: Write the state blob using the write() interface
760 *
761 * @req: the fuse_req_t
762 * @buf: the buffer with the data
763 * @size: the number of bytes in the buffer
764 *
765 * The data are appended to an existing buffer that was created with the
766 * initial ioctl().
767 */
768 static void ptm_write_stateblob(fuse_req_t req, const char *buf, size_t size)
769 {
770 TPM_RESULT res;
771
772 res = ptm_set_stateblob_append(tx_state.blobtype,
773 (unsigned char *)buf, size,
774 tx_state.blob_is_encrypted,
775 (size == 0));
776 if (res) {
777 tx_state.state = TX_STATE_RW_COMMAND;
778 fuse_reply_err(req, EIO);
779 } else {
780 fuse_reply_write(req, size);
781 }
782 }
783
784 /*
785 * ptm_write_cmd: User writing a TPM command
786 *
787 * req: fuse_req_t
788 * buf: the buffer containing the TPM command
789 * size: the size of the buffer
790 * tpmversion: the version of the TPM
791 */
792 static void ptm_write_cmd(fuse_req_t req, const char *buf, size_t size,
793 TPMLIB_TPMVersion l_tpmversion)
794 {
795 ptm_req_len = size;
796 ptm_res_len = 0;
797
798 /* prevent other threads from writing or doing ioctls */
799 g_mutex_lock(FILE_OPS_LOCK);
800
801 if (tpm_running) {
802 /* ensure that we only ever work on one TPM command */
803 if (worker_thread_is_busy()) {
804 fuse_reply_err(req, EBUSY);
805 goto cleanup;
806 }
807
808 if (ptm_req_len > TPM_REQ_MAX)
809 ptm_req_len = TPM_REQ_MAX;
810
811 /* process SetLocality command, if */
812 tpmlib_process(&ptm_response, &ptm_res_len, &ptm_res_tot,
813 (unsigned char *)buf, ptm_req_len,
814 locality_flags, &locality, tpmversion);
815 if (ptm_res_len)
816 goto skip_process;
817
818 if (tpmlib_is_request_cancelable(l_tpmversion,
819 (const unsigned char*)buf,
820 ptm_req_len)) {
821 /* have command processed by thread pool */
822 memcpy(ptm_request, buf, ptm_req_len);
823
824 msg.type = MESSAGE_TPM_CMD;
825
826 worker_thread_mark_busy();
827
828 g_thread_pool_push(pool, &msg, NULL);
829 } else {
830 /* direct processing */
831 TPMLIB_Process(&ptm_response, &ptm_res_len, &ptm_res_tot,
832 (unsigned char *)buf, ptm_req_len);
833 }
834 } else {
835 /* TPM not initialized; return error */
836 ptm_write_fatal_error_response(l_tpmversion);
837 }
838
839 skip_process:
840 fuse_reply_write(req, ptm_req_len);
841
842 cleanup:
843 g_mutex_unlock(FILE_OPS_LOCK);
844
845 return;
846 }
847
848 /*
849 * ptm_write: low-level write() interface; calls approriate function depending
850 * on what is being transferred using the write()
851 */
852 static void ptm_write(fuse_req_t req, const char *buf, size_t size,
853 off_t off, struct fuse_file_info *fi)
854 {
855 switch (tx_state.state) {
856 case TX_STATE_RW_COMMAND:
857 ptm_write_cmd(req, buf, size, tpmversion);
858 break;
859 case TX_STATE_GET_STATE_BLOB:
860 fuse_reply_err(req, EIO);
861 tx_state.state = TX_STATE_RW_COMMAND;
862 break;
863 case TX_STATE_SET_STATE_BLOB:
864 ptm_write_stateblob(req, buf, size);
865 break;
866 }
867 }
868
869 /*
870 * ptm_open: interface to POSIX open()
871 */
872 static void ptm_open(fuse_req_t req, struct fuse_file_info *fi)
873 {
874 tx_state.state = TX_STATE_RW_COMMAND;
875
876 fuse_reply_open(req, fi);
877 }
878
879 /*
880 * ptm_ioctl : ioctl execution
881 *
882 * req: the fuse_req_t used to send response with
883 * cmd: the ioctl request code
884 * arg: the pointer the application used for calling the ioctl (3rd param)
885 * fi:
886 * flags: some flags provided by fuse
887 * in_buf: the copy of the input buffer
888 * in_bufsz: size of the input buffer; provided by fuse and has size of
889 * needed buffer
890 * out_bufsz: size of the output buffer; provided by fuse and has size of
891 * needed buffer
892 */
893 static void ptm_ioctl(fuse_req_t req, int cmd, void *arg,
894 struct fuse_file_info *fi, unsigned flags,
895 const void *in_buf, size_t in_bufsz, size_t out_bufsz)
896 {
897 TPM_RESULT res = TPM_FAIL;
898 bool exit_prg = FALSE;
899 ptm_init *init_p;
900 TPM_MODIFIER_INDICATOR orig_locality;
901
902 /* some commands have to wait until the worker thread is done */
903 switch(cmd) {
904 case PTM_GET_CAPABILITY:
905 case PTM_SET_LOCALITY:
906 case PTM_CANCEL_TPM_CMD:
907 case PTM_GET_CONFIG:
908 case PTM_SET_BUFFERSIZE:
909 /* no need to wait */
910 break;
911 case PTM_INIT:
912 case PTM_SHUTDOWN:
913 case PTM_GET_TPMESTABLISHED:
914 case PTM_RESET_TPMESTABLISHED:
915 case PTM_HASH_START:
916 case PTM_HASH_DATA:
917 case PTM_HASH_END:
918 case PTM_STORE_VOLATILE:
919 case PTM_GET_STATEBLOB:
920 case PTM_SET_STATEBLOB:
921 if (tpm_running)
922 worker_thread_wait_done();
923 break;
924 }
925
926 /* prevent other threads from writing or doing ioctls */
927 g_mutex_lock(FILE_OPS_LOCK);
928
929 switch (cmd) {
930 case PTM_GET_CAPABILITY:
931 if (out_bufsz != sizeof(ptm_cap)) {
932 struct iovec iov = { arg, sizeof(uint8_t) };
933 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
934 } else {
935 ptm_cap ptm_caps;
936 switch (tpmversion) {
937 case TPMLIB_TPM_VERSION_2:
938 ptm_caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN
939 | PTM_CAP_GET_TPMESTABLISHED
940 | PTM_CAP_SET_LOCALITY
941 | PTM_CAP_HASHING
942 | PTM_CAP_CANCEL_TPM_CMD
943 | PTM_CAP_STORE_VOLATILE
944 | PTM_CAP_RESET_TPMESTABLISHED
945 | PTM_CAP_GET_STATEBLOB
946 | PTM_CAP_SET_STATEBLOB
947 | PTM_CAP_STOP
948 | PTM_CAP_GET_CONFIG
949 | PTM_CAP_SET_BUFFERSIZE;
950 break;
951 case TPMLIB_TPM_VERSION_1_2:
952 ptm_caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN
953 | PTM_CAP_GET_TPMESTABLISHED
954 | PTM_CAP_SET_LOCALITY
955 | PTM_CAP_HASHING
956 | PTM_CAP_CANCEL_TPM_CMD
957 | PTM_CAP_STORE_VOLATILE
958 | PTM_CAP_RESET_TPMESTABLISHED
959 | PTM_CAP_GET_STATEBLOB
960 | PTM_CAP_SET_STATEBLOB
961 | PTM_CAP_STOP
962 | PTM_CAP_GET_CONFIG
963 | PTM_CAP_SET_BUFFERSIZE;
964 break;
965 }
966 fuse_reply_ioctl(req, 0, &ptm_caps, sizeof(ptm_caps));
967 }
968 break;
969
970 case PTM_INIT:
971 if (in_bufsz != sizeof(ptm_init)) {
972 struct iovec iov = { arg, sizeof(uint8_t) };
973 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
974 } else {
975 init_p = (ptm_init *)in_buf;
976
977 worker_thread_end();
978
979 TPMLIB_Terminate();
980
981 tpm_running = false;
982 if (tpm_start(init_p->u.req.init_flags, tpmversion) < 0) {
983 res = TPM_FAIL;
984 logprintf(STDERR_FILENO,
985 "Error: Could not initialize the TPM.\n");
986 } else {
987 res = TPM_SUCCESS;
988 tpm_running = true;
989 }
990 init_p->u.resp.tpm_result = res;
991 fuse_reply_ioctl(req, 0, init_p, sizeof(*init_p));
992 }
993 break;
994
995 case PTM_STOP:
996 worker_thread_end();
997
998 res = TPM_SUCCESS;
999 TPMLIB_Terminate();
1000
1001 tpm_running = false;
1002
1003 free(ptm_response);
1004 ptm_response = NULL;
1005
1006 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1007
1008 break;
1009
1010 case PTM_SHUTDOWN:
1011 worker_thread_end();
1012
1013 res = TPM_SUCCESS;
1014 TPMLIB_Terminate();
1015
1016 free(ptm_response);
1017 ptm_response = NULL;
1018
1019 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1020 exit_prg = TRUE;
1021
1022 break;
1023
1024 case PTM_GET_TPMESTABLISHED:
1025 if (!tpm_running)
1026 goto error_not_running;
1027
1028 if (out_bufsz != sizeof(ptm_est)) {
1029 struct iovec iov = { arg, sizeof(uint8_t) };
1030 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1031 } else {
1032 ptm_est te;
1033 te.u.resp.tpm_result = TPM_IO_TpmEstablished_Get(&te.u.resp.bit);
1034 fuse_reply_ioctl(req, 0, &te, sizeof(te));
1035 }
1036 break;
1037
1038 case PTM_RESET_TPMESTABLISHED:
1039 if (!tpm_running)
1040 goto error_not_running;
1041
1042 if (in_bufsz != sizeof(ptm_reset_est)) {
1043 struct iovec iov = { arg, sizeof(uint32_t) };
1044 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1045 } else {
1046 ptm_reset_est *re = (ptm_reset_est *)in_buf;
1047 if (re->u.req.loc > 4) {
1048 res = TPM_BAD_LOCALITY;
1049 } else {
1050 /* set locality and reset flag in one command */
1051 orig_locality = locality;
1052 locality = re->u.req.loc;
1053
1054 res = TPM_IO_TpmEstablished_Reset();
1055
1056 locality = orig_locality;
1057 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1058 }
1059 }
1060 break;
1061
1062 case PTM_SET_LOCALITY:
1063 if (in_bufsz != sizeof(ptm_loc)) {
1064 struct iovec iov = { arg, sizeof(uint32_t) };
1065 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1066 } else {
1067 ptm_loc *l = (ptm_loc *)in_buf;
1068 if (l->u.req.loc > 4 ||
1069 (l->u.req.loc == 4 &&
1070 locality_flags & LOCALITY_FLAG_REJECT_LOCALITY_4)) {
1071 res = TPM_BAD_LOCALITY;
1072 } else {
1073 res = TPM_SUCCESS;
1074 locality = l->u.req.loc;
1075 }
1076 l->u.resp.tpm_result = res;
1077 fuse_reply_ioctl(req, 0, l, sizeof(*l));
1078 }
1079 break;
1080
1081 case PTM_HASH_START:
1082 if (!tpm_running)
1083 goto error_not_running;
1084
1085 res = TPM_IO_Hash_Start();
1086 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1087 break;
1088
1089 case PTM_HASH_DATA:
1090 if (!tpm_running)
1091 goto error_not_running;
1092
1093 if (in_bufsz != sizeof(ptm_hdata)) {
1094 struct iovec iov = { arg, sizeof(uint32_t) };
1095 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1096 } else {
1097 ptm_hdata *data = (ptm_hdata *)in_buf;
1098 if (data->u.req.length <= sizeof(data->u.req.data)) {
1099 res = TPM_IO_Hash_Data(data->u.req.data,
1100 data->u.req.length);
1101 } else {
1102 res = TPM_FAIL;
1103 }
1104 data->u.resp.tpm_result = res;
1105 fuse_reply_ioctl(req, 0, data, sizeof(*data));
1106 }
1107 break;
1108
1109 case PTM_HASH_END:
1110 if (!tpm_running)
1111 goto error_not_running;
1112
1113 res = TPM_IO_Hash_End();
1114 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1115 break;
1116
1117 case PTM_CANCEL_TPM_CMD:
1118 if (!tpm_running)
1119 goto error_not_running;
1120
1121 /* for cancellation to work, the TPM would have to
1122 * execute in another thread that polls on a cancel
1123 * flag
1124 */
1125 res = TPMLIB_CancelCommand();
1126 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1127 break;
1128
1129 case PTM_STORE_VOLATILE:
1130 if (!tpm_running)
1131 goto error_not_running;
1132
1133 res = SWTPM_NVRAM_Store_Volatile();
1134 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1135
1136 cached_stateblob_free();
1137 break;
1138
1139 case PTM_GET_STATEBLOB:
1140 if (!tpm_running)
1141 goto error_not_running;
1142
1143 if (in_bufsz != sizeof(ptm_getstate)) {
1144 struct iovec iov = { arg, sizeof(uint32_t) };
1145 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1146 } else {
1147 ptm_get_stateblob(req, (ptm_getstate *)in_buf);
1148 }
1149 break;
1150
1151 case PTM_SET_STATEBLOB:
1152 if (tpm_running)
1153 goto error_running;
1154
1155 /* tpm state dir must be set */
1156 SWTPM_NVRAM_Init();
1157
1158 if (in_bufsz != sizeof(ptm_setstate)) {
1159 struct iovec iov = { arg, sizeof(uint32_t) };
1160 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1161 } else {
1162 ptm_set_stateblob(req, (ptm_setstate *)in_buf);
1163 }
1164 break;
1165
1166 case PTM_GET_CONFIG:
1167 if (out_bufsz != sizeof(ptm_getconfig)) {
1168 struct iovec iov = { arg, sizeof(uint32_t) };
1169 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1170 } else {
1171 ptm_getconfig pgs;
1172 pgs.u.resp.tpm_result = 0;
1173 pgs.u.resp.flags = 0;
1174 if (SWTPM_NVRAM_Has_FileKey())
1175 pgs.u.resp.flags |= PTM_CONFIG_FLAG_FILE_KEY;
1176 if (SWTPM_NVRAM_Has_MigrationKey())
1177 pgs.u.resp.flags |= PTM_CONFIG_FLAG_MIGRATION_KEY;
1178 fuse_reply_ioctl(req, 0, &pgs, sizeof(pgs));
1179 }
1180 break;
1181
1182 case PTM_SET_BUFFERSIZE:
1183 if (out_bufsz != sizeof(ptm_setbuffersize)) {
1184 struct iovec iov = { arg, sizeof(uint32_t) };
1185 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1186 } else {
1187 ptm_setbuffersize *in_psbs = (ptm_setbuffersize *)in_buf;
1188 ptm_setbuffersize out_psbs;
1189 uint32_t buffersize, minsize, maxsize;
1190
1191 buffersize = in_psbs->u.req.buffersize;
1192
1193 if (buffersize > 0 && tpm_running)
1194 goto error_running;
1195
1196 buffersize = TPMLIB_SetBufferSize(buffersize,
1197 &minsize,
1198 &maxsize);
1199
1200 out_psbs.u.resp.tpm_result = TPM_SUCCESS;
1201 out_psbs.u.resp.buffersize = buffersize;
1202 out_psbs.u.resp.minsize = minsize;
1203 out_psbs.u.resp.maxsize = maxsize;
1204 fuse_reply_ioctl(req, 0, &out_psbs, sizeof(out_psbs));
1205 }
1206 break;
1207
1208 case PTM_GET_INFO:
1209 if (out_bufsz != sizeof(ptm_getinfo)) {
1210 struct iovec iov = { arg, sizeof(uint32_t) };
1211 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1212 } else {
1213 ptm_getinfo *in_pgi = (ptm_getinfo *)in_buf;
1214 ptm_getinfo out_pgi;
1215 char *info_data;
1216 uint32_t length, offset;
1217
1218 info_data = TPMLIB_GetInfo(in_pgi->u.req.flags);
1219 if (!info_data)
1220 goto error_memory;
1221
1222 offset = in_pgi->u.req.offset;
1223 if (offset >= strlen(info_data)) {
1224 free(info_data);
1225 goto error_bad_input;
1226 }
1227
1228 length = min(strlen(info_data) + 1 - offset,
1229 sizeof(out_pgi.u.resp.buffer));
1230
1231 out_pgi.u.resp.tpm_result = 0;
1232 out_pgi.u.resp.totlength = strlen(info_data) + 1;
1233 out_pgi.u.resp.length = length;
1234 /* client has to collect whole string in case buffer is too small */
1235 memcpy(out_pgi.u.resp.buffer, &info_data[offset], length);
1236 free(info_data);
1237
1238 fuse_reply_ioctl(req, 0, &out_pgi, sizeof(out_pgi));
1239 }
1240 break;
1241
1242 default:
1243 fuse_reply_err(req, EINVAL);
1244 }
1245
1246 cleanup:
1247 g_mutex_unlock(FILE_OPS_LOCK);
1248
1249 if (exit_prg) {
1250 logprintf(STDOUT_FILENO, "CUSE TPM is shutting down.\n");
1251 ptm_cleanup();
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 ptm_cleanup();
1285 exit(-13);
1286 }
1287
1288 if (param->runas) {
1289 ret = change_process_owner(param->runas);
1290 if (ret) {
1291 ptm_cleanup();
1292 exit(ret);
1293 }
1294 }
1295 }
1296
1297 static void ptm_cleanup(void)
1298 {
1299 pidfile_remove();
1300 log_global_free();
1301 tpmstate_global_free();
1302 }
1303
1304 static const struct cuse_lowlevel_ops clops = {
1305 .open = ptm_open,
1306 .read = ptm_read,
1307 .write = ptm_write,
1308 .ioctl = ptm_ioctl,
1309 .init_done = ptm_init_done,
1310 };
1311
1312 #ifndef HAVE_SWTPM_CUSE_MAIN
1313 int main(int argc, char **argv)
1314 {
1315 const char *prgname = argv[0];
1316 const char *iface = "";
1317 #else
1318 int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *iface)
1319 {
1320 #endif
1321 int opt, longindex = 0;
1322 static struct option longopts[] = {
1323 {"maj" , required_argument, 0, 'M'},
1324 {"min" , required_argument, 0, 'm'},
1325 {"name" , required_argument, 0, 'n'},
1326 {"runas" , required_argument, 0, 'r'},
1327 {"log" , required_argument, 0, 'l'},
1328 {"locality" , required_argument, 0, 'L'},
1329 {"key" , required_argument, 0, 'k'},
1330 {"migration-key" , required_argument, 0, 'K'},
1331 {"pid" , required_argument, 0, 'p'},
1332 {"tpmstate" , required_argument, 0, 's'},
1333 {"tpm2" , no_argument, 0, '2'},
1334 {"help" , no_argument, 0, 'h'},
1335 {"version" , no_argument, 0, 'v'},
1336 {NULL , 0 , 0, 0 },
1337 };
1338 struct cuse_info cinfo;
1339 struct cuse_param param;
1340 const char *devname = NULL;
1341 char *cinfo_argv[1] = { 0 };
1342 unsigned int num;
1343 struct passwd *passwd;
1344 const char *tpmdir;
1345 int n, tpmfd;
1346 char path[PATH_MAX];
1347 int ret = 0;
1348
1349 memset(&cinfo, 0, sizeof(cinfo));
1350 memset(&param, 0, sizeof(param));
1351
1352 log_set_prefix("swtpm: ");
1353
1354 tpmversion = TPMLIB_TPM_VERSION_1_2;
1355
1356 while (true) {
1357 opt = getopt_long(argc, argv, "M:m:n:r:hv", longopts, &longindex);
1358
1359 if (opt == -1)
1360 break;
1361
1362 switch (opt) {
1363 case 'M': /* major */
1364 if (sscanf(optarg, "%u", &num) != 1) {
1365 logprintf(STDERR_FILENO, "Could not parse major number\n");
1366 ret = -1;
1367 goto exit;
1368 }
1369 if (num > 65535) {
1370 logprintf(STDERR_FILENO,
1371 "Major number outside valid range [0 - 65535]\n");
1372 ret = -1;
1373 goto exit;
1374 }
1375 cinfo.dev_major = num;
1376 break;
1377 case 'm': /* minor */
1378 if (sscanf(optarg, "%u", &num) != 1) {
1379 logprintf(STDERR_FILENO, "Could not parse major number\n");
1380 ret = -1;
1381 goto exit;
1382 }
1383 if (num > 65535) {
1384 logprintf(STDERR_FILENO,
1385 "Major number outside valid range [0 - 65535]\n");
1386 ret = -1;
1387 goto exit;
1388 }
1389 cinfo.dev_minor = num;
1390 break;
1391 case 'n': /* name */
1392 if (!cinfo.dev_info_argc) {
1393 cinfo_argv[0] = calloc(1, strlen("DEVNAME=") + strlen(optarg) + 1);
1394 if (!cinfo_argv[0]) {
1395 logprintf(STDERR_FILENO, "Out of memory\n");
1396 ret = -1;
1397 goto exit;
1398 }
1399 devname = optarg;
1400
1401 strcpy(cinfo_argv[0], "DEVNAME=");
1402 strcat(cinfo_argv[0], optarg);
1403
1404 cinfo.dev_info_argc = 1;
1405 cinfo.dev_info_argv = (const char **)cinfo_argv;
1406 }
1407 break;
1408 case 'r': /* runas */
1409 param.runas = optarg;
1410 break;
1411 case 'l': /* log */
1412 param.logging = optarg;
1413 break;
1414 case 'k': /* key */
1415 param.keydata = optarg;
1416 break;
1417 case 'K': /* migration-key */
1418 param.migkeydata = optarg;
1419 break;
1420 case 'p': /* pid */
1421 param.piddata = optarg;
1422 break;
1423 case 's': /* tpmstate */
1424 param.tpmstatedata = optarg;
1425 break;
1426 case 'L':
1427 param.localitydata = optarg;
1428 break;
1429 case '2':
1430 tpmversion = TPMLIB_TPM_VERSION_2;
1431 break;
1432 case 'h': /* help */
1433 fprintf(stdout, usage, prgname, iface);
1434 goto exit;
1435 case 'v': /* version */
1436 fprintf(stdout, "TPM emulator CUSE interface version %d.%d.%d, "
1437 "Copyright (c) 2014-2015 IBM Corp.\n",
1438 SWTPM_VER_MAJOR,
1439 SWTPM_VER_MINOR,
1440 SWTPM_VER_MICRO);
1441 goto exit;
1442 }
1443 }
1444
1445 if (optind < argc) {
1446 logprintf(STDERR_FILENO,
1447 "Unknown parameter '%s'\n", argv[optind]);
1448 ret = EXIT_FAILURE;
1449 goto exit;
1450 }
1451
1452 /*
1453 * choose the TPM version early so that getting/setting
1454 * buffer size works.
1455 */
1456 if (TPMLIB_ChooseTPMVersion(tpmversion) != TPM_SUCCESS) {
1457 logprintf(STDERR_FILENO,
1458 "Error: Could not choose TPM version.\n");
1459 ret = EXIT_FAILURE;
1460 goto exit;
1461 }
1462
1463 SWTPM_NVRAM_Set_TPMVersion(tpmversion);
1464
1465 if (!cinfo.dev_info_argv) {
1466 logprintf(STDERR_FILENO, "Error: device name missing\n");
1467 ret = -2;
1468 goto exit;
1469 }
1470
1471 if (handle_log_options(param.logging) < 0 ||
1472 handle_key_options(param.keydata) < 0 ||
1473 handle_migration_key_options(param.migkeydata) < 0 ||
1474 handle_pid_options(param.piddata) < 0 ||
1475 handle_tpmstate_options(param.tpmstatedata) < 0 ||
1476 handle_locality_options(param.localitydata, &locality_flags) < 0) {
1477 ret = -3;
1478 goto exit;
1479 }
1480
1481 if (setuid(0)) {
1482 logprintf(STDERR_FILENO, "Error: Unable to setuid root. uid = %d, "
1483 "euid = %d, gid = %d\n", getuid(), geteuid(), getgid());
1484 ret = -4;
1485 goto exit;
1486 }
1487
1488 if (param.runas) {
1489 if (!(passwd = getpwnam(param.runas))) {
1490 logprintf(STDERR_FILENO, "User '%s' does not exist\n",
1491 param.runas);
1492 ret = -5;
1493 goto exit;
1494 }
1495 }
1496
1497 tpmdir = tpmstate_get_dir();
1498 if (tpmdir == NULL) {
1499 logprintf(STDERR_FILENO,
1500 "Error: No TPM state directory is defined; "
1501 "TPM_PATH is not set\n");
1502 ret = -1;
1503 goto exit;
1504 }
1505
1506 n = snprintf(path, sizeof(path), "/dev/%s", devname);
1507 if (n < 0) {
1508 logprintf(STDERR_FILENO,
1509 "Error: Could not create device file name\n");
1510 ret = -1;
1511 goto exit;
1512 }
1513 if (n >= (int)sizeof(path)) {
1514 logprintf(STDERR_FILENO,
1515 "Error: Buffer too small to create device file name\n");
1516 ret = -1;
1517 goto exit;
1518 }
1519
1520 tpmfd = open(path, O_RDWR);
1521 if (tpmfd >= 0) {
1522 close(tpmfd);
1523 logprintf(STDERR_FILENO,
1524 "Error: A device '%s' already exists.\n",
1525 path);
1526 ret = -1;
1527 goto exit;
1528 }
1529
1530 if (tpmlib_register_callbacks(&cbs) != TPM_SUCCESS) {
1531 ret = -1;
1532 goto exit;
1533 }
1534
1535 worker_thread_init();
1536
1537 #if GLIB_MINOR_VERSION >= 32
1538 g_mutex_init(FILE_OPS_LOCK);
1539 #else
1540 FILE_OPS_LOCK = g_mutex_new();
1541 #endif
1542
1543 ret = cuse_lowlevel_main(1, argv, &cinfo, &clops, &param);
1544
1545 exit:
1546 ptm_cleanup();
1547 free(cinfo_argv[0]);
1548
1549 return ret;
1550 }