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 unsigned int vtpm_proxy_fops_poll(struct file *filp, poll_table *wait) 177 { 178 struct proxy_dev *proxy_dev = filp->private_data; 179 unsigned ret; 180 181 poll_wait(filp, &proxy_dev->wq, wait); 182 183 ret = POLLOUT; 184 185 mutex_lock(&proxy_dev->buf_lock); 186 187 if (proxy_dev->req_len) 188 ret |= POLLIN | POLLRDNORM; 189 190 if (!(proxy_dev->state & STATE_OPENED_FLAG)) 191 ret |= POLLHUP; 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_input_header *hdr = (struct tpm_input_header *)buf; 307 308 if (count < sizeof(struct tpm_input_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 int rc = 0; 339 340 if (count > sizeof(proxy_dev->buffer)) { 341 dev_err(&chip->dev, 342 "Invalid size in send: count=%zd, buffer size=%zd\n", 343 count, sizeof(proxy_dev->buffer)); 344 return -EIO; 345 } 346 347 if (!(proxy_dev->state & STATE_DRIVER_COMMAND) && 348 vtpm_proxy_is_driver_command(chip, buf, count)) 349 return -EFAULT; 350 351 mutex_lock(&proxy_dev->buf_lock); 352 353 if (!(proxy_dev->state & STATE_OPENED_FLAG)) { 354 mutex_unlock(&proxy_dev->buf_lock); 355 return -EPIPE; 356 } 357 358 proxy_dev->resp_len = 0; 359 360 proxy_dev->req_len = count; 361 memcpy(proxy_dev->buffer, buf, count); 362 363 proxy_dev->state &= ~STATE_WAIT_RESPONSE_FLAG; 364 365 mutex_unlock(&proxy_dev->buf_lock); 366 367 wake_up_interruptible(&proxy_dev->wq); 368 369 return rc; 370 } 371 372 static void vtpm_proxy_tpm_op_cancel(struct tpm_chip *chip) 373 { 374 /* not supported */ 375 } 376 377 static u8 vtpm_proxy_tpm_op_status(struct tpm_chip *chip) 378 { 379 struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); 380 381 if (proxy_dev->resp_len) 382 return VTPM_PROXY_REQ_COMPLETE_FLAG; 383 384 return 0; 385 } 386 387 static bool vtpm_proxy_tpm_req_canceled(struct tpm_chip *chip, u8 status) 388 { 389 struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); 390 bool ret; 391 392 mutex_lock(&proxy_dev->buf_lock); 393 394 ret = !(proxy_dev->state & STATE_OPENED_FLAG); 395 396 mutex_unlock(&proxy_dev->buf_lock); 397 398 return ret; 399 } 400 401 static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality) 402 { 403 struct tpm_buf buf; 404 int rc; 405 const struct tpm_output_header *header; 406 struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); 407 408 if (chip->flags & TPM_CHIP_FLAG_TPM2) 409 rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, 410 TPM2_CC_SET_LOCALITY); 411 else 412 rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, 413 TPM_ORD_SET_LOCALITY); 414 if (rc) 415 return rc; 416 tpm_buf_append_u8(&buf, locality); 417 418 proxy_dev->state |= STATE_DRIVER_COMMAND; 419 420 rc = tpm_transmit_cmd(chip, NULL, buf.data, tpm_buf_length(&buf), 0, 421 TPM_TRANSMIT_UNLOCKED | TPM_TRANSMIT_RAW, 422 "attempting to set locality"); 423 424 proxy_dev->state &= ~STATE_DRIVER_COMMAND; 425 426 if (rc < 0) { 427 locality = rc; 428 goto out; 429 } 430 431 header = (const struct tpm_output_header *)buf.data; 432 rc = be32_to_cpu(header->return_code); 433 if (rc) 434 locality = -1; 435 436 out: 437 tpm_buf_destroy(&buf); 438 439 return locality; 440 } 441 442 static const struct tpm_class_ops vtpm_proxy_tpm_ops = { 443 .flags = TPM_OPS_AUTO_STARTUP, 444 .recv = vtpm_proxy_tpm_op_recv, 445 .send = vtpm_proxy_tpm_op_send, 446 .cancel = vtpm_proxy_tpm_op_cancel, 447 .status = vtpm_proxy_tpm_op_status, 448 .req_complete_mask = VTPM_PROXY_REQ_COMPLETE_FLAG, 449 .req_complete_val = VTPM_PROXY_REQ_COMPLETE_FLAG, 450 .req_canceled = vtpm_proxy_tpm_req_canceled, 451 .request_locality = vtpm_proxy_request_locality, 452 }; 453 454 /* 455 * Code related to the startup of the TPM 2 and startup of TPM 1.2 + 456 * retrieval of timeouts and durations. 457 */ 458 459 static void vtpm_proxy_work(struct work_struct *work) 460 { 461 struct proxy_dev *proxy_dev = container_of(work, struct proxy_dev, 462 work); 463 int rc; 464 465 rc = tpm_chip_register(proxy_dev->chip); 466 if (rc) 467 vtpm_proxy_fops_undo_open(proxy_dev); 468 else 469 proxy_dev->state |= STATE_REGISTERED_FLAG; 470 } 471 472 /* 473 * vtpm_proxy_work_stop: make sure the work has finished 474 * 475 * This function is useful when user space closed the fd 476 * while the driver still determines timeouts. 477 */ 478 static void vtpm_proxy_work_stop(struct proxy_dev *proxy_dev) 479 { 480 vtpm_proxy_fops_undo_open(proxy_dev); 481 flush_work(&proxy_dev->work); 482 } 483 484 /* 485 * vtpm_proxy_work_start: Schedule the work for TPM 1.2 & 2 initialization 486 */ 487 static inline void vtpm_proxy_work_start(struct proxy_dev *proxy_dev) 488 { 489 queue_work(workqueue, &proxy_dev->work); 490 } 491 492 /* 493 * Code related to creation and deletion of device pairs 494 */ 495 static struct proxy_dev *vtpm_proxy_create_proxy_dev(void) 496 { 497 struct proxy_dev *proxy_dev; 498 struct tpm_chip *chip; 499 int err; 500 501 proxy_dev = kzalloc(sizeof(*proxy_dev), GFP_KERNEL); 502 if (proxy_dev == NULL) 503 return ERR_PTR(-ENOMEM); 504 505 init_waitqueue_head(&proxy_dev->wq); 506 mutex_init(&proxy_dev->buf_lock); 507 INIT_WORK(&proxy_dev->work, vtpm_proxy_work); 508 509 chip = tpm_chip_alloc(NULL, &vtpm_proxy_tpm_ops); 510 if (IS_ERR(chip)) { 511 err = PTR_ERR(chip); 512 goto err_proxy_dev_free; 513 } 514 dev_set_drvdata(&chip->dev, proxy_dev); 515 516 proxy_dev->chip = chip; 517 518 return proxy_dev; 519 520 err_proxy_dev_free: 521 kfree(proxy_dev); 522 523 return ERR_PTR(err); 524 } 525 526 /* 527 * Undo what has been done in vtpm_create_proxy_dev 528 */ 529 static inline void vtpm_proxy_delete_proxy_dev(struct proxy_dev *proxy_dev) 530 { 531 put_device(&proxy_dev->chip->dev); /* frees chip */ 532 kfree(proxy_dev); 533 } 534 535 /* 536 * Create a /dev/tpm%d and 'server side' file descriptor pair 537 * 538 * Return: 539 * Returns file pointer on success, an error value otherwise 540 */ 541 static struct file *vtpm_proxy_create_device( 542 struct vtpm_proxy_new_dev *vtpm_new_dev) 543 { 544 struct proxy_dev *proxy_dev; 545 int rc, fd; 546 struct file *file; 547 548 if (vtpm_new_dev->flags & ~VTPM_PROXY_FLAGS_ALL) 549 return ERR_PTR(-EOPNOTSUPP); 550 551 proxy_dev = vtpm_proxy_create_proxy_dev(); 552 if (IS_ERR(proxy_dev)) 553 return ERR_CAST(proxy_dev); 554 555 proxy_dev->flags = vtpm_new_dev->flags; 556 557 /* setup an anonymous file for the server-side */ 558 fd = get_unused_fd_flags(O_RDWR); 559 if (fd < 0) { 560 rc = fd; 561 goto err_delete_proxy_dev; 562 } 563 564 file = anon_inode_getfile("[vtpms]", &vtpm_proxy_fops, proxy_dev, 565 O_RDWR); 566 if (IS_ERR(file)) { 567 rc = PTR_ERR(file); 568 goto err_put_unused_fd; 569 } 570 571 /* from now on we can unwind with put_unused_fd() + fput() */ 572 /* simulate an open() on the server side */ 573 vtpm_proxy_fops_open(file); 574 575 if (proxy_dev->flags & VTPM_PROXY_FLAG_TPM2) 576 proxy_dev->chip->flags |= TPM_CHIP_FLAG_TPM2; 577 578 vtpm_proxy_work_start(proxy_dev); 579 580 vtpm_new_dev->fd = fd; 581 vtpm_new_dev->major = MAJOR(proxy_dev->chip->dev.devt); 582 vtpm_new_dev->minor = MINOR(proxy_dev->chip->dev.devt); 583 vtpm_new_dev->tpm_num = proxy_dev->chip->dev_num; 584 585 return file; 586 587 err_put_unused_fd: 588 put_unused_fd(fd); 589 590 err_delete_proxy_dev: 591 vtpm_proxy_delete_proxy_dev(proxy_dev); 592 593 return ERR_PTR(rc); 594 } 595 596 /* 597 * Counter part to vtpm_create_device. 598 */ 599 static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev) 600 { 601 vtpm_proxy_work_stop(proxy_dev); 602 603 /* 604 * A client may hold the 'ops' lock, so let it know that the server 605 * side shuts down before we try to grab the 'ops' lock when 606 * unregistering the chip. 607 */ 608 vtpm_proxy_fops_undo_open(proxy_dev); 609 610 if (proxy_dev->state & STATE_REGISTERED_FLAG) 611 tpm_chip_unregister(proxy_dev->chip); 612 613 vtpm_proxy_delete_proxy_dev(proxy_dev); 614 } 615 616 /* 617 * Code related to the control device /dev/vtpmx 618 */ 619 620 /** 621 * vtpmx_ioc_new_dev - handler for the %VTPM_PROXY_IOC_NEW_DEV ioctl 622 * @file: /dev/vtpmx 623 * @ioctl: the ioctl number 624 * @arg: pointer to the struct vtpmx_proxy_new_dev 625 * 626 * Creates an anonymous file that is used by the process acting as a TPM to 627 * communicate with the client processes. The function will also add a new TPM 628 * device through which data is proxied to this TPM acting process. The caller 629 * will be provided with a file descriptor to communicate with the clients and 630 * major and minor numbers for the TPM device. 631 */ 632 static long vtpmx_ioc_new_dev(struct file *file, unsigned int ioctl, 633 unsigned long arg) 634 { 635 void __user *argp = (void __user *)arg; 636 struct vtpm_proxy_new_dev __user *vtpm_new_dev_p; 637 struct vtpm_proxy_new_dev vtpm_new_dev; 638 struct file *vtpm_file; 639 640 if (!capable(CAP_SYS_ADMIN)) 641 return -EPERM; 642 643 vtpm_new_dev_p = argp; 644 645 if (copy_from_user(&vtpm_new_dev, vtpm_new_dev_p, 646 sizeof(vtpm_new_dev))) 647 return -EFAULT; 648 649 vtpm_file = vtpm_proxy_create_device(&vtpm_new_dev); 650 if (IS_ERR(vtpm_file)) 651 return PTR_ERR(vtpm_file); 652 653 if (copy_to_user(vtpm_new_dev_p, &vtpm_new_dev, 654 sizeof(vtpm_new_dev))) { 655 put_unused_fd(vtpm_new_dev.fd); 656 fput(vtpm_file); 657 return -EFAULT; 658 } 659 660 fd_install(vtpm_new_dev.fd, vtpm_file); 661 return 0; 662 } 663 664 /* 665 * vtpmx_fops_ioctl: ioctl on /dev/vtpmx 666 * 667 * Return: 668 * Returns 0 on success, a negative error code otherwise. 669 */ 670 static long vtpmx_fops_ioctl(struct file *f, unsigned int ioctl, 671 unsigned long arg) 672 { 673 switch (ioctl) { 674 case VTPM_PROXY_IOC_NEW_DEV: 675 return vtpmx_ioc_new_dev(f, ioctl, arg); 676 default: 677 return -ENOIOCTLCMD; 678 } 679 } 680 681 #ifdef CONFIG_COMPAT 682 static long vtpmx_fops_compat_ioctl(struct file *f, unsigned int ioctl, 683 unsigned long arg) 684 { 685 return vtpmx_fops_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); 686 } 687 #endif 688 689 static const struct file_operations vtpmx_fops = { 690 .owner = THIS_MODULE, 691 .unlocked_ioctl = vtpmx_fops_ioctl, 692 #ifdef CONFIG_COMPAT 693 .compat_ioctl = vtpmx_fops_compat_ioctl, 694 #endif 695 .llseek = noop_llseek, 696 }; 697 698 static struct miscdevice vtpmx_miscdev = { 699 .minor = MISC_DYNAMIC_MINOR, 700 .name = "vtpmx", 701 .fops = &vtpmx_fops, 702 }; 703 704 static int vtpmx_init(void) 705 { 706 return misc_register(&vtpmx_miscdev); 707 } 708 709 static void vtpmx_cleanup(void) 710 { 711 misc_deregister(&vtpmx_miscdev); 712 } 713 714 static int __init vtpm_module_init(void) 715 { 716 int rc; 717 718 rc = vtpmx_init(); 719 if (rc) { 720 pr_err("couldn't create vtpmx device\n"); 721 return rc; 722 } 723 724 workqueue = create_workqueue("tpm-vtpm"); 725 if (!workqueue) { 726 pr_err("couldn't create workqueue\n"); 727 rc = -ENOMEM; 728 goto err_vtpmx_cleanup; 729 } 730 731 return 0; 732 733 err_vtpmx_cleanup: 734 vtpmx_cleanup(); 735 736 return rc; 737 } 738 739 static void __exit vtpm_module_exit(void) 740 { 741 destroy_workqueue(workqueue); 742 vtpmx_cleanup(); 743 } 744 745 module_init(vtpm_module_init); 746 module_exit(vtpm_module_exit); 747 748 MODULE_AUTHOR("Stefan Berger (stefanb@us.ibm.com)"); 749 MODULE_DESCRIPTION("vTPM Driver"); 750 MODULE_VERSION("0.1"); 751 MODULE_LICENSE("GPL"); 752