]> git.proxmox.com Git - swtpm.git/blob - src/swtpm/cuse_tpm.c
swtpm: Remove unnecessary #include <seccomp.h> (fixes SuSE build)
[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 #include "seccomp_profile.h"
79 #include "options.h"
80 #include "capabilities.h"
81
82 /* maximum size of request buffer */
83 #define TPM_REQ_MAX 4096
84
85 /* version of the TPM (1.2 or 2) */
86 static TPMLIB_TPMVersion tpmversion;
87
88 /* buffer containing the TPM request */
89 static unsigned char *ptm_request;
90
91 /* buffer containing the TPM response */
92 static unsigned char *ptm_response;
93
94 /* the sizes of the data in the buffers */
95 static uint32_t ptm_req_len, ptm_res_len, ptm_res_tot;
96
97 /* locality applied to TPM commands */
98 static TPM_MODIFIER_INDICATOR locality;
99
100 /* whether the TPM is running (TPM_Init was received) */
101 static bool tpm_running;
102
103 /* flags on how to handle locality */
104 static uint32_t locality_flags;
105
106 /* the fuse_session that we will signal an exit to to exit the prg. */
107 static struct fuse_session *ptm_fuse_session;
108
109 #if GLIB_MAJOR_VERSION >= 2
110 # if GLIB_MINOR_VERSION >= 32
111
112 GMutex file_ops_lock;
113 # define FILE_OPS_LOCK &file_ops_lock
114
115 # else
116
117 GMutex *file_ops_lock;
118 # define FILE_OPS_LOCK file_ops_lock
119
120 # endif
121 #else
122
123 #error Unsupport glib version
124
125 #endif
126
127 struct cuse_param {
128 char *runas;
129 char *logging;
130 char *keydata;
131 char *migkeydata;
132 char *piddata;
133 char *tpmstatedata;
134 char *localitydata;
135 char *seccompdata;
136 unsigned int seccomp_action;
137 };
138
139 /* single message to send to the worker thread */
140 static struct thread_message msg;
141
142 struct stateblob {
143 uint8_t type;
144 uint8_t *data;
145 uint32_t length;
146 TPM_BOOL is_encrypted;
147 };
148
149 typedef struct stateblob_desc {
150 uint32_t blobtype;
151 TPM_BOOL decrypt;
152 TPM_BOOL is_encrypted;
153 unsigned char *data;
154 uint32_t data_length;
155 } stateblob_desc;
156
157 typedef enum tx_state_type {
158 TX_STATE_RW_COMMAND = 1,
159 TX_STATE_SET_STATE_BLOB = 2,
160 TX_STATE_GET_STATE_BLOB = 3,
161 } tx_state_type;
162
163 typedef struct transfer_state {
164 tx_state_type state;
165 /* while in TX_STATE_GET/SET_STATEBLOB */
166 uint32_t blobtype;
167 TPM_BOOL blob_is_encrypted;
168 /* while in TX_STATE_GET */
169 uint32_t offset;
170 } transfer_state;
171
172 typedef struct TPM_Response_Header {
173 uint16_t tag;
174 uint32_t paramSize;
175 uint32_t returnCode;
176 } __attribute__ ((packed)) TPM_Response_Header;
177
178 /*********************************** data *************************************/
179
180 static const char *usage =
181 "usage: %s %s [options]\n"
182 "\n"
183 "The following options are supported:\n"
184 "\n"
185 "-n NAME|--name=NAME : device name (mandatory)\n"
186 "-M MAJ|--maj=MAJ : device major number\n"
187 "-m MIN|--min=MIN : device minor number\n"
188 "--key file=<path>|fd=<fd>[,mode=aes-cbc|aes-256-cbc][,format=hex|binary][,remove=[true|false]]\n"
189 " : use an AES key for the encryption of the TPM's state\n"
190 " files; use the given mode for the block encryption;\n"
191 " the key is to be provided as a hex string or in binary\n"
192 " format; the keyfile can be automatically removed using\n"
193 " the remove parameter\n"
194 "--key pwdfile=<path>|pwdfd=<fd>[,mode=aes-cbc|aes-256-cbc][,remove=[true|false]][,kdf=sha512|pbkdf2]\n"
195 " : provide a passphrase in a file; the AES key will be\n"
196 " derived from this passphrase; default kdf is PBKDF2\n"
197 "--locality [reject-locality-4][,allow-set-locality]\n"
198 " : reject-locality-4: reject any command in locality 4\n"
199 " allow-set-locality: accept SetLocality command\n"
200 "--migration-key file=<path>|fd=<fd>[,mode=aes-cbc|aes-256-cbc][,format=hex|binary][,remove=[true|false]]\n"
201 " : use an AES key for the encryption of the TPM's state\n"
202 " when it is retrieved from the TPM via ioctls;\n"
203 " Setting this key ensures that the TPM's state will always\n"
204 " be encrypted when migrated\n"
205 "--migration-key pwdfile=<path>|pwdfd=<fd>[,mode=aes-cbc|aes-256-cbc][,remove=[true|false]][,kdf=sha512|pbkdf2]\n"
206 " : provide a passphrase in a file; the AES key will be\n"
207 " derived from this passphrase; default kdf is PBKDF2\n"
208 "--log file=<path>|fd=<filedescriptor>[,level=n][,prefix=<prefix>][,truncate]\n"
209 " : write the TPM's log into the given file rather than\n"
210 " to the console; provide '-' for path to avoid logging\n"
211 " log level 5 and higher will enable libtpms logging;\n"
212 " all logged output will be prefixed with prefix;\n"
213 " the log file can be reset (truncate)\n"
214 "--pid file=<path>|fd=<filedescriptor>\n"
215 " : write the process ID into the given file\n"
216 "--tpmstate dir=<dir>[,mode=0...]\n"
217 " : set the directory where the TPM's state will be written\n"
218 " into; the TPM_PATH environment variable can be used\n"
219 " instead;\n"
220 " mode allows to set the file mode bits of the state\n"
221 " files; the default mode is 0640;\n"
222 "-r|--runas <user> : after creating the CUSE device, change to the given\n"
223 " user\n"
224 "--tpm2 : choose TPM2 functionality\n"
225 #ifdef WITH_SECCOMP
226 # ifndef SCMP_ACT_LOG
227 "--seccomp action=none|kill\n"
228 # else
229 "--seccomp action=none|kill|log\n"
230 # endif
231 " : Choose the action of the seccomp profile when a\n"
232 " blacklisted syscall is executed; default is kill\n"
233 #endif
234 "--print-capabilites : print capabilities and terminate\n"
235 "-h|--help : display this help screen and terminate\n"
236 "\n";
237
238 static TPM_RESULT
239 ptm_io_getlocality(TPM_MODIFIER_INDICATOR *loc, uint32_t tpmnum)
240 {
241 *loc = locality;
242 return TPM_SUCCESS;
243 }
244
245 static struct libtpms_callbacks cbs = {
246 .sizeOfStruct = sizeof(struct libtpms_callbacks),
247 .tpm_nvram_init = SWTPM_NVRAM_Init,
248 .tpm_nvram_loaddata = SWTPM_NVRAM_LoadData,
249 .tpm_nvram_storedata = SWTPM_NVRAM_StoreData,
250 .tpm_nvram_deletename = SWTPM_NVRAM_DeleteName,
251 .tpm_io_getlocality = ptm_io_getlocality,
252 };
253
254 /* the current state the transfer interface is in */
255 static transfer_state tx_state;
256
257 /* function prototypes */
258 static void ptm_cleanup(void);
259
260 /************************* cached stateblob *********************************/
261
262 static stateblob_desc cached_stateblob;
263
264 /*
265 * cached_stateblob_is_loaded: is the stateblob with the given properties
266 * the one in the cache?
267 */
268 static bool cached_stateblob_is_loaded(uint32_t blobtype,
269 TPM_BOOL decrypt)
270 {
271 return (cached_stateblob.data != NULL) &&
272 (cached_stateblob.blobtype == blobtype) &&
273 (cached_stateblob.decrypt == decrypt);
274 }
275
276 /*
277 * cached_stateblob_free: Free any previously loaded state blob
278 */
279 static void cached_stateblob_free(void)
280 {
281 free(cached_stateblob.data);
282 cached_stateblob.data = NULL;
283 cached_stateblob.data_length = 0;
284 }
285
286 /*
287 * cached_stateblob_get_bloblength: get the total length of the cached blob
288 */
289 static uint32_t cached_stateblob_get_bloblength(void)
290 {
291 return cached_stateblob.data_length;
292 }
293
294 /*
295 * cached_statblob_get: get stateblob data without copying them
296 *
297 * @offset: at which offset to get the data
298 * @bufptr: pointer to a buffer pointer used to return buffer start
299 * @length: pointer used to return number of available bytes in returned buffer
300 */
301 static int cached_stateblob_get(uint32_t offset,
302 unsigned char **bufptr, size_t *length)
303 {
304 if (cached_stateblob.data == NULL ||
305 offset > cached_stateblob.data_length)
306 return -1;
307
308 *bufptr = &cached_stateblob.data[offset];
309 *length = cached_stateblob.data_length - offset;
310
311 return 0;
312 }
313
314 /*
315 * cached_stateblob_load: load a state blob into the cache
316 *
317 * blobtype: the type of blob
318 * decrypt: whether the blob is to be decrypted
319 */
320 static TPM_RESULT cached_stateblob_load(uint32_t blobtype, TPM_BOOL decrypt)
321 {
322 TPM_RESULT res = 0;
323 const char *blobname = tpmlib_get_blobname(blobtype);
324 uint32_t tpm_number = 0;
325
326 if (!blobname)
327 return TPM_BAD_PARAMETER;
328
329 cached_stateblob_free();
330
331 if (blobtype == PTM_BLOB_TYPE_VOLATILE)
332 res = SWTPM_NVRAM_Store_Volatile();
333
334 if (res == 0)
335 res = SWTPM_NVRAM_GetStateBlob(&cached_stateblob.data,
336 &cached_stateblob.data_length,
337 tpm_number, blobname, decrypt,
338 &cached_stateblob.is_encrypted);
339
340 /* make sure the volatile state file is gone */
341 if (blobtype == PTM_BLOB_TYPE_VOLATILE)
342 SWTPM_NVRAM_DeleteName(tpm_number, blobname, FALSE);
343
344 if (res == 0) {
345 cached_stateblob.blobtype = blobtype;
346 cached_stateblob.decrypt = decrypt;
347 }
348
349 return res;
350 }
351
352 /*
353 * cached_state_blob_copy: copy the cached state blob to a destination buffer
354 *
355 * dest: destination buffer
356 * destlen: size of the buffer
357 * srcoffset: offset to copy from
358 * copied: variable to return the number of copied bytes
359 * is_encrypted: variable to return whether the blob is encrypted
360 */
361 static int cached_stateblob_copy(void *dest, size_t destlen,
362 uint32_t srcoffset, uint32_t *copied,
363 TPM_BOOL *is_encrypted)
364 {
365 int ret = -1;
366
367 *copied = 0;
368
369 if (cached_stateblob.data != NULL && cached_stateblob.data_length > 0) {
370
371 if (srcoffset < cached_stateblob.data_length) {
372 *copied = min(cached_stateblob.data_length - srcoffset, destlen);
373
374 memcpy(dest, &cached_stateblob.data[srcoffset], *copied);
375
376 *is_encrypted = cached_stateblob.is_encrypted;
377 }
378
379 ret = 0;
380 }
381
382 return ret;
383 }
384
385 /************************* worker thread ************************************/
386
387 /*
388 * worker_thread: the worker thread
389 */
390 static void worker_thread(gpointer data, gpointer user_data)
391 {
392 struct thread_message *msg = (struct thread_message *)data;
393
394 switch (msg->type) {
395 case MESSAGE_TPM_CMD:
396 TPMLIB_Process(&ptm_response, &ptm_res_len, &ptm_res_tot,
397 ptm_request, ptm_req_len);
398 break;
399 case MESSAGE_IOCTL:
400 break;
401 }
402
403 /* results are ready */
404 worker_thread_mark_done();
405 }
406
407 /***************************** utility functions ****************************/
408
409 /*
410 * tpm_start: Start the TPM
411 *
412 * Check whether the TPM's state directory exists and if it does
413 * not exists, try to creat it. Start the thread pool, initilize
414 * libtpms and allocate a global TPM request buffer.
415 *
416 * @flags: libtpms init flags
417 * @l_tpmversion: the version of the TPM
418 * @res: the result from starting the TPM
419 */
420 static int tpm_start(uint32_t flags, TPMLIB_TPMVersion l_tpmversion,
421 TPM_RESULT *res)
422 {
423 DIR *dir;
424 const char *tpmdir = tpmstate_get_dir();
425
426 *res = TPM_FAIL;
427
428 dir = opendir(tpmdir);
429 if (dir) {
430 closedir(dir);
431 } else {
432 if (mkdir(tpmdir, 0775)) {
433 logprintf(STDERR_FILENO,
434 "Error: Could not open tpmstate dir %s\n",
435 tpmdir);
436 return -1;
437 }
438 }
439
440 pool = g_thread_pool_new(worker_thread,
441 NULL,
442 1,
443 FALSE,
444 NULL);
445 if (!pool) {
446 logprintf(STDERR_FILENO,
447 "Error: Could not create the thread pool.\n");
448 return -1;
449 }
450
451 if(!ptm_request)
452 ptm_request = malloc(4096);
453 if(!ptm_request) {
454 logprintf(STDERR_FILENO,
455 "Error: Could not allocate memory for request buffer.\n");
456 goto error_del_pool;
457 }
458
459 *res = tpmlib_start(flags, l_tpmversion);
460 if (*res != TPM_SUCCESS)
461 goto error_del_pool;
462
463 logprintf(STDOUT_FILENO,
464 "CUSE TPM successfully initialized.\n");
465
466 return 0;
467
468 error_del_pool:
469 g_thread_pool_free(pool, TRUE, TRUE);
470 pool = NULL;
471
472 return -1;
473 }
474
475 /*
476 * ptm_write_fatal_error_response: Write fatal error response
477 *
478 * Write a fatal error response into the global ptm_response buffer.
479 */
480 static void ptm_write_fatal_error_response(TPMLIB_TPMVersion l_tpmversion)
481 {
482 tpmlib_write_fatal_error_response(&ptm_response,
483 &ptm_res_len,
484 &ptm_res_tot,
485 l_tpmversion);
486 }
487
488 /************************************ read() support ***************************/
489
490 /*
491 * ptm_read_result: Return the TPM response packet
492 *
493 * @req: the fuse_req_t
494 * @size: the max. number of bytes to return to the requester
495 */
496 static void ptm_read_result(fuse_req_t req, size_t size)
497 {
498 int len;
499
500 if (tpm_running) {
501 /* wait until results are ready */
502 worker_thread_wait_done();
503 }
504
505 len = ptm_res_len;
506
507 if (ptm_res_len > size) {
508 len = size;
509 ptm_res_len -= size;
510 } else {
511 ptm_res_len = 0;
512 }
513
514 fuse_reply_buf(req, (const char *)ptm_response, len);
515 }
516
517 /*
518 * ptm_read_stateblob: get a TPM stateblob via the read() interface
519 *
520 * @req: the fuse_req_t
521 * @size: the number of bytes to read
522 *
523 * The internal offset into the buffer is advanced by the number
524 * of bytes that were copied. We switch back to command read/write
525 * mode if an error occurred or once all bytes were read.
526 */
527 static void ptm_read_stateblob(fuse_req_t req, size_t size)
528 {
529 unsigned char *bufptr = NULL;
530 size_t numbytes;
531 size_t tocopy;
532
533 if (cached_stateblob_get(tx_state.offset, &bufptr, &numbytes) < 0) {
534 fuse_reply_err(req, EIO);
535 tx_state.state = TX_STATE_RW_COMMAND;
536 } else {
537 tocopy = MIN(size, numbytes);
538 tx_state.offset += tocopy;
539
540 fuse_reply_buf(req, (char *)bufptr, tocopy);
541 /* last transfer indicated by less bytes available than requested */
542 if (numbytes < size) {
543 tx_state.state = TX_STATE_RW_COMMAND;
544 }
545 }
546 }
547
548 /*
549 * ptm_read: interface to POSIX read()
550 *
551 * @req: fuse_req_t
552 * @size: number of bytes to read
553 * @off: offset (not used)
554 * @fi: fuse_file_info (not used)
555 *
556 * Depending on the current state of the transfer interface (read/write)
557 * return either the results of TPM commands or a data of a TPM state blob.
558 */
559 static void ptm_read(fuse_req_t req, size_t size, off_t off,
560 struct fuse_file_info *fi)
561 {
562 switch (tx_state.state) {
563 case TX_STATE_RW_COMMAND:
564 ptm_read_result(req, size);
565 break;
566 case TX_STATE_SET_STATE_BLOB:
567 fuse_reply_err(req, EIO);
568 tx_state.state = TX_STATE_RW_COMMAND;
569 break;
570 case TX_STATE_GET_STATE_BLOB:
571 ptm_read_stateblob(req, size);
572 break;
573 }
574 }
575
576 /*************************read/write stateblob support ***********************/
577
578 /*
579 * ptm_set_stateblob_append: Append a piece of TPM state blob and transfer to TPM
580 *
581 * blobtype: the type of blob
582 * data: the data to append
583 * length: length of the data
584 * is_encrypted: whether the blob is encrypted
585 * is_last: whether this is the last part of the TPM state blob; if it is, the TPM
586 * state blob will then be transferred to the TPM
587 */
588 static TPM_RESULT
589 ptm_set_stateblob_append(uint32_t blobtype,
590 const unsigned char *data, uint32_t length,
591 bool is_encrypted, bool is_last)
592 {
593 TPM_RESULT res = 0;
594 static struct stateblob stateblob;
595 unsigned char *tmp;
596
597 if (stateblob.type != blobtype) {
598 /* new blob; clear old data */
599 free(stateblob.data);
600 stateblob.data = NULL;
601 stateblob.length = 0;
602 stateblob.type = blobtype;
603 stateblob.is_encrypted = is_encrypted;
604
605 /*
606 * on the first call for a new state blob we allow 0 bytes to be written
607 * this allows the user to transfer via write()
608 */
609 if (length == 0)
610 return 0;
611 }
612
613 /* append */
614 tmp = realloc(stateblob.data, stateblob.length + length);
615 if (!tmp) {
616 logprintf(STDERR_FILENO,
617 "Could not allocate %u bytes.\n", stateblob.length + length);
618 /* error */
619 free(stateblob.data);
620 stateblob.data = NULL;
621 stateblob.length = 0;
622 stateblob.type = 0;
623
624 return TPM_FAIL;
625 } else
626 stateblob.data = tmp;
627
628 memcpy(&stateblob.data[stateblob.length], data, length);
629 stateblob.length += length;
630
631 if (!is_last) {
632 /* full packet -- expecting more data */
633 return res;
634 }
635
636 res = SWTPM_NVRAM_SetStateBlob(stateblob.data,
637 stateblob.length,
638 stateblob.is_encrypted,
639 0 /* tpm_number */,
640 blobtype);
641
642 logprintf(STDERR_FILENO,
643 "Deserialized state type %d (%s), length=%d, res=%d\n",
644 blobtype, tpmlib_get_blobname(blobtype),
645 stateblob.length, res);
646
647 free(stateblob.data);
648 stateblob.data = NULL;
649 stateblob.length = 0;
650 stateblob.type = 0;
651
652 /* transfer of blob is complete */
653 tx_state.state = TX_STATE_RW_COMMAND;
654
655 return res;
656 }
657
658 /*
659 * ptm_set_stateblob: set part of a TPM state blob
660 *
661 * @req: fuse_req_t
662 * pss: ptm_setstate provided via ioctl()
663 */
664 static void
665 ptm_set_stateblob(fuse_req_t req, ptm_setstate *pss)
666 {
667 TPM_RESULT res = 0;
668 TPM_BOOL is_encrypted =
669 ((pss->u.req.state_flags & PTM_STATE_FLAG_ENCRYPTED) != 0);
670 bool is_last = (sizeof(pss->u.req.data) != pss->u.req.length);
671
672 if (pss->u.req.length > sizeof(pss->u.req.data)) {
673 res = TPM_BAD_PARAMETER;
674 goto send_response;
675 }
676
677 /* transfer of blob initiated */
678 tx_state.state = TX_STATE_SET_STATE_BLOB;
679 tx_state.blobtype = pss->u.req.type;
680 tx_state.blob_is_encrypted = is_encrypted;
681 tx_state.offset = 0;
682
683 res = ptm_set_stateblob_append(pss->u.req.type,
684 pss->u.req.data,
685 pss->u.req.length,
686 is_encrypted,
687 is_last);
688
689 if (res)
690 tx_state.state = TX_STATE_RW_COMMAND;
691
692 send_response:
693 pss->u.resp.tpm_result = res;
694
695 fuse_reply_ioctl(req, 0, pss, sizeof(*pss));
696 }
697
698 /*
699 * ptm_get_stateblob_part: get part of a state blob
700 *
701 * @blobtype: the type of blob to get
702 * @buffer: the buffer this function will write the blob into
703 * @buffer_size: the size of the buffer
704 * @offset: the offset into the state blob
705 * @copied: pointer to int to indicate the number of bytes that were copied
706 * @is_encryped: returns whether the state blob is encrypted
707 */
708 static TPM_RESULT
709 ptm_get_stateblob_part(uint32_t blobtype,
710 unsigned char *buffer, size_t buffer_size,
711 uint32_t offset, uint32_t *copied,
712 TPM_BOOL decrypt, TPM_BOOL *is_encrypted)
713 {
714 TPM_RESULT res = 0;
715
716 if (!cached_stateblob_is_loaded(blobtype, decrypt)) {
717 res = cached_stateblob_load(blobtype, decrypt);
718 }
719
720 if (res == 0) {
721 cached_stateblob_copy(buffer, buffer_size,
722 offset, copied, is_encrypted);
723 }
724
725 return res;
726 }
727
728 /*
729 * ptm_get_stateblob: Get the state blob from the TPM using ioctl()
730 */
731 static void
732 ptm_get_stateblob(fuse_req_t req, ptm_getstate *pgs)
733 {
734 TPM_RESULT res = 0;
735 uint32_t blobtype = pgs->u.req.type;
736 TPM_BOOL decrypt =
737 ((pgs->u.req.state_flags & PTM_STATE_FLAG_DECRYPTED) != 0);
738 TPM_BOOL is_encrypted = FALSE;
739 uint32_t copied = 0;
740 uint32_t offset = pgs->u.req.offset;
741 uint32_t totlength;
742
743 res = ptm_get_stateblob_part(blobtype,
744 pgs->u.resp.data, sizeof(pgs->u.resp.data),
745 pgs->u.req.offset, &copied,
746 decrypt, &is_encrypted);
747
748 totlength = cached_stateblob_get_bloblength();
749
750 pgs->u.resp.state_flags = 0;
751 if (is_encrypted)
752 pgs->u.resp.state_flags |= PTM_STATE_FLAG_ENCRYPTED;
753
754 pgs->u.resp.length = copied;
755 pgs->u.resp.totlength = totlength;
756 pgs->u.resp.tpm_result = res;
757 logprintf(STDERR_FILENO,
758 "Serialized state type %d, length=%d, totlength=%d, res=%d\n",
759 blobtype, copied, totlength, 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 * tpmversion: the version of the TPM
815 */
816 static void ptm_write_cmd(fuse_req_t req, const char *buf, size_t size,
817 TPMLIB_TPMVersion l_tpmversion)
818 {
819 ptm_req_len = size;
820 ptm_res_len = 0;
821
822 /* prevent other threads from writing or doing ioctls */
823 g_mutex_lock(FILE_OPS_LOCK);
824
825 if (tpm_running) {
826 /* ensure that we only ever work on one TPM command */
827 if (worker_thread_is_busy()) {
828 fuse_reply_err(req, EBUSY);
829 goto cleanup;
830 }
831
832 if (ptm_req_len > TPM_REQ_MAX)
833 ptm_req_len = TPM_REQ_MAX;
834
835 /* process SetLocality command, if */
836 tpmlib_process(&ptm_response, &ptm_res_len, &ptm_res_tot,
837 (unsigned char *)buf, ptm_req_len,
838 locality_flags, &locality, tpmversion);
839 if (ptm_res_len)
840 goto skip_process;
841
842 if (tpmlib_is_request_cancelable(l_tpmversion,
843 (const unsigned char*)buf,
844 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(l_tpmversion);
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, tpmversion);
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 TPM_MODIFIER_INDICATOR orig_locality;
925
926 /* some commands have to wait until the worker thread is done */
927 switch(cmd) {
928 case PTM_GET_CAPABILITY:
929 case PTM_SET_LOCALITY:
930 case PTM_CANCEL_TPM_CMD:
931 case PTM_GET_CONFIG:
932 case PTM_SET_BUFFERSIZE:
933 /* no need to wait */
934 break;
935 case PTM_INIT:
936 case PTM_SHUTDOWN:
937 case PTM_GET_TPMESTABLISHED:
938 case PTM_RESET_TPMESTABLISHED:
939 case PTM_HASH_START:
940 case PTM_HASH_DATA:
941 case PTM_HASH_END:
942 case PTM_STORE_VOLATILE:
943 case PTM_GET_STATEBLOB:
944 case PTM_SET_STATEBLOB:
945 if (tpm_running)
946 worker_thread_wait_done();
947 break;
948 }
949
950 /* prevent other threads from writing or doing ioctls */
951 g_mutex_lock(FILE_OPS_LOCK);
952
953 switch (cmd) {
954 case PTM_GET_CAPABILITY:
955 if (out_bufsz != sizeof(ptm_cap)) {
956 struct iovec iov = { arg, sizeof(uint8_t) };
957 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
958 } else {
959 ptm_cap ptm_caps;
960 switch (tpmversion) {
961 case TPMLIB_TPM_VERSION_2:
962 ptm_caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN
963 | PTM_CAP_GET_TPMESTABLISHED
964 | PTM_CAP_SET_LOCALITY
965 | PTM_CAP_HASHING
966 | PTM_CAP_CANCEL_TPM_CMD
967 | PTM_CAP_STORE_VOLATILE
968 | PTM_CAP_RESET_TPMESTABLISHED
969 | PTM_CAP_GET_STATEBLOB
970 | PTM_CAP_SET_STATEBLOB
971 | PTM_CAP_STOP
972 | PTM_CAP_GET_CONFIG
973 | PTM_CAP_SET_BUFFERSIZE
974 | PTM_CAP_GET_INFO;
975 break;
976 case TPMLIB_TPM_VERSION_1_2:
977 ptm_caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN
978 | PTM_CAP_GET_TPMESTABLISHED
979 | PTM_CAP_SET_LOCALITY
980 | PTM_CAP_HASHING
981 | PTM_CAP_CANCEL_TPM_CMD
982 | PTM_CAP_STORE_VOLATILE
983 | PTM_CAP_RESET_TPMESTABLISHED
984 | PTM_CAP_GET_STATEBLOB
985 | PTM_CAP_SET_STATEBLOB
986 | PTM_CAP_STOP
987 | PTM_CAP_GET_CONFIG
988 | PTM_CAP_SET_BUFFERSIZE
989 | PTM_CAP_GET_INFO;
990 break;
991 }
992 fuse_reply_ioctl(req, 0, &ptm_caps, sizeof(ptm_caps));
993 }
994 break;
995
996 case PTM_INIT:
997 if (in_bufsz != sizeof(ptm_init)) {
998 struct iovec iov = { arg, sizeof(uint8_t) };
999 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1000 } else {
1001 init_p = (ptm_init *)in_buf;
1002
1003 worker_thread_end();
1004
1005 TPMLIB_Terminate();
1006
1007 tpm_running = false;
1008 if (tpm_start(init_p->u.req.init_flags, tpmversion, &res) < 0) {
1009 logprintf(STDERR_FILENO,
1010 "Error: Could not initialize the TPM.\n");
1011 } else {
1012 tpm_running = true;
1013 }
1014 init_p->u.resp.tpm_result = res;
1015 fuse_reply_ioctl(req, 0, init_p, sizeof(*init_p));
1016 }
1017 break;
1018
1019 case PTM_STOP:
1020 worker_thread_end();
1021
1022 res = TPM_SUCCESS;
1023 TPMLIB_Terminate();
1024
1025 tpm_running = false;
1026
1027 free(ptm_response);
1028 ptm_response = NULL;
1029
1030 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1031
1032 break;
1033
1034 case PTM_SHUTDOWN:
1035 worker_thread_end();
1036
1037 res = TPM_SUCCESS;
1038 TPMLIB_Terminate();
1039
1040 free(ptm_response);
1041 ptm_response = NULL;
1042
1043 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1044 exit_prg = TRUE;
1045
1046 break;
1047
1048 case PTM_GET_TPMESTABLISHED:
1049 if (!tpm_running)
1050 goto error_not_running;
1051
1052 if (out_bufsz != sizeof(ptm_est)) {
1053 struct iovec iov = { arg, sizeof(uint8_t) };
1054 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1055 } else {
1056 ptm_est te;
1057 memset(&te, 0, sizeof(te));
1058 te.u.resp.tpm_result = TPM_IO_TpmEstablished_Get(&te.u.resp.bit);
1059 fuse_reply_ioctl(req, 0, &te, sizeof(te));
1060 }
1061 break;
1062
1063 case PTM_RESET_TPMESTABLISHED:
1064 if (!tpm_running)
1065 goto error_not_running;
1066
1067 if (in_bufsz != sizeof(ptm_reset_est)) {
1068 struct iovec iov = { arg, sizeof(uint32_t) };
1069 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1070 } else {
1071 ptm_reset_est *re = (ptm_reset_est *)in_buf;
1072 if (re->u.req.loc > 4) {
1073 res = TPM_BAD_LOCALITY;
1074 } else {
1075 /* set locality and reset flag in one command */
1076 orig_locality = locality;
1077 locality = re->u.req.loc;
1078
1079 res = TPM_IO_TpmEstablished_Reset();
1080
1081 locality = orig_locality;
1082 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1083 }
1084 }
1085 break;
1086
1087 case PTM_SET_LOCALITY:
1088 if (in_bufsz != sizeof(ptm_loc)) {
1089 struct iovec iov = { arg, sizeof(uint32_t) };
1090 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1091 } else {
1092 ptm_loc *l = (ptm_loc *)in_buf;
1093 if (l->u.req.loc > 4 ||
1094 (l->u.req.loc == 4 &&
1095 locality_flags & LOCALITY_FLAG_REJECT_LOCALITY_4)) {
1096 res = TPM_BAD_LOCALITY;
1097 } else {
1098 res = TPM_SUCCESS;
1099 locality = l->u.req.loc;
1100 }
1101 l->u.resp.tpm_result = res;
1102 fuse_reply_ioctl(req, 0, l, sizeof(*l));
1103 }
1104 break;
1105
1106 case PTM_HASH_START:
1107 if (!tpm_running)
1108 goto error_not_running;
1109
1110 res = TPM_IO_Hash_Start();
1111 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1112 break;
1113
1114 case PTM_HASH_DATA:
1115 if (!tpm_running)
1116 goto error_not_running;
1117
1118 if (in_bufsz != sizeof(ptm_hdata)) {
1119 struct iovec iov = { arg, sizeof(uint32_t) };
1120 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1121 } else {
1122 ptm_hdata *data = (ptm_hdata *)in_buf;
1123 if (data->u.req.length <= sizeof(data->u.req.data)) {
1124 res = TPM_IO_Hash_Data(data->u.req.data,
1125 data->u.req.length);
1126 } else {
1127 res = TPM_FAIL;
1128 }
1129 data->u.resp.tpm_result = res;
1130 fuse_reply_ioctl(req, 0, data, sizeof(*data));
1131 }
1132 break;
1133
1134 case PTM_HASH_END:
1135 if (!tpm_running)
1136 goto error_not_running;
1137
1138 res = TPM_IO_Hash_End();
1139 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1140 break;
1141
1142 case PTM_CANCEL_TPM_CMD:
1143 if (!tpm_running)
1144 goto error_not_running;
1145
1146 /* for cancellation to work, the TPM would have to
1147 * execute in another thread that polls on a cancel
1148 * flag
1149 */
1150 res = TPMLIB_CancelCommand();
1151 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1152 break;
1153
1154 case PTM_STORE_VOLATILE:
1155 if (!tpm_running)
1156 goto error_not_running;
1157
1158 res = SWTPM_NVRAM_Store_Volatile();
1159 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1160
1161 cached_stateblob_free();
1162 break;
1163
1164 case PTM_GET_STATEBLOB:
1165 if (!tpm_running)
1166 goto error_not_running;
1167
1168 if (in_bufsz != sizeof(ptm_getstate)) {
1169 struct iovec iov = { arg, sizeof(uint32_t) };
1170 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1171 } else {
1172 ptm_get_stateblob(req, (ptm_getstate *)in_buf);
1173 }
1174 break;
1175
1176 case PTM_SET_STATEBLOB:
1177 if (tpm_running)
1178 goto error_running;
1179
1180 /* tpm state dir must be set */
1181 SWTPM_NVRAM_Init();
1182
1183 if (in_bufsz != sizeof(ptm_setstate)) {
1184 struct iovec iov = { arg, sizeof(uint32_t) };
1185 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1186 } else {
1187 ptm_set_stateblob(req, (ptm_setstate *)in_buf);
1188 }
1189 break;
1190
1191 case PTM_GET_CONFIG:
1192 if (out_bufsz != sizeof(ptm_getconfig)) {
1193 struct iovec iov = { arg, sizeof(uint32_t) };
1194 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1195 } else {
1196 ptm_getconfig pgs;
1197 pgs.u.resp.tpm_result = 0;
1198 pgs.u.resp.flags = 0;
1199 if (SWTPM_NVRAM_Has_FileKey())
1200 pgs.u.resp.flags |= PTM_CONFIG_FLAG_FILE_KEY;
1201 if (SWTPM_NVRAM_Has_MigrationKey())
1202 pgs.u.resp.flags |= PTM_CONFIG_FLAG_MIGRATION_KEY;
1203 fuse_reply_ioctl(req, 0, &pgs, sizeof(pgs));
1204 }
1205 break;
1206
1207 case PTM_SET_BUFFERSIZE:
1208 if (out_bufsz != sizeof(ptm_setbuffersize)) {
1209 struct iovec iov = { arg, sizeof(uint32_t) };
1210 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1211 } else {
1212 ptm_setbuffersize *in_psbs = (ptm_setbuffersize *)in_buf;
1213 ptm_setbuffersize out_psbs;
1214 uint32_t buffersize, minsize, maxsize;
1215
1216 buffersize = in_psbs->u.req.buffersize;
1217
1218 if (buffersize > 0 && tpm_running)
1219 goto error_running;
1220
1221 buffersize = TPMLIB_SetBufferSize(buffersize,
1222 &minsize,
1223 &maxsize);
1224
1225 out_psbs.u.resp.tpm_result = TPM_SUCCESS;
1226 out_psbs.u.resp.buffersize = buffersize;
1227 out_psbs.u.resp.minsize = minsize;
1228 out_psbs.u.resp.maxsize = maxsize;
1229 fuse_reply_ioctl(req, 0, &out_psbs, sizeof(out_psbs));
1230 }
1231 break;
1232
1233 case PTM_GET_INFO:
1234 if (out_bufsz != sizeof(ptm_getinfo)) {
1235 struct iovec iov = { arg, sizeof(uint32_t) };
1236 fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
1237 } else {
1238 ptm_getinfo *in_pgi = (ptm_getinfo *)in_buf;
1239 ptm_getinfo out_pgi;
1240 char *info_data;
1241 uint32_t length, offset;
1242
1243 info_data = TPMLIB_GetInfo(in_pgi->u.req.flags);
1244 if (!info_data)
1245 goto error_memory;
1246
1247 offset = in_pgi->u.req.offset;
1248 if (offset >= strlen(info_data)) {
1249 free(info_data);
1250 goto error_bad_input;
1251 }
1252
1253 length = min(strlen(info_data) + 1 - offset,
1254 sizeof(out_pgi.u.resp.buffer));
1255
1256 out_pgi.u.resp.tpm_result = 0;
1257 out_pgi.u.resp.totlength = strlen(info_data) + 1;
1258 out_pgi.u.resp.length = length;
1259 /* client has to collect whole string in case buffer is too small */
1260 memcpy(out_pgi.u.resp.buffer, &info_data[offset], length);
1261 free(info_data);
1262
1263 fuse_reply_ioctl(req, 0, &out_pgi, sizeof(out_pgi));
1264 }
1265 break;
1266
1267 default:
1268 fuse_reply_err(req, EINVAL);
1269 }
1270
1271 cleanup:
1272 g_mutex_unlock(FILE_OPS_LOCK);
1273
1274 if (exit_prg) {
1275 logprintf(STDOUT_FILENO, "CUSE TPM is shutting down.\n");
1276 ptm_cleanup();
1277 fuse_session_exit(ptm_fuse_session);
1278 }
1279
1280 return;
1281
1282 error_bad_input:
1283 res = TPM_BAD_PARAMETER;
1284 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1285
1286 goto cleanup;
1287
1288 error_running:
1289 error_not_running:
1290 res = TPM_BAD_ORDINAL;
1291 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1292
1293 goto cleanup;
1294
1295 error_memory:
1296 res = TPM_SIZE;
1297 fuse_reply_ioctl(req, 0, &res, sizeof(res));
1298
1299 goto cleanup;
1300 }
1301
1302 static void ptm_init_done(void *userdata)
1303 {
1304 struct cuse_param *param = userdata;
1305 int ret;
1306
1307 /* at this point the entry in /dev/ is available */
1308 if (pidfile_write(getpid()) < 0) {
1309 ret = -13;
1310 goto error_exit;
1311 }
1312
1313 if (param->runas) {
1314 ret = change_process_owner(param->runas);
1315 if (ret)
1316 goto error_exit;
1317 }
1318
1319 if (create_seccomp_profile(true, param->seccomp_action) < 0) {
1320 ret = -14;
1321 goto error_exit;
1322 }
1323
1324 return;
1325
1326 error_exit:
1327 ptm_cleanup();
1328
1329 exit(ret);
1330 }
1331
1332 static void ptm_cleanup(void)
1333 {
1334 pidfile_remove();
1335 log_global_free();
1336 tpmstate_global_free();
1337 }
1338
1339 static const struct cuse_lowlevel_ops clops = {
1340 .open = ptm_open,
1341 .read = ptm_read,
1342 .write = ptm_write,
1343 .ioctl = ptm_ioctl,
1344 .init_done = ptm_init_done,
1345 };
1346
1347 /* ptm_cuse_lowlevel_main is like cuse_lowlevel_main with the difference that
1348 * it uses a global ptm_fuse_session so we can call fuse_session_exit() on it
1349 * for a graceful exit with cleanups.
1350 */
1351 static int
1352 ptm_cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci,
1353 const struct cuse_lowlevel_ops *clop, void *userdata)
1354 {
1355 int mt;
1356 int ret;
1357 struct cuse_param *param = userdata;
1358
1359 ptm_fuse_session = cuse_lowlevel_setup(argc, argv, ci, clop, &mt,
1360 userdata);
1361 if (ptm_fuse_session == NULL)
1362 return 1;
1363
1364 if (param->seccomp_action == SWTPM_SECCOMP_ACTION_NONE && mt)
1365 ret = fuse_session_loop_mt(ptm_fuse_session);
1366 else
1367 ret = fuse_session_loop(ptm_fuse_session);
1368
1369 cuse_lowlevel_teardown(ptm_fuse_session);
1370 if (ret < 0)
1371 ret = 1;
1372
1373 return ret;
1374 }
1375
1376 #ifndef HAVE_SWTPM_CUSE_MAIN
1377 int main(int argc, char **argv)
1378 {
1379 const char *prgname = argv[0];
1380 const char *iface = "";
1381 #else
1382 int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *iface)
1383 {
1384 #endif
1385 int opt, longindex = 0;
1386 static struct option longopts[] = {
1387 {"maj" , required_argument, 0, 'M'},
1388 {"min" , required_argument, 0, 'm'},
1389 {"name" , required_argument, 0, 'n'},
1390 {"runas" , required_argument, 0, 'r'},
1391 {"log" , required_argument, 0, 'l'},
1392 {"locality" , required_argument, 0, 'L'},
1393 {"key" , required_argument, 0, 'k'},
1394 {"migration-key" , required_argument, 0, 'K'},
1395 {"pid" , required_argument, 0, 'p'},
1396 {"tpmstate" , required_argument, 0, 's'},
1397 {"tpm2" , no_argument, 0, '2'},
1398 {"help" , no_argument, 0, 'h'},
1399 {"version" , no_argument, 0, 'v'},
1400 #ifdef WITH_SECCOMP
1401 {"seccomp" , required_argument, 0, 'S'},
1402 #endif
1403 {"print-capabilities"
1404 , no_argument, 0, 'a'},
1405 {NULL , 0 , 0, 0 },
1406 };
1407 struct cuse_info cinfo;
1408 struct cuse_param param;
1409 const char *devname = NULL;
1410 char *cinfo_argv[1] = { 0 };
1411 unsigned int num;
1412 struct passwd *passwd;
1413 const char *tpmdir;
1414 int n, tpmfd;
1415 char path[PATH_MAX];
1416 int ret = 0;
1417
1418 memset(&cinfo, 0, sizeof(cinfo));
1419 memset(&param, 0, sizeof(param));
1420
1421 log_set_prefix("swtpm: ");
1422
1423 tpmversion = TPMLIB_TPM_VERSION_1_2;
1424
1425 while (true) {
1426 opt = getopt_long(argc, argv, "M:m:n:r:hv", longopts, &longindex);
1427
1428 if (opt == -1)
1429 break;
1430
1431 switch (opt) {
1432 case 'M': /* major */
1433 if (sscanf(optarg, "%u", &num) != 1) {
1434 logprintf(STDERR_FILENO, "Could not parse major number\n");
1435 ret = -1;
1436 goto exit;
1437 }
1438 if (num > 65535) {
1439 logprintf(STDERR_FILENO,
1440 "Major number outside valid range [0 - 65535]\n");
1441 ret = -1;
1442 goto exit;
1443 }
1444 cinfo.dev_major = num;
1445 break;
1446 case 'm': /* minor */
1447 if (sscanf(optarg, "%u", &num) != 1) {
1448 logprintf(STDERR_FILENO, "Could not parse major number\n");
1449 ret = -1;
1450 goto exit;
1451 }
1452 if (num > 65535) {
1453 logprintf(STDERR_FILENO,
1454 "Major number outside valid range [0 - 65535]\n");
1455 ret = -1;
1456 goto exit;
1457 }
1458 cinfo.dev_minor = num;
1459 break;
1460 case 'n': /* name */
1461 if (!cinfo.dev_info_argc) {
1462 cinfo_argv[0] = calloc(1, strlen("DEVNAME=") + strlen(optarg) + 1);
1463 if (!cinfo_argv[0]) {
1464 logprintf(STDERR_FILENO, "Out of memory\n");
1465 ret = -1;
1466 goto exit;
1467 }
1468 devname = optarg;
1469
1470 strcpy(cinfo_argv[0], "DEVNAME=");
1471 strcat(cinfo_argv[0], optarg);
1472
1473 cinfo.dev_info_argc = 1;
1474 cinfo.dev_info_argv = (const char **)cinfo_argv;
1475 }
1476 break;
1477 case 'r': /* runas */
1478 param.runas = optarg;
1479 break;
1480 case 'l': /* log */
1481 param.logging = optarg;
1482 break;
1483 case 'k': /* key */
1484 param.keydata = optarg;
1485 break;
1486 case 'K': /* migration-key */
1487 param.migkeydata = optarg;
1488 break;
1489 case 'p': /* pid */
1490 param.piddata = optarg;
1491 break;
1492 case 's': /* tpmstate */
1493 param.tpmstatedata = optarg;
1494 break;
1495 case 'L':
1496 param.localitydata = optarg;
1497 break;
1498 case '2':
1499 tpmversion = TPMLIB_TPM_VERSION_2;
1500 break;
1501 case 'S':
1502 param.seccompdata = optarg;
1503 break;
1504 case 'h': /* help */
1505 fprintf(stdout, usage, prgname, iface);
1506 goto exit;
1507 case 'a':
1508 ret = capabilities_print_json(true);
1509 goto exit;
1510 case 'v': /* version */
1511 fprintf(stdout, "TPM emulator CUSE interface version %d.%d.%d, "
1512 "Copyright (c) 2014-2015 IBM Corp.\n",
1513 SWTPM_VER_MAJOR,
1514 SWTPM_VER_MINOR,
1515 SWTPM_VER_MICRO);
1516 goto exit;
1517 }
1518 }
1519
1520 if (optind < argc) {
1521 logprintf(STDERR_FILENO,
1522 "Unknown parameter '%s'\n", argv[optind]);
1523 ret = EXIT_FAILURE;
1524 goto exit;
1525 }
1526
1527 /*
1528 * choose the TPM version early so that getting/setting
1529 * buffer size works.
1530 */
1531 if (TPMLIB_ChooseTPMVersion(tpmversion) != TPM_SUCCESS) {
1532 logprintf(STDERR_FILENO,
1533 "Error: Could not choose TPM version.\n");
1534 ret = EXIT_FAILURE;
1535 goto exit;
1536 }
1537
1538 SWTPM_NVRAM_Set_TPMVersion(tpmversion);
1539
1540 if (!cinfo.dev_info_argv) {
1541 logprintf(STDERR_FILENO, "Error: device name missing\n");
1542 ret = -2;
1543 goto exit;
1544 }
1545
1546 if (handle_log_options(param.logging) < 0 ||
1547 handle_key_options(param.keydata) < 0 ||
1548 handle_migration_key_options(param.migkeydata) < 0 ||
1549 handle_pid_options(param.piddata) < 0 ||
1550 handle_tpmstate_options(param.tpmstatedata) < 0 ||
1551 handle_seccomp_options(param.seccompdata, &param.seccomp_action) < 0 ||
1552 handle_locality_options(param.localitydata, &locality_flags) < 0) {
1553 ret = -3;
1554 goto exit;
1555 }
1556
1557 if (setuid(0)) {
1558 logprintf(STDERR_FILENO, "Error: Unable to setuid root. uid = %d, "
1559 "euid = %d, gid = %d\n", getuid(), geteuid(), getgid());
1560 ret = -4;
1561 goto exit;
1562 }
1563
1564 if (param.runas) {
1565 if (!(passwd = getpwnam(param.runas))) {
1566 logprintf(STDERR_FILENO, "User '%s' does not exist\n",
1567 param.runas);
1568 ret = -5;
1569 goto exit;
1570 }
1571 }
1572
1573 tpmdir = tpmstate_get_dir();
1574 if (tpmdir == NULL) {
1575 logprintf(STDERR_FILENO,
1576 "Error: No TPM state directory is defined; "
1577 "TPM_PATH is not set\n");
1578 ret = -1;
1579 goto exit;
1580 }
1581
1582 n = snprintf(path, sizeof(path), "/dev/%s", devname);
1583 if (n < 0) {
1584 logprintf(STDERR_FILENO,
1585 "Error: Could not create device file name\n");
1586 ret = -1;
1587 goto exit;
1588 }
1589 if (n >= (int)sizeof(path)) {
1590 logprintf(STDERR_FILENO,
1591 "Error: Buffer too small to create device file name\n");
1592 ret = -1;
1593 goto exit;
1594 }
1595
1596 tpmfd = open(path, O_RDWR);
1597 if (tpmfd >= 0) {
1598 close(tpmfd);
1599 logprintf(STDERR_FILENO,
1600 "Error: A device '%s' already exists.\n",
1601 path);
1602 ret = -1;
1603 goto exit;
1604 }
1605
1606 if (tpmlib_register_callbacks(&cbs) != TPM_SUCCESS) {
1607 ret = -1;
1608 goto exit;
1609 }
1610
1611 worker_thread_init();
1612
1613 #if GLIB_MINOR_VERSION >= 32
1614 g_mutex_init(FILE_OPS_LOCK);
1615 #else
1616 FILE_OPS_LOCK = g_mutex_new();
1617 #endif
1618
1619 ret = ptm_cuse_lowlevel_main(1, argv, &cinfo, &clops, &param);
1620
1621 exit:
1622 ptm_cleanup();
1623 free(cinfo_argv[0]);
1624
1625 return ret;
1626 }