]> git.proxmox.com Git - swtpm.git/blob - src/swtpm/cuse_tpm.c
Use TPMLIB_SetState to set state blobs
[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 TPM_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
608 if (stateblob.type != blobtype) {
609 /* new blob; clear old data */
610 TPM_Free(stateblob.data);
611 stateblob.data = NULL;
612 stateblob.length = 0;
613 stateblob.type = blobtype;
614 stateblob.is_encrypted = is_encrypted;
615
616 /*
617 * on the first call for a new state blob we allow 0 bytes to be written
618 * this allows the user to transfer via write()
619 */
620 if (length == 0)
621 return 0;
622 }
623
624 /* append */
625 res = TPM_Realloc(&stateblob.data, stateblob.length + length);
626 if (res != 0) {
627 /* error */
628 TPM_Free(stateblob.data);
629 stateblob.data = NULL;
630 stateblob.length = 0;
631 stateblob.type = 0;
632
633 return res;
634 }
635
636 memcpy(&stateblob.data[stateblob.length], data, length);
637 stateblob.length += length;
638
639 if (!is_last) {
640 /* full packet -- expecting more data */
641 return res;
642 }
643
644 res = SWTPM_NVRAM_SetStateBlob(stateblob.data,
645 stateblob.length,
646 stateblob.is_encrypted,
647 0 /* tpm_number */,
648 blobtype);
649
650 TPM_Free(stateblob.data);
651 stateblob.data = NULL;
652 stateblob.length = 0;
653 stateblob.type = 0;
654
655 /* transfer of blob is complete */
656 tx_state.state = TX_STATE_RW_COMMAND;
657
658 return res;
659 }
660
661 /*
662 * ptm_set_stateblob: set part of a TPM state blob
663 *
664 * @req: fuse_req_t
665 * pss: ptm_setstate provided via ioctl()
666 */
667 static void
668 ptm_set_stateblob(fuse_req_t req, ptm_setstate *pss)
669 {
670 TPM_RESULT res = 0;
671 TPM_BOOL is_encrypted =
672 ((pss->u.req.state_flags & PTM_STATE_FLAG_ENCRYPTED) != 0);
673 bool is_last = (sizeof(pss->u.req.data) != pss->u.req.length);
674
675 if (pss->u.req.length > sizeof(pss->u.req.data)) {
676 res = TPM_BAD_PARAMETER;
677 goto send_response;
678 }
679
680 /* transfer of blob initiated */
681 tx_state.state = TX_STATE_SET_STATE_BLOB;
682 tx_state.blobtype = pss->u.req.type;
683 tx_state.blob_is_encrypted = is_encrypted;
684 tx_state.offset = 0;
685
686 res = ptm_set_stateblob_append(pss->u.req.type,
687 pss->u.req.data,
688 pss->u.req.length,
689 is_encrypted,
690 is_last);
691
692 if (res)
693 tx_state.state = TX_STATE_RW_COMMAND;
694
695 send_response:
696 pss->u.resp.tpm_result = res;
697
698 fuse_reply_ioctl(req, 0, pss, sizeof(*pss));
699 }
700
701 /*
702 * ptm_get_stateblob_part: get part of a state blob
703 *
704 * @blobtype: the type of blob to get
705 * @buffer: the buffer this function will write the blob into
706 * @buffer_size: the size of the buffer
707 * @offset: the offset into the state blob
708 * @copied: pointer to int to indicate the number of bytes that were copied
709 * @is_encryped: returns whether the state blob is encrypted
710 */
711 static TPM_RESULT
712 ptm_get_stateblob_part(uint32_t blobtype,
713 unsigned char *buffer, size_t buffer_size,
714 uint32_t offset, uint32_t *copied,
715 TPM_BOOL decrypt, TPM_BOOL *is_encrypted)
716 {
717 TPM_RESULT res = 0;
718
719 if (!cached_stateblob_is_loaded(blobtype, decrypt)) {
720 res = cached_stateblob_load(blobtype, decrypt);
721 }
722
723 if (res == 0) {
724 cached_stateblob_copy(buffer, buffer_size,
725 offset, copied, is_encrypted);
726 }
727
728 return res;
729 }
730
731 /*
732 * ptm_get_stateblob: Get the state blob from the TPM using ioctl()
733 */
734 static void
735 ptm_get_stateblob(fuse_req_t req, ptm_getstate *pgs)
736 {
737 TPM_RESULT res = 0;
738 uint32_t blobtype = pgs->u.req.type;
739 TPM_BOOL decrypt =
740 ((pgs->u.req.state_flags & PTM_STATE_FLAG_DECRYPTED) != 0);
741 TPM_BOOL is_encrypted = FALSE;
742 uint32_t copied = 0;
743 uint32_t offset = pgs->u.req.offset;
744 uint32_t totlength;
745
746 res = ptm_get_stateblob_part(blobtype,
747 pgs->u.resp.data, sizeof(pgs->u.resp.data),
748 pgs->u.req.offset, &copied,
749 decrypt, &is_encrypted);
750
751 totlength = cached_stateblob_get_bloblength();
752
753 pgs->u.resp.state_flags = 0;
754 if (is_encrypted)
755 pgs->u.resp.state_flags |= PTM_STATE_FLAG_ENCRYPTED;
756
757 pgs->u.resp.length = copied;
758 pgs->u.resp.totlength = totlength;
759 pgs->u.resp.tpm_result = res;
760
761 if (res == 0) {
762 if (offset + copied < totlength) {
763 /* last byte was not copied */
764 tx_state.state = TX_STATE_GET_STATE_BLOB;
765 tx_state.blobtype = pgs->u.req.type;
766 tx_state.blob_is_encrypted = is_encrypted;
767 tx_state.offset = copied;
768 } else {
769 /* last byte was copied */
770 tx_state.state = TX_STATE_RW_COMMAND;
771 }
772 } else {
773 /* error occurred */
774 tx_state.state = TX_STATE_RW_COMMAND;
775 }
776
777 fuse_reply_ioctl(req, 0, pgs, sizeof(pgs->u.resp));
778 }
779
780 /*********************************** write() support *************************/
781
782 /*
783 * ptm_write_stateblob: Write the state blob using the write() interface
784 *
785 * @req: the fuse_req_t
786 * @buf: the buffer with the data
787 * @size: the number of bytes in the buffer
788 *
789 * The data are appended to an existing buffer that was created with the
790 * initial ioctl().
791 */
792 static void ptm_write_stateblob(fuse_req_t req, const char *buf, size_t size)
793 {
794 TPM_RESULT res;
795
796 res = ptm_set_stateblob_append(tx_state.blobtype,
797 (unsigned char *)buf, size,
798 tx_state.blob_is_encrypted,
799 (size == 0));
800 if (res) {
801 tx_state.state = TX_STATE_RW_COMMAND;
802 fuse_reply_err(req, EIO);
803 } else {
804 fuse_reply_write(req, size);
805 }
806 }
807
808 /*
809 * ptm_write_cmd: User writing a TPM command
810 *
811 * req: fuse_req_t
812 * buf: the buffer containing the TPM command
813 * size: the size of the buffer
814 */
815 static void ptm_write_cmd(fuse_req_t req, const char *buf, size_t size)
816 {
817 ptm_req_len = size;
818 ptm_res_len = 0;
819
820 /* prevent other threads from writing or doing ioctls */
821 g_mutex_lock(FILE_OPS_LOCK);
822
823 if (tpm_running) {
824 /* ensure that we only ever work on one TPM command */
825 if (worker_thread_is_busy()) {
826 fuse_reply_err(req, EBUSY);
827 goto cleanup;
828 }
829
830 if (ptm_req_len > TPM_REQ_MAX)
831 ptm_req_len = TPM_REQ_MAX;
832
833 /* process SetLocality command, if */
834 tpmlib_process(&ptm_response, &ptm_res_len, &ptm_res_tot,
835 (unsigned char *)buf, ptm_req_len,
836 locality_flags, &locality);
837 if (ptm_res_len)
838 goto skip_process;
839
840 if (tpmlib_is_request_cancelable(ptm_request, ptm_req_len)) {
841 /* have command processed by thread pool */
842 memcpy(ptm_request, buf, ptm_req_len);
843
844 msg.type = MESSAGE_TPM_CMD;
845
846 worker_thread_mark_busy();
847
848 g_thread_pool_push(pool, &msg, NULL);
849 } else {
850 /* direct processing */
851 TPMLIB_Process(&ptm_response, &ptm_res_len, &ptm_res_tot,
852 (unsigned char *)buf, ptm_req_len);
853 }
854 } else {
855 /* TPM not initialized; return error */
856 ptm_write_fatal_error_response();
857 }
858
859 skip_process:
860 fuse_reply_write(req, ptm_req_len);
861
862 cleanup:
863 g_mutex_unlock(FILE_OPS_LOCK);
864
865 return;
866 }
867
868 /*
869 * ptm_write: low-level write() interface; calls approriate function depending
870 * on what is being transferred using the write()
871 */
872 static void ptm_write(fuse_req_t req, const char *buf, size_t size,
873 off_t off, struct fuse_file_info *fi)
874 {
875 switch (tx_state.state) {
876 case TX_STATE_RW_COMMAND:
877 ptm_write_cmd(req, buf, size);
878 break;
879 case TX_STATE_GET_STATE_BLOB:
880 fuse_reply_err(req, EIO);
881 tx_state.state = TX_STATE_RW_COMMAND;
882 break;
883 case TX_STATE_SET_STATE_BLOB:
884 ptm_write_stateblob(req, buf, size);
885 break;
886 }
887 }
888
889 /*
890 * ptm_open: interface to POSIX open()
891 */
892 static void ptm_open(fuse_req_t req, struct fuse_file_info *fi)
893 {
894 tx_state.state = TX_STATE_RW_COMMAND;
895
896 fuse_reply_open(req, fi);
897 }
898
899 /*
900 * ptm_ioctl : ioctl execution
901 *
902 * req: the fuse_req_t used to send response with
903 * cmd: the ioctl request code
904 * arg: the pointer the application used for calling the ioctl (3rd param)
905 * fi:
906 * flags: some flags provided by fuse
907 * in_buf: the copy of the input buffer
908 * in_bufsz: size of the input buffer; provided by fuse and has size of
909 * needed buffer
910 * out_bufsz: size of the output buffer; provided by fuse and has size of
911 * needed buffer
912 */
913 static void ptm_ioctl(fuse_req_t req, int cmd, void *arg,
914 struct fuse_file_info *fi, unsigned flags,
915 const void *in_buf, size_t in_bufsz, size_t out_bufsz)
916 {
917 TPM_RESULT res = TPM_FAIL;
918 bool exit_prg = FALSE;
919 ptm_init *init_p;
920
921 /* some commands have to wait until the worker thread is done */
922 switch(cmd) {
923 case PTM_GET_CAPABILITY:
924 case PTM_SET_LOCALITY:
925 case PTM_CANCEL_TPM_CMD:
926 case PTM_GET_CONFIG:
927 case PTM_SET_BUFFERSIZE:
928 /* no need to wait */
929 break;
930 case PTM_INIT:
931 case PTM_SHUTDOWN:
932 case PTM_GET_TPMESTABLISHED:
933 case PTM_RESET_TPMESTABLISHED:
934 case PTM_HASH_START:
935 case PTM_HASH_DATA:
936 case PTM_HASH_END:
937 case PTM_STORE_VOLATILE:
938 case PTM_GET_STATEBLOB:
939 case PTM_SET_STATEBLOB:
940 if (tpm_running)
941 worker_thread_wait_done();
942 break;
943 }
944
945 /* prevent other threads from writing or doing ioctls */
946 g_mutex_lock(FILE_OPS_LOCK);
947
948 switch (cmd) {
949 case PTM_GET_CAPABILITY:
950 if (out_bufsz != sizeof(ptm_cap)) {
951 struct iovec iov = { arg, sizeof(uint8_t) };
952 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
953 } else {
954 ptm_cap ptm_caps;
955 ptm_caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN
956 | PTM_CAP_GET_TPMESTABLISHED
957 | PTM_CAP_SET_LOCALITY
958 | PTM_CAP_HASHING
959 | PTM_CAP_CANCEL_TPM_CMD
960 | PTM_CAP_STORE_VOLATILE
961 | PTM_CAP_RESET_TPMESTABLISHED
962 | PTM_CAP_GET_STATEBLOB
963 | PTM_CAP_SET_STATEBLOB
964 | PTM_CAP_STOP
965 | PTM_CAP_GET_CONFIG
966 | PTM_CAP_SET_BUFFERSIZE;
967 fuse_reply_ioctl(req, 0, &ptm_caps, sizeof(ptm_caps));
968 }
969 break;
970
971 case PTM_INIT:
972 if (in_bufsz != sizeof(ptm_init)) {
973 struct iovec iov = { arg, sizeof(uint8_t) };
974 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
975 } else {
976 init_p = (ptm_init *)in_buf;
977
978 worker_thread_end();
979
980 TPMLIB_Terminate();
981
982 tpm_running = false;
983 if (tpm_start(init_p->u.req.init_flags) < 0) {
984 res = TPM_FAIL;
985 logprintf(STDERR_FILENO,
986 "Error: Could not initialize the TPM.\n");
987 } else {
988 res = TPM_SUCCESS;
989 tpm_running = true;
990 }
991 init_p->u.resp.tpm_result = res;
992 fuse_reply_ioctl(req, 0, init_p, sizeof(*init_p));
993 }
994 break;
995
996 case PTM_STOP:
997 worker_thread_end();
998
999 res = TPM_SUCCESS;
1000 TPMLIB_Terminate();
1001
1002 tpm_running = false;
1003
1004 TPM_Free(ptm_response);
1005 ptm_response = NULL;
1006
1007 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1008
1009 break;
1010
1011 case PTM_SHUTDOWN:
1012 worker_thread_end();
1013
1014 res = TPM_SUCCESS;
1015 TPMLIB_Terminate();
1016
1017 TPM_Free(ptm_response);
1018 ptm_response = NULL;
1019
1020 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1021 exit_prg = TRUE;
1022
1023 break;
1024
1025 case PTM_GET_TPMESTABLISHED:
1026 if (!tpm_running)
1027 goto error_not_running;
1028
1029 if (out_bufsz != sizeof(ptm_est)) {
1030 struct iovec iov = { arg, sizeof(uint8_t) };
1031 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1032 } else {
1033 ptm_est te;
1034 te.u.resp.tpm_result = TPM_IO_TpmEstablished_Get(&te.u.resp.bit);
1035 fuse_reply_ioctl(req, 0, &te, sizeof(te));
1036 }
1037 break;
1038
1039 case PTM_RESET_TPMESTABLISHED:
1040 if (!tpm_running)
1041 goto error_not_running;
1042
1043 if (in_bufsz != sizeof(ptm_reset_est)) {
1044 struct iovec iov = { arg, sizeof(uint32_t) };
1045 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1046 } else {
1047 ptm_reset_est *re = (ptm_reset_est *)in_buf;
1048 if (re->u.req.loc > 4) {
1049 res = TPM_BAD_LOCALITY;
1050 } else {
1051 res = _TPM_IO_TpmEstablished_Reset(req, re->u.req.loc);
1052 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1053 }
1054 }
1055 break;
1056
1057 case PTM_SET_LOCALITY:
1058 if (in_bufsz != sizeof(ptm_loc)) {
1059 struct iovec iov = { arg, sizeof(uint32_t) };
1060 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1061 } else {
1062 ptm_loc *l = (ptm_loc *)in_buf;
1063 if (l->u.req.loc > 4 ||
1064 (l->u.req.loc == 4 &&
1065 locality_flags & LOCALITY_FLAG_REJECT_LOCALITY_4)) {
1066 res = TPM_BAD_LOCALITY;
1067 } else {
1068 res = TPM_SUCCESS;
1069 locality = l->u.req.loc;
1070 }
1071 l->u.resp.tpm_result = res;
1072 fuse_reply_ioctl(req, 0, l, sizeof(*l));
1073 }
1074 break;
1075
1076 case PTM_HASH_START:
1077 if (!tpm_running)
1078 goto error_not_running;
1079
1080 res = TPM_IO_Hash_Start();
1081 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1082 break;
1083
1084 case PTM_HASH_DATA:
1085 if (!tpm_running)
1086 goto error_not_running;
1087
1088 if (in_bufsz != sizeof(ptm_hdata)) {
1089 struct iovec iov = { arg, sizeof(uint32_t) };
1090 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1091 } else {
1092 ptm_hdata *data = (ptm_hdata *)in_buf;
1093 if (data->u.req.length <= sizeof(data->u.req.data)) {
1094 res = TPM_IO_Hash_Data(data->u.req.data,
1095 data->u.req.length);
1096 } else {
1097 res = TPM_FAIL;
1098 }
1099 data->u.resp.tpm_result = res;
1100 fuse_reply_ioctl(req, 0, data, sizeof(*data));
1101 }
1102 break;
1103
1104 case PTM_HASH_END:
1105 if (!tpm_running)
1106 goto error_not_running;
1107
1108 res = TPM_IO_Hash_End();
1109 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1110 break;
1111
1112 case PTM_CANCEL_TPM_CMD:
1113 if (!tpm_running)
1114 goto error_not_running;
1115
1116 /* for cancellation to work, the TPM would have to
1117 * execute in another thread that polls on a cancel
1118 * flag
1119 */
1120 res = TPM_FAIL;
1121 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1122 break;
1123
1124 case PTM_STORE_VOLATILE:
1125 if (!tpm_running)
1126 goto error_not_running;
1127
1128 res = SWTPM_NVRAM_Store_Volatile();
1129 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1130
1131 cached_stateblob_free();
1132 break;
1133
1134 case PTM_GET_STATEBLOB:
1135 if (!tpm_running)
1136 goto error_not_running;
1137
1138 if (in_bufsz != sizeof(ptm_getstate)) {
1139 struct iovec iov = { arg, sizeof(uint32_t) };
1140 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1141 } else {
1142 ptm_get_stateblob(req, (ptm_getstate *)in_buf);
1143 }
1144 break;
1145
1146 case PTM_SET_STATEBLOB:
1147 if (tpm_running)
1148 goto error_running;
1149
1150 /* tpm state dir must be set */
1151 SWTPM_NVRAM_Init();
1152
1153 if (in_bufsz != sizeof(ptm_setstate)) {
1154 struct iovec iov = { arg, sizeof(uint32_t) };
1155 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1156 } else {
1157 ptm_set_stateblob(req, (ptm_setstate *)in_buf);
1158 }
1159 break;
1160
1161 case PTM_GET_CONFIG:
1162 if (out_bufsz != sizeof(ptm_getconfig)) {
1163 struct iovec iov = { arg, sizeof(uint32_t) };
1164 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1165 } else {
1166 ptm_getconfig pgs;
1167 pgs.u.resp.tpm_result = 0;
1168 pgs.u.resp.flags = 0;
1169 if (SWTPM_NVRAM_Has_FileKey())
1170 pgs.u.resp.flags |= PTM_CONFIG_FLAG_FILE_KEY;
1171 if (SWTPM_NVRAM_Has_MigrationKey())
1172 pgs.u.resp.flags |= PTM_CONFIG_FLAG_MIGRATION_KEY;
1173 fuse_reply_ioctl(req, 0, &pgs, sizeof(pgs));
1174 }
1175 break;
1176
1177 case PTM_SET_BUFFERSIZE:
1178 if (out_bufsz != sizeof(ptm_setbuffersize)) {
1179 struct iovec iov = { arg, sizeof(uint32_t) };
1180 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1181 } else {
1182 ptm_setbuffersize *in_psbs = (ptm_setbuffersize *)in_buf;
1183 ptm_setbuffersize out_psbs;
1184 uint32_t buffersize, minsize, maxsize;
1185
1186 buffersize = in_psbs->u.req.buffersize;
1187
1188 if (buffersize > 0 && tpm_running)
1189 goto error_running;
1190
1191 buffersize = TPMLIB_SetBufferSize(buffersize,
1192 &minsize,
1193 &maxsize);
1194
1195 out_psbs.u.resp.tpm_result = TPM_SUCCESS;
1196 out_psbs.u.resp.buffersize = buffersize;
1197 out_psbs.u.resp.minsize = minsize;
1198 out_psbs.u.resp.maxsize = maxsize;
1199 fuse_reply_ioctl(req, 0, &out_psbs, sizeof(out_psbs));
1200 }
1201 break;
1202
1203 case PTM_GET_INFO:
1204 if (out_bufsz != sizeof(ptm_getinfo)) {
1205 struct iovec iov = { arg, sizeof(uint32_t) };
1206 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1207 } else {
1208 ptm_getinfo *in_pgi = (ptm_getinfo *)in_buf;
1209 ptm_getinfo out_pgi;
1210 char *info_data;
1211 uint32_t length, offset;
1212
1213 info_data = TPMLIB_GetInfo(in_pgi->u.req.flags);
1214 if (!info_data)
1215 goto error_memory;
1216
1217 offset = in_pgi->u.req.offset;
1218 if (offset >= strlen(info_data)) {
1219 free(info_data);
1220 goto error_bad_input;
1221 }
1222
1223 length = min(strlen(info_data) + 1 - offset,
1224 sizeof(out_pgi.u.resp.buffer));
1225
1226 out_pgi.u.resp.tpm_result = 0;
1227 out_pgi.u.resp.totlength = strlen(info_data) + 1;
1228 out_pgi.u.resp.length = length;
1229 strncpy(out_pgi.u.resp.buffer, &info_data[offset], length);
1230 free(info_data);
1231
1232 fuse_reply_ioctl(req, 0, &out_pgi, sizeof(out_pgi));
1233 }
1234 break;
1235
1236 default:
1237 fuse_reply_err(req, EINVAL);
1238 }
1239
1240 cleanup:
1241 g_mutex_unlock(FILE_OPS_LOCK);
1242
1243 if (exit_prg) {
1244 logprintf(STDOUT_FILENO, "CUSE TPM is shutting down.\n");
1245 pidfile_remove();
1246
1247 exit(0);
1248 }
1249
1250 return;
1251
1252 error_bad_input:
1253 res = TPM_BAD_PARAMETER;
1254 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1255
1256 goto cleanup;
1257
1258 error_running:
1259 error_not_running:
1260 res = TPM_BAD_ORDINAL;
1261 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1262
1263 goto cleanup;
1264
1265 error_memory:
1266 res = TPM_SIZE;
1267 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1268
1269 goto cleanup;
1270 }
1271
1272 static void ptm_init_done(void *userdata)
1273 {
1274 struct cuse_param *param = userdata;
1275 int ret;
1276
1277 /* at this point the entry in /dev/ is available */
1278 if (pidfile_write(getpid()) < 0) {
1279 exit(-13);
1280 }
1281
1282 if (param->runas) {
1283 ret = change_process_owner(param->runas);
1284 if (ret)
1285 exit(ret);
1286 }
1287 }
1288
1289 static const struct cuse_lowlevel_ops clops = {
1290 .open = ptm_open,
1291 .read = ptm_read,
1292 .write = ptm_write,
1293 .ioctl = ptm_ioctl,
1294 .init_done = ptm_init_done,
1295 };
1296
1297 #ifndef HAVE_SWTPM_CUSE_MAIN
1298 int main(int argc, char **argv)
1299 {
1300 const char *prgname = argv[0];
1301 const char *iface = "";
1302 #else
1303 int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *iface)
1304 {
1305 #endif
1306 int opt, longindex = 0;
1307 static struct option longopts[] = {
1308 {"maj" , required_argument, 0, 'M'},
1309 {"min" , required_argument, 0, 'm'},
1310 {"name" , required_argument, 0, 'n'},
1311 {"runas" , required_argument, 0, 'r'},
1312 {"log" , required_argument, 0, 'l'},
1313 {"locality" , required_argument, 0, 'L'},
1314 {"key" , required_argument, 0, 'k'},
1315 {"migration-key" , required_argument, 0, 'K'},
1316 {"pid" , required_argument, 0, 'p'},
1317 {"tpmstate" , required_argument, 0, 's'},
1318 {"help" , no_argument, 0, 'h'},
1319 {"version" , no_argument, 0, 'v'},
1320 {NULL , 0 , 0, 0 },
1321 };
1322 struct cuse_info cinfo;
1323 struct cuse_param param;
1324 const char *devname = NULL;
1325 char *cinfo_argv[1];
1326 unsigned int num;
1327 struct passwd *passwd;
1328 const char *tpmdir;
1329 int n, tpmfd;
1330 char path[PATH_MAX];
1331
1332 memset(&cinfo, 0, sizeof(cinfo));
1333 memset(&param, 0, sizeof(param));
1334
1335 log_set_prefix("swtpm: ");
1336
1337 while (true) {
1338 opt = getopt_long(argc, argv, "M:m:n:r:hv", longopts, &longindex);
1339
1340 if (opt == -1)
1341 break;
1342
1343 switch (opt) {
1344 case 'M': /* major */
1345 if (sscanf(optarg, "%u", &num) != 1) {
1346 logprintf(STDERR_FILENO, "Could not parse major number\n");
1347 return -1;
1348 }
1349 if (num > 65535) {
1350 logprintf(STDERR_FILENO,
1351 "Major number outside valid range [0 - 65535]\n");
1352 return -1;
1353 }
1354 cinfo.dev_major = num;
1355 break;
1356 case 'm': /* minor */
1357 if (sscanf(optarg, "%u", &num) != 1) {
1358 logprintf(STDERR_FILENO, "Could not parse major number\n");
1359 return -1;
1360 }
1361 if (num > 65535) {
1362 logprintf(STDERR_FILENO,
1363 "Major number outside valid range [0 - 65535]\n");
1364 return -1;
1365 }
1366 cinfo.dev_minor = num;
1367 break;
1368 case 'n': /* name */
1369 if (!cinfo.dev_info_argc) {
1370 cinfo_argv[0] = calloc(1, strlen("DEVNAME=") + strlen(optarg) + 1);
1371 if (!cinfo_argv[0]) {
1372 logprintf(STDERR_FILENO, "Out of memory\n");
1373 return -1;
1374 }
1375 devname = optarg;
1376
1377 strcpy(cinfo_argv[0], "DEVNAME=");
1378 strcat(cinfo_argv[0], optarg);
1379
1380 cinfo.dev_info_argc = 1;
1381 cinfo.dev_info_argv = (const char **)cinfo_argv;
1382 }
1383 break;
1384 case 'r': /* runas */
1385 param.runas = optarg;
1386 break;
1387 case 'l': /* log */
1388 param.logging = optarg;
1389 break;
1390 case 'k': /* key */
1391 param.keydata = optarg;
1392 break;
1393 case 'K': /* migration-key */
1394 param.migkeydata = optarg;
1395 break;
1396 case 'p': /* pid */
1397 param.piddata = optarg;
1398 break;
1399 case 's': /* tpmstate */
1400 param.tpmstatedata = optarg;
1401 break;
1402 case 'L':
1403 param.localitydata = optarg;
1404 break;
1405 case 'h': /* help */
1406 fprintf(stdout, usage, prgname, iface);
1407 return 0;
1408 case 'v': /* version */
1409 fprintf(stdout, "TPM emulator CUSE interface version %d.%d.%d, "
1410 "Copyright (c) 2014-2015 IBM Corp.\n",
1411 SWTPM_VER_MAJOR,
1412 SWTPM_VER_MINOR,
1413 SWTPM_VER_MICRO);
1414 return 0;
1415 }
1416 }
1417
1418 if (optind < argc) {
1419 logprintf(STDERR_FILENO,
1420 "Unknown parameter '%s'\n", argv[optind]);
1421 return EXIT_FAILURE;
1422 }
1423
1424 if (!cinfo.dev_info_argv) {
1425 logprintf(STDERR_FILENO, "Error: device name missing\n");
1426 return -2;
1427 }
1428
1429 if (handle_log_options(param.logging) < 0 ||
1430 handle_key_options(param.keydata) < 0 ||
1431 handle_migration_key_options(param.migkeydata) < 0 ||
1432 handle_pid_options(param.piddata) < 0 ||
1433 handle_tpmstate_options(param.tpmstatedata) < 0 ||
1434 handle_locality_options(param.localitydata, &locality_flags) < 0)
1435 return -3;
1436
1437 if (setuid(0)) {
1438 logprintf(STDERR_FILENO, "Error: Unable to setuid root. uid = %d, "
1439 "euid = %d, gid = %d\n", getuid(), geteuid(), getgid());
1440 return -4;
1441 }
1442
1443 if (param.runas) {
1444 if (!(passwd = getpwnam(param.runas))) {
1445 logprintf(STDERR_FILENO, "User '%s' does not exist\n",
1446 param.runas);
1447 return -5;
1448 }
1449 }
1450
1451 tpmdir = tpmstate_get_dir();
1452 if (tpmdir == NULL) {
1453 logprintf(STDERR_FILENO,
1454 "Error: No TPM state directory is defined; "
1455 "TPM_PATH is not set\n");
1456 return -1;
1457 }
1458
1459 n = snprintf(path, sizeof(path), "/dev/%s", devname);
1460 if (n < 0) {
1461 logprintf(STDERR_FILENO,
1462 "Error: Could not create device file name\n");
1463 return -1;
1464 }
1465 if (n >= (int)sizeof(path)) {
1466 logprintf(STDERR_FILENO,
1467 "Error: Buffer too small to create device file name\n");
1468 return -1;
1469 }
1470
1471 tpmfd = open(path, O_RDWR);
1472 if (tpmfd >= 0) {
1473 close(tpmfd);
1474 logprintf(STDERR_FILENO,
1475 "Error: A device '%s' already exists.\n",
1476 path);
1477 return -1;
1478 }
1479
1480 if (tpmlib_register_callbacks(&cbs) != TPM_SUCCESS)
1481 return -1;
1482
1483 worker_thread_init();
1484
1485 #if GLIB_MINOR_VERSION >= 32
1486 g_mutex_init(FILE_OPS_LOCK);
1487 #else
1488 FILE_OPS_LOCK = g_mutex_new();
1489 #endif
1490
1491 return cuse_lowlevel_main(1, argv, &cinfo, &clops, &param);
1492 }