1 /* 2 * Copyright (C) 2015, 2016 IBM Corporation 3 * Copyright (C) 2016 Intel Corporation 4 * 5 * Author: Stefan Berger <stefanb@us.ibm.com> 6 * 7 * Maintained by: <tpmdd-devel@lists.sourceforge.net> 8 * 9 * Device driver for vTPM (vTPM proxy driver) 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation, version 2 of the 14 * License. 15 * 16 */ 17 18 #include <linux/types.h> 19 #include <linux/spinlock.h> 20 #include <linux/uaccess.h> 21 #include <linux/wait.h> 22 #include <linux/miscdevice.h> 23 #include <linux/vtpm_proxy.h> 24 #include <linux/file.h> 25 #include <linux/anon_inodes.h> 26 #include <linux/poll.h> 27 #include <linux/compat.h> 28 29 #include "tpm.h" 30 31 #define VTPM_PROXY_REQ_COMPLETE_FLAG BIT(0) 32 33 struct proxy_dev { 34 struct tpm_chip *chip; 35 36 u32 flags; /* public API flags */ 37 38 wait_queue_head_t wq; 39 40 struct mutex buf_lock; /* protect buffer and flags */ 41 42 long state; /* internal state */ 43 #define STATE_OPENED_FLAG BIT(0) 44 #define STATE_WAIT_RESPONSE_FLAG BIT(1) /* waiting for emulator response */ 45 #define STATE_REGISTERED_FLAG BIT(2) 46 #define STATE_DRIVER_COMMAND BIT(3) /* sending a driver specific command */ 47 48 size_t req_len; /* length of queued TPM request */ 49 size_t resp_len; /* length of queued TPM response */ 50 u8 buffer[TPM_BUFSIZE]; /* request/response buffer */ 51 52 struct work_struct work; /* task that retrieves TPM timeouts */ 53 }; 54 55 /* all supported flags */ 56 #define VTPM_PROXY_FLAGS_ALL (VTPM_PROXY_FLAG_TPM2) 57 58 static struct workqueue_struct *workqueue; 59 60 static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev); 61 62 /* 63 * Functions related to 'server side' 64 */ 65 66 /** 67 * vtpm_proxy_fops_read - Read TPM commands on 'server side' 68 * 69 * @filp: file pointer 70 * @buf: read buffer 71 * @count: number of bytes to read 72 * @off: offset 73 * 74 * Return: 75 * Number of bytes read or negative error code 76 */ 77 static ssize_t vtpm_proxy_fops_read(struct file *filp, char __user *buf, 78 size_t count, loff_t *off) 79 { 80 struct proxy_dev *proxy_dev = filp->private_data; 81 size_t len; 82 int sig, rc; 83 84 sig = wait_event_interruptible(proxy_dev->wq, 85 proxy_dev->req_len != 0 || 86 !(proxy_dev->state & STATE_OPENED_FLAG)); 87 if (sig) 88 return -EINTR; 89 90 mutex_lock(&proxy_dev->buf_lock); 91 92 if (!(proxy_dev->state & STATE_OPENED_FLAG)) { 93 mutex_unlock(&proxy_dev->buf_lock); 94 return -EPIPE; 95 } 96 97 len = proxy_dev->req_len; 98 99 if (count < len) { 100 mutex_unlock(&proxy_dev->buf_lock); 101 pr_debug("Invalid size in recv: count=%zd, req_len=%zd\n", 102 count, len); 103 return -EIO; 104 } 105 106 rc = copy_to_user(buf, proxy_dev->buffer, len); 107 memset(proxy_dev->buffer, 0, len); 108 proxy_dev->req_len = 0; 109 110 if (!rc) 111 proxy_dev->state |= STATE_WAIT_RESPONSE_FLAG; 112 113 mutex_unlock(&proxy_dev->buf_lock); 114 115 if (rc) 116 return -EFAULT; 117 118 return len; 119 } 120 121 /** 122 * vtpm_proxy_fops_write - Write TPM responses on 'server side' 123 * 124 * @filp: file pointer 125 * @buf: write buffer 126 * @count: number of bytes to write 127 * @off: offset 128 * 129 * Return: 130 * Number of bytes read or negative error value 131 */ 132 static ssize_t vtpm_proxy_fops_write(struct file *filp, const char __user *buf, 133 size_t count, loff_t *off) 134 { 135 struct proxy_dev *proxy_dev = filp->private_data; 136 137 mutex_lock(&proxy_dev->buf_lock); 138 139 if (!(proxy_dev->state & STATE_OPENED_FLAG)) { 140 mutex_unlock(&proxy_dev->buf_lock); 141 return -EPIPE; 142 } 143 144 if (count > sizeof(proxy_dev->buffer) || 145 !(proxy_dev->state & STATE_WAIT_RESPONSE_FLAG)) { 146 mutex_unlock(&proxy_dev->buf_lock); 147 return -EIO; 148 } 149 150 proxy_dev->state &= ~STATE_WAIT_RESPONSE_FLAG; 151 152 proxy_dev->req_len = 0; 153 154 if (copy_from_user(proxy_dev->buffer, buf, count)) { 155 mutex_unlock(&proxy_dev->buf_lock); 156 return -EFAULT; 157 } 158 159 proxy_dev->resp_len = count; 160 161 mutex_unlock(&proxy_dev->buf_lock); 162 163 wake_up_interruptible(&proxy_dev->wq); 164 165 return count; 166 } 167 168 /* 169 * vtpm_proxy_fops_poll - Poll status on 'server side' 170 * 171 * @filp: file pointer 172 * @wait: poll table 173 * 174 * Return: Poll flags 175 */ 176 static __poll_t vtpm_proxy_fops_poll(struct file *filp, poll_table *wait) 177 { 178 struct proxy_dev *proxy_dev = filp->private_data; 179 __poll_t ret; 180 181 poll_wait(filp, &proxy_dev->wq, wait); 182 183 ret = EPOLLOUT; 184 185 mutex_lock(&proxy_dev->buf_lock); 186 187 if (proxy_dev->req_len) 188 ret |= EPOLLIN | EPOLLRDNORM; 189 190 if (!(proxy_dev->state & STATE_OPENED_FLAG)) 191 ret |= EPOLLHUP; 192 193 mutex_unlock(&proxy_dev->buf_lock); 194 195 return ret; 196 } 197 198 /* 199 * vtpm_proxy_fops_open - Open vTPM device on 'server side' 200 * 201 * @filp: file pointer 202 * 203 * Called when setting up the anonymous file descriptor 204 */ 205 static void vtpm_proxy_fops_open(struct file *filp) 206 { 207 struct proxy_dev *proxy_dev = filp->private_data; 208 209 proxy_dev->state |= STATE_OPENED_FLAG; 210 } 211 212 /** 213 * vtpm_proxy_fops_undo_open - counter-part to vtpm_fops_open 214 * Call to undo vtpm_proxy_fops_open 215 * 216 *@proxy_dev: tpm proxy device 217 */ 218 static void vtpm_proxy_fops_undo_open(struct proxy_dev *proxy_dev) 219 { 220 mutex_lock(&proxy_dev->buf_lock); 221 222 proxy_dev->state &= ~STATE_OPENED_FLAG; 223 224 mutex_unlock(&proxy_dev->buf_lock); 225 226 /* no more TPM responses -- wake up anyone waiting for them */ 227 wake_up_interruptible(&proxy_dev->wq); 228 } 229 230 /* 231 * vtpm_proxy_fops_release - Close 'server side' 232 * 233 * @inode: inode 234 * @filp: file pointer 235 * Return: 236 * Always returns 0. 237 */ 238 static int vtpm_proxy_fops_release(struct inode *inode, struct file *filp) 239 { 240 struct proxy_dev *proxy_dev = filp->private_data; 241 242 filp->private_data = NULL; 243 244 vtpm_proxy_delete_device(proxy_dev); 245 246 return 0; 247 } 248 249 static const struct file_operations vtpm_proxy_fops = { 250 .owner = THIS_MODULE, 251 .llseek = no_llseek, 252 .read = vtpm_proxy_fops_read, 253 .write = vtpm_proxy_fops_write, 254 .poll = vtpm_proxy_fops_poll, 255 .release = vtpm_proxy_fops_release, 256 }; 257 258 /* 259 * Functions invoked by the core TPM driver to send TPM commands to 260 * 'server side' and receive responses from there. 261 */ 262 263 /* 264 * Called when core TPM driver reads TPM responses from 'server side' 265 * 266 * @chip: tpm chip to use 267 * @buf: receive buffer 268 * @count: bytes to read 269 * Return: 270 * Number of TPM response bytes read, negative error value otherwise 271 */ 272 static int vtpm_proxy_tpm_op_recv(struct tpm_chip *chip, u8 *buf, size_t count) 273 { 274 struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); 275 size_t len; 276 277 /* process gone ? */ 278 mutex_lock(&proxy_dev->buf_lock); 279 280 if (!(proxy_dev->state & STATE_OPENED_FLAG)) { 281 mutex_unlock(&proxy_dev->buf_lock); 282 return -EPIPE; 283 } 284 285 len = proxy_dev->resp_len; 286 if (count < len) { 287 dev_err(&chip->dev, 288 "Invalid size in recv: count=%zd, resp_len=%zd\n", 289 count, len); 290 len = -EIO; 291 goto out; 292 } 293 294 memcpy(buf, proxy_dev->buffer, len); 295 proxy_dev->resp_len = 0; 296 297 out: 298 mutex_unlock(&proxy_dev->buf_lock); 299 300 return len; 301 } 302 303 static int vtpm_proxy_is_driver_command(struct tpm_chip *chip, 304 u8 *buf, size_t count) 305 { 306 struct tpm_header *hdr = (struct tpm_header *)buf; 307 308 if (count < sizeof(struct tpm_header)) 309 return 0; 310 311 if (chip->flags & TPM_CHIP_FLAG_TPM2) { 312 switch (be32_to_cpu(hdr->ordinal)) { 313 case TPM2_CC_SET_LOCALITY: 314 return 1; 315 } 316 } else { 317 switch (be32_to_cpu(hdr->ordinal)) { 318 case TPM_ORD_SET_LOCALITY: 319 return 1; 320 } 321 } 322 return 0; 323 } 324 325 /* 326 * Called when core TPM driver forwards TPM requests to 'server side'. 327 * 328 * @chip: tpm chip to use 329 * @buf: send buffer 330 * @count: bytes to send 331 * 332 * Return: 333 * 0 in case of success, negative error value otherwise. 334 */ 335 static int vtpm_proxy_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t count) 336 { 337 struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); 338 339 if (count > sizeof(proxy_dev->buffer)) { 340 dev_err(&chip->dev, 341 "Invalid size in send: count=%zd, buffer size=%zd\n", 342 count, sizeof(proxy_dev->buffer)); 343 return -EIO; 344 } 345 346 if (!(proxy_dev->state & STATE_DRIVER_COMMAND) && 347 vtpm_proxy_is_driver_command(chip, buf, count)) 348 return -EFAULT; 349 350 mutex_lock(&proxy_dev->buf_lock); 351 352 if (!(proxy_dev->state & STATE_OPENED_FLAG)) { 353 mutex_unlock(&proxy_dev->buf_lock); 354 return -EPIPE; 355 } 356 357 proxy_dev->resp_len = 0; 358 359 proxy_dev->req_len = count; 360 memcpy(proxy_dev->buffer, buf, count); 361 362 proxy_dev->state &= ~STATE_WAIT_RESPONSE_FLAG; 363 364 mutex_unlock(&proxy_dev->buf_lock); 365 366 wake_up_interruptible(&proxy_dev->wq); 367 368 return 0; 369 } 370 371 static void vtpm_proxy_tpm_op_cancel(struct tpm_chip *chip) 372 { 373 /* not supported */ 374 } 375 376 static u8 vtpm_proxy_tpm_op_status(struct tpm_chip *chip) 377 { 378 struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); 379 380 if (proxy_dev->resp_len) 381 return VTPM_PROXY_REQ_COMPLETE_FLAG; 382 383 return 0; 384 } 385 386 static bool vtpm_proxy_tpm_req_canceled(struct tpm_chip *chip, u8 status) 387 { 388 struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); 389 bool ret; 390 391 mutex_lock(&proxy_dev->buf_lock); 392 393 ret = !(proxy_dev->state & STATE_OPENED_FLAG); 394 395 mutex_unlock(&proxy_dev->buf_lock); 396 397 return ret; 398 } 399 400 static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality) 401 { 402 struct tpm_buf buf; 403 int rc; 404 const struct tpm_header *header; 405 struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); 406 407 if (chip->flags & TPM_CHIP_FLAG_TPM2) 408 rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, 409 TPM2_CC_SET_LOCALITY); 410 else 411 rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, 412 TPM_ORD_SET_LOCALITY); 413 if (rc) 414 return rc; 415 tpm_buf_append_u8(&buf, locality); 416 417 proxy_dev->state |= STATE_DRIVER_COMMAND; 418 419 rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to set locality"); 420 421 proxy_dev->state &= ~STATE_DRIVER_COMMAND; 422 423 if (rc < 0) { 424 locality = rc; 425 goto out; 426 } 427 428 header = (const struct tpm_header *)buf.data; 429 rc = be32_to_cpu(header->return_code); 430 if (rc) 431 locality = -1; 432 433 out: 434 tpm_buf_destroy(&buf); 435 436 return locality; 437 } 438 439 static const struct tpm_class_ops vtpm_proxy_tpm_ops = { 440 .flags = TPM_OPS_AUTO_STARTUP, 441 .recv = vtpm_proxy_tpm_op_recv, 442 .send = vtpm_proxy_tpm_op_send, 443 .cancel = vtpm_proxy_tpm_op_cancel, 444 .status = vtpm_proxy_tpm_op_status, 445 .req_complete_mask = VTPM_PROXY_REQ_COMPLETE_FLAG, 446 .req_complete_val = VTPM_PROXY_REQ_COMPLETE_FLAG, 447 .req_canceled = vtpm_proxy_tpm_req_canceled, 448 .request_locality = vtpm_proxy_request_locality, 449 }; 450 451 /* 452 * Code related to the startup of the TPM 2 and startup of TPM 1.2 + 453 * retrieval of timeouts and durations. 454 */ 455 456 static void vtpm_proxy_work(struct work_struct *work) 457 { 458 struct proxy_dev *proxy_dev = container_of(work, struct proxy_dev, 459 work); 460 int rc; 461 462 rc = tpm_chip_register(proxy_dev->chip); 463 if (rc) 464 vtpm_proxy_fops_undo_open(proxy_dev); 465 else 466 proxy_dev->state |= STATE_REGISTERED_FLAG; 467 } 468 469 /* 470 * vtpm_proxy_work_stop: make sure the work has finished 471 * 472 * This function is useful when user space closed the fd 473 * while the driver still determines timeouts. 474 */ 475 static void vtpm_proxy_work_stop(struct proxy_dev *proxy_dev) 476 { 477 vtpm_proxy_fops_undo_open(proxy_dev); 478 flush_work(&proxy_dev->work); 479 } 480 481 /* 482 * vtpm_proxy_work_start: Schedule the work for TPM 1.2 & 2 initialization 483 */ 484 static inline void vtpm_proxy_work_start(struct proxy_dev *proxy_dev) 485 { 486 queue_work(workqueue, &proxy_dev->work); 487 } 488 489 /* 490 * Code related to creation and deletion of device pairs 491 */ 492 static struct proxy_dev *vtpm_proxy_create_proxy_dev(void) 493 { 494 struct proxy_dev *proxy_dev; 495 struct tpm_chip *chip; 496 int err; 497 498 proxy_dev = kzalloc(sizeof(*proxy_dev), GFP_KERNEL); 499 if (proxy_dev == NULL) 500 return ERR_PTR(-ENOMEM); 501 502 init_waitqueue_head(&proxy_dev->wq); 503 mutex_init(&proxy_dev->buf_lock); 504 INIT_WORK(&proxy_dev->work, vtpm_proxy_work); 505 506 chip = tpm_chip_alloc(NULL, &vtpm_proxy_tpm_ops); 507 if (IS_ERR(chip)) { 508 err = PTR_ERR(chip); 509 goto err_proxy_dev_free; 510 } 511 dev_set_drvdata(&chip->dev, proxy_dev); 512 513 proxy_dev->chip = chip; 514 515 return proxy_dev; 516 517 err_proxy_dev_free: 518 kfree(proxy_dev); 519 520 return ERR_PTR(err); 521 } 522 523 /* 524 * Undo what has been done in vtpm_create_proxy_dev 525 */ 526 static inline void vtpm_proxy_delete_proxy_dev(struct proxy_dev *proxy_dev) 527 { 528 put_device(&proxy_dev->chip->dev); /* frees chip */ 529 kfree(proxy_dev); 530 } 531 532 /* 533 * Create a /dev/tpm%d and 'server side' file descriptor pair 534 * 535 * Return: 536 * Returns file pointer on success, an error value otherwise 537 */ 538 static struct file *vtpm_proxy_create_device( 539 struct vtpm_proxy_new_dev *vtpm_new_dev) 540 { 541 struct proxy_dev *proxy_dev; 542 int rc, fd; 543 struct file *file; 544 545 if (vtpm_new_dev->flags & ~VTPM_PROXY_FLAGS_ALL) 546 return ERR_PTR(-EOPNOTSUPP); 547 548 proxy_dev = vtpm_proxy_create_proxy_dev(); 549 if (IS_ERR(proxy_dev)) 550 return ERR_CAST(proxy_dev); 551 552 proxy_dev->flags = vtpm_new_dev->flags; 553 554 /* setup an anonymous file for the server-side */ 555 fd = get_unused_fd_flags(O_RDWR); 556 if (fd < 0) { 557 rc = fd; 558 goto err_delete_proxy_dev; 559 } 560 561 file = anon_inode_getfile("[vtpms]", &vtpm_proxy_fops, proxy_dev, 562 O_RDWR); 563 if (IS_ERR(file)) { 564 rc = PTR_ERR(file); 565 goto err_put_unused_fd; 566 } 567 568 /* from now on we can unwind with put_unused_fd() + fput() */ 569 /* simulate an open() on the server side */ 570 vtpm_proxy_fops_open(file); 571 572 if (proxy_dev->flags & VTPM_PROXY_FLAG_TPM2) 573 proxy_dev->chip->flags |= TPM_CHIP_FLAG_TPM2; 574 575 vtpm_proxy_work_start(proxy_dev); 576 577 vtpm_new_dev->fd = fd; 578 vtpm_new_dev->major = MAJOR(proxy_dev->chip->dev.devt); 579 vtpm_new_dev->minor = MINOR(proxy_dev->chip->dev.devt); 580 vtpm_new_dev->tpm_num = proxy_dev->chip->dev_num; 581 582 return file; 583 584 err_put_unused_fd: 585 put_unused_fd(fd); 586 587 err_delete_proxy_dev: 588 vtpm_proxy_delete_proxy_dev(proxy_dev); 589 590 return ERR_PTR(rc); 591 } 592 593 /* 594 * Counter part to vtpm_create_device. 595 */ 596 static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev) 597 { 598 vtpm_proxy_work_stop(proxy_dev); 599 600 /* 601 * A client may hold the 'ops' lock, so let it know that the server 602 * side shuts down before we try to grab the 'ops' lock when 603 * unregistering the chip. 604 */ 605 vtpm_proxy_fops_undo_open(proxy_dev); 606 607 if (proxy_dev->state & STATE_REGISTERED_FLAG) 608 tpm_chip_unregister(proxy_dev->chip); 609 610 vtpm_proxy_delete_proxy_dev(proxy_dev); 611 } 612 613 /* 614 * Code related to the control device /dev/vtpmx 615 */ 616 617 /** 618 * vtpmx_ioc_new_dev - handler for the %VTPM_PROXY_IOC_NEW_DEV ioctl 619 * @file: /dev/vtpmx 620 * @ioctl: the ioctl number 621 * @arg: pointer to the struct vtpmx_proxy_new_dev 622 * 623 * Creates an anonymous file that is used by the process acting as a TPM to 624 * communicate with the client processes. The function will also add a new TPM 625 * device through which data is proxied to this TPM acting process. The caller 626 * will be provided with a file descriptor to communicate with the clients and 627 * major and minor numbers for the TPM device. 628 */ 629 static long vtpmx_ioc_new_dev(struct file *file, unsigned int ioctl, 630 unsigned long arg) 631 { 632 void __user *argp = (void __user *)arg; 633 struct vtpm_proxy_new_dev __user *vtpm_new_dev_p; 634 struct vtpm_proxy_new_dev vtpm_new_dev; 635 struct file *vtpm_file; 636 637 if (!capable(CAP_SYS_ADMIN)) 638 return -EPERM; 639 640 vtpm_new_dev_p = argp; 641 642 if (copy_from_user(&vtpm_new_dev, vtpm_new_dev_p, 643 sizeof(vtpm_new_dev))) 644 return -EFAULT; 645 646 vtpm_file = vtpm_proxy_create_device(&vtpm_new_dev); 647 if (IS_ERR(vtpm_file)) 648 return PTR_ERR(vtpm_file); 649 650 if (copy_to_user(vtpm_new_dev_p, &vtpm_new_dev, 651 sizeof(vtpm_new_dev))) { 652 put_unused_fd(vtpm_new_dev.fd); 653 fput(vtpm_file); 654 return -EFAULT; 655 } 656 657 fd_install(vtpm_new_dev.fd, vtpm_file); 658 return 0; 659 } 660 661 /* 662 * vtpmx_fops_ioctl: ioctl on /dev/vtpmx 663 * 664 * Return: 665 * Returns 0 on success, a negative error code otherwise. 666 */ 667 static long vtpmx_fops_ioctl(struct file *f, unsigned int ioctl, 668 unsigned long arg) 669 { 670 switch (ioctl) { 671 case VTPM_PROXY_IOC_NEW_DEV: 672 return vtpmx_ioc_new_dev(f, ioctl, arg); 673 default: 674 return -ENOIOCTLCMD; 675 } 676 } 677 678 #ifdef CONFIG_COMPAT 679 static long vtpmx_fops_compat_ioctl(struct file *f, unsigned int ioctl, 680 unsigned long arg) 681 { 682 return vtpmx_fops_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); 683 } 684 #endif 685 686 static const struct file_operations vtpmx_fops = { 687 .owner = THIS_MODULE, 688 .unlocked_ioctl = vtpmx_fops_ioctl, 689 #ifdef CONFIG_COMPAT 690 .compat_ioctl = vtpmx_fops_compat_ioctl, 691 #endif 692 .llseek = noop_llseek, 693 }; 694 695 static struct miscdevice vtpmx_miscdev = { 696 .minor = MISC_DYNAMIC_MINOR, 697 .name = "vtpmx", 698 .fops = &vtpmx_fops, 699 }; 700 701 static int vtpmx_init(void) 702 { 703 return misc_register(&vtpmx_miscdev); 704 } 705 706 static void vtpmx_cleanup(void) 707 { 708 misc_deregister(&vtpmx_miscdev); 709 } 710 711 static int __init vtpm_module_init(void) 712 { 713 int rc; 714 715 rc = vtpmx_init(); 716 if (rc) { 717 pr_err("couldn't create vtpmx device\n"); 718 return rc; 719 } 720 721 workqueue = create_workqueue("tpm-vtpm"); 722 if (!workqueue) { 723 pr_err("couldn't create workqueue\n"); 724 rc = -ENOMEM; 725 goto err_vtpmx_cleanup; 726 } 727 728 return 0; 729 730 err_vtpmx_cleanup: 731 vtpmx_cleanup(); 732 733 return rc; 734 } 735 736 static void __exit vtpm_module_exit(void) 737 { 738 destroy_workqueue(workqueue); 739 vtpmx_cleanup(); 740 } 741 742 module_init(vtpm_module_init); 743 module_exit(vtpm_module_exit); 744 745 MODULE_AUTHOR("Stefan Berger (stefanb@us.ibm.com)"); 746 MODULE_DESCRIPTION("vTPM Driver"); 747 MODULE_VERSION("0.1"); 748 MODULE_LICENSE("GPL"); 749