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