1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * TPM 1.2 Driver for the TPMs that follow TIS v1.2 29 */ 30 31 #include <sys/devops.h> /* used by dev_ops */ 32 #include <sys/conf.h> /* used by dev_ops,cb_ops */ 33 #include <sys/modctl.h> /* for _init,_info,_fini,mod_* */ 34 #include <sys/ddi.h> /* used by all entry points */ 35 #include <sys/sunddi.h> /* used by all entry points */ 36 #include <sys/cmn_err.h> /* used for debug outputs */ 37 #include <sys/types.h> /* used by prop_op, ddi_prop_op */ 38 39 #include <sys/file.h> /* used by open, close */ 40 #include <sys/errno.h> /* used by open,close,read,write */ 41 #include <sys/open.h> /* used by open,close,read,write */ 42 #include <sys/cred.h> /* used by open,close,read */ 43 #include <sys/uio.h> /* used by read */ 44 #include <sys/stat.h> /* defines S_IFCHR */ 45 46 #include <sys/byteorder.h> /* for ntohs, ntohl, htons, htonl */ 47 48 #ifdef sun4v 49 #include <sys/hypervisor_api.h> 50 #include <sys/hsvc.h> 51 #endif 52 53 #include <tss/platform.h> /* from SUNWtss */ 54 #include <tss/tpm.h> /* from SUNWtss */ 55 56 #include "tpm_tis.h" 57 #include "tpm_ddi.h" 58 #include "tpm_duration.h" 59 60 #define TPM_HEADER_SIZE 10 61 typedef enum { 62 TPM_TAG_OFFSET = 0, 63 TPM_PARAMSIZE_OFFSET = 2, 64 TPM_RETURN_OFFSET = 6, 65 TPM_COMMAND_CODE_OFFSET = 6, 66 } TPM_HEADER_OFFSET_T; 67 68 /* 69 * This is to address some TPMs that does not report the correct duration 70 * and timeouts. In our experience with the production TPMs, we encountered 71 * time errors such as GetCapability command from TPM reporting the timeout 72 * and durations in milliseconds rather than microseconds. Some other TPMs 73 * report the value 0's 74 * 75 * Short Duration is based on section 11.3.4 of TIS speciciation, that 76 * TPM_GetCapability (short duration) commands should not be longer than 750ms 77 * and that section 11.3.7 states that TPM_ContinueSelfTest (medium duration) 78 * should not be longer than 1 second. 79 */ 80 #define DEFAULT_SHORT_DURATION 750000 81 #define DEFAULT_MEDIUM_DURATION 1000000 82 #define DEFAULT_LONG_DURATION 300000000 83 #define DEFAULT_TIMEOUT_A 750000 84 #define DEFAULT_TIMEOUT_B 2000000 85 #define DEFAULT_TIMEOUT_C 750000 86 #define DEFAULT_TIMEOUT_D 750000 87 88 /* 89 * In order to test the 'millisecond bug', we test if DURATIONS and TIMEOUTS 90 * are unreasonably low...such as 10 milliseconds (TPM isn't that fast). 91 * and 400 milliseconds for long duration 92 */ 93 #define TEN_MILLISECONDS 10000 /* 10 milliseconds */ 94 #define FOUR_HUNDRED_MILLISECONDS 400000 /* 4 hundred milliseconds */ 95 96 #define DEFAULT_LOCALITY 0 97 /* 98 * TPM input/output buffer offsets 99 */ 100 101 typedef enum { 102 TPM_CAP_RESPSIZE_OFFSET = 10, 103 TPM_CAP_RESP_OFFSET = 14, 104 } TPM_CAP_RET_OFFSET_T; 105 106 typedef enum { 107 TPM_CAP_TIMEOUT_A_OFFSET = 14, 108 TPM_CAP_TIMEOUT_B_OFFSET = 18, 109 TPM_CAP_TIMEOUT_C_OFFSET = 22, 110 TPM_CAP_TIMEOUT_D_OFFSET = 26, 111 } TPM_CAP_TIMEOUT_OFFSET_T; 112 113 typedef enum { 114 TPM_CAP_DUR_SHORT_OFFSET = 14, 115 TPM_CAP_DUR_MEDIUM_OFFSET = 18, 116 TPM_CAP_DUR_LONG_OFFSET = 22, 117 } TPM_CAP_DURATION_OFFSET_T; 118 119 #define TPM_CAP_VERSION_INFO_OFFSET 14 120 #define TPM_CAP_VERSION_INFO_SIZE 15 121 122 /* 123 * Internal TPM command functions 124 */ 125 static int itpm_command(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz); 126 static int tpm_get_timeouts(tpm_state_t *tpm); 127 static int tpm_get_duration(tpm_state_t *tpm); 128 static int tpm_get_version(tpm_state_t *tpm); 129 static int tpm_continue_selftest(tpm_state_t *tpm); 130 131 /* 132 * Internal TIS related functions 133 */ 134 static int tpm_wait_for_stat(tpm_state_t *, uint8_t, clock_t); 135 static clock_t tpm_get_ordinal_duration(tpm_state_t *, uint8_t); 136 static int tis_check_active_locality(tpm_state_t *, char); 137 static int tis_request_locality(tpm_state_t *, char); 138 static void tis_release_locality(tpm_state_t *, char, int); 139 static int tis_init(tpm_state_t *); 140 static uint8_t tis_get_status(tpm_state_t *); 141 static int tis_send_data(tpm_state_t *, uint8_t *, size_t); 142 static int tis_recv_data(tpm_state_t *, uint8_t *, size_t); 143 144 /* Auxilliary */ 145 static int receive_data(tpm_state_t *, uint8_t *, size_t); 146 static inline int tpm_io_lock(tpm_state_t *); 147 static inline void tpm_unlock(tpm_state_t *); 148 static void tpm_cleanup(dev_info_t *, tpm_state_t *); 149 150 /* 151 * Sun DDI/DDK entry points 152 */ 153 154 /* Declaration of autoconfig functions */ 155 static int tpm_attach(dev_info_t *, ddi_attach_cmd_t); 156 static int tpm_detach(dev_info_t *, ddi_detach_cmd_t); 157 static int tpm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 158 static int tpm_quiesce(dev_info_t *); 159 /* End of autoconfig functions */ 160 161 /* Declaration of driver entry point functions */ 162 static int tpm_open(dev_t *, int, int, cred_t *); 163 static int tpm_close(dev_t, int, int, cred_t *); 164 static int tpm_read(dev_t, struct uio *, cred_t *); 165 static int tpm_write(dev_t, struct uio *, cred_t *); 166 /* End of driver entry point functions */ 167 168 /* cb_ops structure */ 169 static struct cb_ops tpm_cb_ops = { 170 tpm_open, 171 tpm_close, 172 nodev, /* no strategy - nodev returns ENXIO */ 173 nodev, /* no print */ 174 nodev, /* no dump */ 175 tpm_read, 176 tpm_write, 177 nodev, /* no ioctl */ 178 nodev, /* no devmap */ 179 nodev, /* no mmap */ 180 nodev, /* no segmap */ 181 nochpoll, /* returns ENXIO for non-pollable devices */ 182 ddi_prop_op, 183 NULL, /* streamtab struc */ 184 D_MP, /* compatibility flags */ 185 CB_REV, /* cb_ops revision number */ 186 nodev, /* no aread */ 187 nodev /* no awrite */ 188 }; 189 190 /* dev_ops structure */ 191 static struct dev_ops tpm_dev_ops = { 192 DEVO_REV, 193 0, /* reference count */ 194 tpm_getinfo, 195 nulldev, /* no identify - nulldev returns 0 */ 196 nulldev, 197 tpm_attach, 198 tpm_detach, 199 nodev, /* no reset - nodev returns ENXIO */ 200 &tpm_cb_ops, 201 (struct bus_ops *)NULL, 202 nodev, /* no power */ 203 tpm_quiesce 204 }; 205 206 /* modldrv structure */ 207 static struct modldrv modldrv = { 208 &mod_driverops, /* Type: This is a driver */ 209 "TPM 1.2 driver", /* Name of the module. */ 210 &tpm_dev_ops 211 }; 212 213 /* modlinkage structure */ 214 static struct modlinkage tpm_ml = { 215 MODREV_1, 216 { &modldrv, NULL } 217 }; 218 219 220 #ifdef KCF_TPM_RNG_PROVIDER 221 222 #define IDENT_TPMRNG "TPM Random Number Generator" 223 224 #include <sys/crypto/common.h> 225 #include <sys/crypto/impl.h> 226 #include <sys/crypto/spi.h> 227 /* 228 * CSPI information (entry points, provider info, etc.) 229 */ 230 static void tpmrng_provider_status(crypto_provider_handle_t, uint_t *); 231 232 static crypto_control_ops_t tpmrng_control_ops = { 233 tpmrng_provider_status 234 }; 235 236 static int tpmrng_seed_random(crypto_provider_handle_t, crypto_session_id_t, 237 uchar_t *, size_t, uint_t, uint32_t, crypto_req_handle_t); 238 239 static int tpmrng_generate_random(crypto_provider_handle_t, 240 crypto_session_id_t, uchar_t *, size_t, crypto_req_handle_t); 241 242 static crypto_random_number_ops_t tpmrng_random_number_ops = { 243 tpmrng_seed_random, 244 tpmrng_generate_random 245 }; 246 247 static int tpmrng_ext_info(crypto_provider_handle_t, 248 crypto_provider_ext_info_t *, 249 crypto_req_handle_t); 250 251 static crypto_provider_management_ops_t tpmrng_extinfo_op = { 252 tpmrng_ext_info, 253 NULL, 254 NULL, 255 NULL 256 }; 257 258 static int tpmrng_register(tpm_state_t *); 259 static int tpmrng_unregister(tpm_state_t *); 260 261 static crypto_ops_t tpmrng_crypto_ops = { 262 .co_control_ops = &tpmrng_control_ops, 263 .co_random_ops = &tpmrng_random_number_ops, 264 .co_provider_ops = &tpmrng_extinfo_op 265 }; 266 267 static crypto_provider_info_t tpmrng_prov_info = { 268 CRYPTO_SPI_VERSION_2, 269 "TPM Random Number Provider", 270 CRYPTO_HW_PROVIDER, 271 NULL, 272 NULL, 273 &tpmrng_crypto_ops, 274 0, 275 NULL, 276 0, 277 NULL 278 }; 279 #endif /* KCF_TPM_RNG_PROVIDER */ 280 281 static void *statep = NULL; 282 283 /* 284 * Inline code to get exclusive lock on the TPM device and to make sure 285 * the device is not suspended. This grabs the primary TPM mutex (pm_mutex) 286 * and then checks the suspend status. If suspended, it will wait until 287 * the device is "resumed" before releasing the pm_mutex and continuing. 288 */ 289 #define TPM_EXCLUSIVE_LOCK(tpm) { \ 290 mutex_enter(&tpm->pm_mutex); \ 291 while (tpm->suspended) \ 292 cv_wait(&tpm->suspend_cv, &tpm->pm_mutex); \ 293 mutex_exit(&tpm->pm_mutex); } 294 295 /* 296 * TPM accessor functions 297 */ 298 #ifdef sun4v 299 300 extern uint64_t 301 hcall_tpm_get(uint64_t, uint64_t, uint64_t, uint64_t *); 302 303 extern uint64_t 304 hcall_tpm_put(uint64_t, uint64_t, uint64_t, uint64_t); 305 306 static inline uint8_t 307 tpm_get8(tpm_state_t *tpm, unsigned long offset) 308 { 309 uint64_t value; 310 311 ASSERT(tpm != NULL); 312 (void) hcall_tpm_get(tpm->locality, offset, sizeof (uint8_t), &value); 313 return ((uint8_t)value); 314 } 315 316 static inline uint32_t 317 tpm_get32(tpm_state_t *tpm, unsigned long offset) 318 { 319 uint64_t value; 320 321 ASSERT(tpm != NULL); 322 (void) hcall_tpm_get(tpm->locality, offset, sizeof (uint32_t), &value); 323 return ((uint32_t)value); 324 } 325 326 static inline void 327 tpm_put8(tpm_state_t *tpm, unsigned long offset, uint8_t value) 328 { 329 ASSERT(tpm != NULL); 330 (void) hcall_tpm_put(tpm->locality, offset, sizeof (uint8_t), value); 331 } 332 333 #else 334 335 static inline uint8_t 336 tpm_get8(tpm_state_t *tpm, unsigned long offset) 337 { 338 ASSERT(tpm != NULL); 339 340 return (ddi_get8(tpm->handle, 341 (uint8_t *)(TPM_LOCALITY_OFFSET(tpm->locality) | 342 (uintptr_t)tpm->addr + offset))); 343 } 344 345 static inline uint32_t 346 tpm_get32(tpm_state_t *tpm, unsigned long offset) 347 { 348 ASSERT(tpm != NULL); 349 return (ddi_get32(tpm->handle, 350 (uint32_t *)(TPM_LOCALITY_OFFSET(tpm->locality) | 351 (uintptr_t)tpm->addr + offset))); 352 } 353 354 static inline void 355 tpm_put8(tpm_state_t *tpm, unsigned long offset, uint8_t value) 356 { 357 ASSERT(tpm != NULL); 358 ddi_put8(tpm->handle, 359 (uint8_t *)(TPM_LOCALITY_OFFSET(tpm->locality) | 360 (uintptr_t)tpm->addr + offset), value); 361 } 362 363 #endif /* sun4v */ 364 365 /* 366 * TPM commands to get the TPM's properties, e.g.,timeout 367 */ 368 /*ARGSUSED*/ 369 static int 370 tpm_quiesce(dev_info_t *dip) 371 { 372 return (DDI_SUCCESS); 373 } 374 375 static uint32_t 376 load32(uchar_t *ptr, uint32_t offset) 377 { 378 uint32_t val; 379 bcopy(ptr + offset, &val, sizeof (uint32_t)); 380 381 return (ntohl(val)); 382 } 383 384 /* 385 * Get the actual timeouts supported by the TPM by issuing TPM_GetCapability 386 * with the subcommand TPM_CAP_PROP_TIS_TIMEOUT 387 * TPM_GetCapability (TPM Main Part 3 Rev. 94, pg.38) 388 */ 389 static int 390 tpm_get_timeouts(tpm_state_t *tpm) 391 { 392 int ret; 393 uint32_t timeout; /* in milliseconds */ 394 uint32_t len; 395 396 /* The buffer size (30) needs room for 4 timeout values (uint32_t) */ 397 uint8_t buf[30] = { 398 0, 193, /* TPM_TAG_RQU_COMMAND */ 399 0, 0, 0, 22, /* paramsize in bytes */ 400 0, 0, 0, 101, /* TPM_ORD_GetCapability */ 401 0, 0, 0, 5, /* TPM_CAP_Prop */ 402 0, 0, 0, 4, /* SUB_CAP size in bytes */ 403 0, 0, 1, 21 /* TPM_CAP_PROP_TIS_TIMEOUT(0x115) */ 404 }; 405 char *myname = "tpm_get_timeout"; 406 407 ASSERT(tpm != NULL); 408 409 ret = itpm_command(tpm, buf, sizeof (buf)); 410 if (ret != DDI_SUCCESS) { 411 #ifdef DEBUG 412 cmn_err(CE_WARN, "!%s: itpm_command failed", myname); 413 #endif 414 return (DDI_FAILURE); 415 } 416 417 /* 418 * Get the length of the returned buffer 419 * Make sure that there are 4 timeout values returned 420 * length of the capability response is stored in data[10-13] 421 * Also the TPM is in network byte order 422 */ 423 len = load32(buf, TPM_CAP_RESPSIZE_OFFSET); 424 if (len != 4 * sizeof (uint32_t)) { 425 #ifdef DEBUG 426 cmn_err(CE_WARN, "!%s: capability response size should be %d" 427 "instead len = %d", 428 myname, (int)(4 * sizeof (uint32_t)), (int)len); 429 #endif 430 return (DDI_FAILURE); 431 } 432 433 /* Get the four timeout's: a,b,c,d (they are 4 bytes long each) */ 434 timeout = load32(buf, TPM_CAP_TIMEOUT_A_OFFSET); 435 if (timeout == 0) { 436 timeout = DEFAULT_TIMEOUT_A; 437 } else if (timeout < TEN_MILLISECONDS) { 438 /* timeout is in millisecond range (should be microseconds) */ 439 timeout *= 1000; 440 } 441 tpm->timeout_a = drv_usectohz(timeout); 442 443 timeout = load32(buf, TPM_CAP_TIMEOUT_B_OFFSET); 444 if (timeout == 0) { 445 timeout = DEFAULT_TIMEOUT_B; 446 } else if (timeout < TEN_MILLISECONDS) { 447 /* timeout is in millisecond range (should be microseconds) */ 448 timeout *= 1000; 449 } 450 tpm->timeout_b = drv_usectohz(timeout); 451 452 timeout = load32(buf, TPM_CAP_TIMEOUT_C_OFFSET); 453 if (timeout == 0) { 454 timeout = DEFAULT_TIMEOUT_C; 455 } else if (timeout < TEN_MILLISECONDS) { 456 /* timeout is in millisecond range (should be microseconds) */ 457 timeout *= 1000; 458 } 459 tpm->timeout_c = drv_usectohz(timeout); 460 461 timeout = load32(buf, TPM_CAP_TIMEOUT_D_OFFSET); 462 if (timeout == 0) { 463 timeout = DEFAULT_TIMEOUT_D; 464 } else if (timeout < TEN_MILLISECONDS) { 465 /* timeout is in millisecond range (should be microseconds) */ 466 timeout *= 1000; 467 } 468 tpm->timeout_d = drv_usectohz(timeout); 469 470 return (DDI_SUCCESS); 471 } 472 473 /* 474 * Get the actual timeouts supported by the TPM by issuing TPM_GetCapability 475 * with the subcommand TPM_CAP_PROP_TIS_DURATION 476 * TPM_GetCapability (TPM Main Part 3 Rev. 94, pg.38) 477 */ 478 static int 479 tpm_get_duration(tpm_state_t *tpm) { 480 int ret; 481 uint32_t duration; 482 uint32_t len; 483 uint8_t buf[30] = { 484 0, 193, /* TPM_TAG_RQU_COMMAND */ 485 0, 0, 0, 22, /* paramsize in bytes */ 486 0, 0, 0, 101, /* TPM_ORD_GetCapability */ 487 0, 0, 0, 5, /* TPM_CAP_Prop */ 488 0, 0, 0, 4, /* SUB_CAP size in bytes */ 489 0, 0, 1, 32 /* TPM_CAP_PROP_TIS_DURATION(0x120) */ 490 }; 491 char *myname = "tpm_get_duration"; 492 493 ASSERT(tpm != NULL); 494 495 ret = itpm_command(tpm, buf, sizeof (buf)); 496 if (ret != DDI_SUCCESS) { 497 #ifdef DEBUG 498 cmn_err(CE_WARN, "!%s: itpm_command failed with ret code: 0x%x", 499 myname, ret); 500 #endif 501 return (DDI_FAILURE); 502 } 503 504 /* 505 * Get the length of the returned buffer 506 * Make sure that there are 3 duration values (S,M,L: in that order) 507 * length of the capability response is stored in data[10-13] 508 * Also the TPM is in network byte order 509 */ 510 len = load32(buf, TPM_CAP_RESPSIZE_OFFSET); 511 if (len != 3 * sizeof (uint32_t)) { 512 #ifdef DEBUG 513 cmn_err(CE_WARN, "!%s: capability response should be %d, " 514 "instead, it's %d", 515 myname, (int)(3 * sizeof (uint32_t)), (int)len); 516 #endif 517 return (DDI_FAILURE); 518 } 519 520 duration = load32(buf, TPM_CAP_DUR_SHORT_OFFSET); 521 if (duration == 0) { 522 duration = DEFAULT_SHORT_DURATION; 523 } else if (duration < TEN_MILLISECONDS) { 524 duration *= 1000; 525 } 526 tpm->duration[TPM_SHORT] = drv_usectohz(duration); 527 528 duration = load32(buf, TPM_CAP_DUR_MEDIUM_OFFSET); 529 if (duration == 0) { 530 duration = DEFAULT_MEDIUM_DURATION; 531 } else if (duration < TEN_MILLISECONDS) { 532 duration *= 1000; 533 } 534 tpm->duration[TPM_MEDIUM] = drv_usectohz(duration); 535 536 duration = load32(buf, TPM_CAP_DUR_LONG_OFFSET); 537 if (duration == 0) { 538 duration = DEFAULT_LONG_DURATION; 539 } else if (duration < FOUR_HUNDRED_MILLISECONDS) { 540 duration *= 1000; 541 } 542 tpm->duration[TPM_LONG] = drv_usectohz(duration); 543 544 /* Just make the undefined duration be the same as the LONG */ 545 tpm->duration[TPM_UNDEFINED] = tpm->duration[TPM_LONG]; 546 547 return (DDI_SUCCESS); 548 } 549 550 /* 551 * Get the actual timeouts supported by the TPM by issuing TPM_GetCapability 552 * with the subcommand TPM_CAP_PROP_TIS_DURATION 553 * TPM_GetCapability (TPM Main Part 3 Rev. 94, pg.38) 554 */ 555 static int 556 tpm_get_version(tpm_state_t *tpm) { 557 int ret; 558 uint32_t len; 559 char vendorId[5]; 560 /* If this buf is too small, the "vendor specific" data won't fit */ 561 uint8_t buf[64] = { 562 0, 193, /* TPM_TAG_RQU_COMMAND */ 563 0, 0, 0, 18, /* paramsize in bytes */ 564 0, 0, 0, 101, /* TPM_ORD_GetCapability */ 565 0, 0, 0, 0x1A, /* TPM_CAP_VERSION_VAL */ 566 0, 0, 0, 0, /* SUB_CAP size in bytes */ 567 }; 568 char *myname = "tpm_get_version"; 569 570 ASSERT(tpm != NULL); 571 572 ret = itpm_command(tpm, buf, sizeof (buf)); 573 if (ret != DDI_SUCCESS) { 574 #ifdef DEBUG 575 cmn_err(CE_WARN, "!%s: itpm_command failed with ret code: 0x%x", 576 myname, ret); 577 #endif 578 return (DDI_FAILURE); 579 } 580 581 /* 582 * Get the length of the returned buffer. 583 */ 584 len = load32(buf, TPM_CAP_RESPSIZE_OFFSET); 585 if (len < TPM_CAP_VERSION_INFO_SIZE) { 586 #ifdef DEBUG 587 cmn_err(CE_WARN, "!%s: capability response should be greater" 588 " than %d, instead, it's %d", 589 myname, TPM_CAP_VERSION_INFO_SIZE, len); 590 #endif 591 return (DDI_FAILURE); 592 } 593 594 bcopy(buf + TPM_CAP_VERSION_INFO_OFFSET, &tpm->vers_info, 595 TPM_CAP_VERSION_INFO_SIZE); 596 597 bcopy(tpm->vers_info.tpmVendorID, vendorId, 598 sizeof (tpm->vers_info.tpmVendorID)); 599 vendorId[4] = '\0'; 600 601 cmn_err(CE_NOTE, "!TPM found: Ver %d.%d, Rev %d.%d, " 602 "SpecLevel %d, errataRev %d, VendorId '%s'", 603 tpm->vers_info.version.major, /* Version */ 604 tpm->vers_info.version.minor, 605 tpm->vers_info.version.revMajor, /* Revision */ 606 tpm->vers_info.version.revMinor, 607 (int)ntohs(tpm->vers_info.specLevel), 608 tpm->vers_info.errataRev, 609 vendorId); 610 611 /* 612 * This driver only supports TPM Version 1.2 613 */ 614 if (tpm->vers_info.version.major != 1 && 615 tpm->vers_info.version.minor != 2) { 616 cmn_err(CE_WARN, "!%s: Unsupported TPM version (%d.%d)", 617 myname, 618 tpm->vers_info.version.major, /* Version */ 619 tpm->vers_info.version.minor); 620 return (DDI_FAILURE); 621 } 622 623 return (DDI_SUCCESS); 624 } 625 626 /* 627 * To prevent the TPM from complaining that certain functions are not tested 628 * we run this command when the driver attaches. 629 * For details see Section 4.2 of TPM Main Part 3 Command Specification 630 */ 631 static int 632 tpm_continue_selftest(tpm_state_t *tpm) { 633 int ret; 634 uint8_t buf[10] = { 635 0, 193, /* TPM_TAG_RQU COMMAND */ 636 0, 0, 0, 10, /* paramsize in bytes */ 637 0, 0, 0, 83 /* TPM_ORD_ContinueSelfTest */ 638 }; 639 char *myname = "tpm_continue_selftest"; 640 641 /* Need a longer timeout */ 642 ret = itpm_command(tpm, buf, sizeof (buf)); 643 if (ret != DDI_SUCCESS) { 644 #ifdef DEBUG 645 cmn_err(CE_WARN, "!%s: itpm_command failed", myname); 646 #endif 647 return (DDI_FAILURE); 648 } 649 650 return (DDI_SUCCESS); 651 } 652 /* 653 * Auxilary Functions 654 */ 655 656 /* 657 * Find out how long we should wait for the TPM command to complete a command 658 */ 659 static clock_t 660 tpm_get_ordinal_duration(tpm_state_t *tpm, uint8_t ordinal) 661 { 662 uint8_t index; 663 char *myname = "tpm_get_ordinal_duration"; 664 665 ASSERT(tpm != NULL); 666 667 /* Default and failure case for IFX */ 668 /* Is it a TSC_ORDINAL? */ 669 if (ordinal & TSC_ORDINAL_MASK) { 670 if (ordinal > TSC_ORDINAL_MAX) { 671 #ifdef DEBUG 672 cmn_err(CE_WARN, 673 "!%s: tsc ordinal: %d exceeds MAX: %d", 674 myname, ordinal, TSC_ORDINAL_MAX); 675 #endif 676 return (0); 677 } 678 index = tsc_ords_duration[ordinal]; 679 } else { 680 if (ordinal > TPM_ORDINAL_MAX) { 681 #ifdef DEBUG 682 cmn_err(CE_WARN, 683 "!%s: ordinal %d exceeds MAX: %d", 684 myname, ordinal, TPM_ORDINAL_MAX); 685 #endif 686 return (0); 687 } 688 index = tpm_ords_duration[ordinal]; 689 } 690 691 if (index > TPM_DURATION_MAX_IDX) { 692 #ifdef DEBUG 693 cmn_err(CE_WARN, "!%s: duration index '%d' is out of bounds", 694 myname, index); 695 #endif 696 return (0); 697 } 698 return (tpm->duration[index]); 699 } 700 701 /* 702 * Internal TPM Transmit Function: 703 * Calls implementation specific sendto and receive 704 * The code assumes that the buffer is in network byte order 705 */ 706 static int 707 itpm_command(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz) 708 { 709 int ret; 710 uint32_t count; 711 char *myname = "itpm_command"; 712 713 ASSERT(tpm != NULL && buf != NULL); 714 715 /* The byte order is network byte order so convert it */ 716 count = load32(buf, TPM_PARAMSIZE_OFFSET); 717 718 if (count == 0 || (count > bufsiz)) { 719 #ifdef DEBUG 720 cmn_err(CE_WARN, "!%s: invalid byte count value " 721 "(%d > bufsiz %d)", myname, (int)count, (int)bufsiz); 722 #endif 723 return (DDI_FAILURE); 724 } 725 726 /* Send the command */ 727 ret = tis_send_data(tpm, buf, count); 728 if (ret != DDI_SUCCESS) { 729 #ifdef DEBUG 730 cmn_err(CE_WARN, "!%s: tis_send_data failed with error %x", 731 myname, ret); 732 #endif 733 return (DDI_FAILURE); 734 } 735 736 /* 737 * Now receive the data from the tpm 738 * Should at least receive "the common" 10 bytes (TPM_HEADER_SIZE) 739 */ 740 ret = tis_recv_data(tpm, buf, bufsiz); 741 if (ret < TPM_HEADER_SIZE) { 742 #ifdef DEBUG 743 cmn_err(CE_WARN, "!%s: tis_recv_data failed", myname); 744 #endif 745 return (DDI_FAILURE); 746 } 747 748 /* Check the return code */ 749 ret = load32(buf, TPM_RETURN_OFFSET); 750 if (ret != TPM_SUCCESS) { 751 if (ret == TPM_E_DEACTIVATED) 752 cmn_err(CE_WARN, "!%s: TPM is deactivated", myname); 753 else if (ret == TPM_E_DISABLED) 754 cmn_err(CE_WARN, "!%s: TPM is disabled", myname); 755 else 756 cmn_err(CE_WARN, "!%s: TPM error code 0x%0x", 757 myname, ret); 758 return (DDI_FAILURE); 759 } 760 761 return (DDI_SUCCESS); 762 } 763 764 /* 765 * Whenever the driver wants to write to the DATA_IO register, it must need 766 * to figure out the burstcount. This is the amount of bytes it can write 767 * before having to wait for long LPC bus cycle 768 * 769 * Returns: 0 if error, burst count if sucess 770 */ 771 static uint16_t 772 tpm_get_burstcount(tpm_state_t *tpm) { 773 clock_t stop; 774 uint16_t burstcnt; 775 776 ASSERT(tpm != NULL); 777 778 /* 779 * Spec says timeout should be TIMEOUT_D 780 * burst count is TPM_STS bits 8..23 781 */ 782 stop = ddi_get_lbolt() + tpm->timeout_d; 783 do { 784 /* 785 * burstcnt is stored as a little endian value 786 * 'ntohs' doesn't work since the value is not word-aligned 787 */ 788 burstcnt = tpm_get8(tpm, TPM_STS + 1); 789 burstcnt += tpm_get8(tpm, TPM_STS + 2) << 8; 790 791 if (burstcnt) 792 return (burstcnt); 793 794 delay(tpm->timeout_poll); 795 } while (ddi_get_lbolt() < stop); 796 797 return (0); 798 } 799 800 /* 801 * Writing 1 to TPM_STS_CMD_READY bit in TPM_STS will do the following: 802 * 1. The TPM will clears IO buffers if any 803 * 2. The TPM will enters either Idle or Ready state within TIMEOUT_B 804 * (checked in the calling function) 805 */ 806 static void 807 tpm_set_ready(tpm_state_t *tpm) { 808 tpm_put8(tpm, TPM_STS, TPM_STS_CMD_READY); 809 } 810 811 static int 812 receive_data(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz) { 813 int size = 0; 814 int retried = 0; 815 uint8_t stsbits; 816 817 /* A number of consecutive bytes that can be written to TPM */ 818 uint16_t burstcnt; 819 820 ASSERT(tpm != NULL && buf != NULL); 821 retry: 822 while (size < bufsiz && 823 (tpm_wait_for_stat(tpm, 824 (TPM_STS_DATA_AVAIL|TPM_STS_VALID), 825 tpm->timeout_c) == DDI_SUCCESS)) { 826 /* 827 * Burstcount should be available within TIMEOUT_D 828 * after STS is set to valid 829 * burstcount is dynamic, so have to get it each time 830 */ 831 burstcnt = tpm_get_burstcount(tpm); 832 for (; burstcnt > 0 && size < bufsiz; burstcnt--) { 833 buf[size++] = tpm_get8(tpm, TPM_DATA_FIFO); 834 } 835 } 836 stsbits = tis_get_status(tpm); 837 /* check to see if we need to retry (just once) */ 838 if (size < bufsiz && !(stsbits & TPM_STS_DATA_AVAIL) && retried == 0) { 839 /* issue responseRetry (TIS 1.2 pg 54) */ 840 tpm_put8(tpm, TPM_STS, TPM_STS_RESPONSE_RETRY); 841 /* update the retry counter so we only retry once */ 842 retried++; 843 /* reset the size to 0 and reread the entire response */ 844 size = 0; 845 goto retry; 846 } 847 return (size); 848 } 849 850 /* Receive the data from the TPM */ 851 static int 852 tis_recv_data(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz) { 853 int ret; 854 int size = 0; 855 uint32_t expected, status; 856 uint32_t cmdresult; 857 char *myname = "tis_recv_data"; 858 859 ASSERT(tpm != NULL && buf != NULL); 860 861 if (bufsiz < TPM_HEADER_SIZE) { 862 /* There should be at least tag, paramsize, return code */ 863 #ifdef DEBUG 864 cmn_err(CE_WARN, "!%s: received data should contain at least " 865 "the header which is %d bytes long", 866 myname, TPM_HEADER_SIZE); 867 #endif 868 goto OUT; 869 } 870 871 /* Read tag(2 bytes), paramsize(4), and result(4) */ 872 size = receive_data(tpm, buf, TPM_HEADER_SIZE); 873 if (size < TPM_HEADER_SIZE) { 874 #ifdef DEBUG 875 cmn_err(CE_WARN, "!%s: recv TPM_HEADER failed, size = %d", 876 myname, size); 877 #endif 878 goto OUT; 879 } 880 881 cmdresult = load32(buf, TPM_RETURN_OFFSET); 882 883 /* Get 'paramsize'(4 bytes)--it includes tag and paramsize */ 884 expected = load32(buf, TPM_PARAMSIZE_OFFSET); 885 if (expected > bufsiz) { 886 #ifdef DEBUG 887 cmn_err(CE_WARN, "!%s: paramSize is bigger " 888 "than the requested size: paramSize=%d bufsiz=%d result=%d", 889 myname, (int)expected, (int)bufsiz, cmdresult); 890 #endif 891 goto OUT; 892 } 893 894 /* Read in the rest of the data from the TPM */ 895 size += receive_data(tpm, (uint8_t *)&buf[TPM_HEADER_SIZE], 896 expected - TPM_HEADER_SIZE); 897 if (size < expected) { 898 #ifdef DEBUG 899 cmn_err(CE_WARN, "!%s: received data length (%d) " 900 "is less than expected (%d)", myname, size, expected); 901 #endif 902 goto OUT; 903 } 904 905 /* The TPM MUST set the state to stsValid within TIMEOUT_C */ 906 ret = tpm_wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c); 907 908 status = tis_get_status(tpm); 909 if (ret != DDI_SUCCESS) { 910 #ifdef DEBUG 911 cmn_err(CE_WARN, "!%s: TPM didn't set stsValid after its I/O: " 912 "status = 0x%08X", myname, status); 913 #endif 914 goto OUT; 915 } 916 917 /* There is still more data? */ 918 if (status & TPM_STS_DATA_AVAIL) { 919 #ifdef DEBUG 920 cmn_err(CE_WARN, "!%s: TPM_STS_DATA_AVAIL is set:0x%08X", 921 myname, status); 922 #endif 923 goto OUT; 924 } 925 926 /* 927 * Release the control of the TPM after we are done with it 928 * it...so others can also get a chance to send data 929 */ 930 tis_release_locality(tpm, tpm->locality, 0); 931 932 OUT: 933 tpm_set_ready(tpm); 934 tis_release_locality(tpm, tpm->locality, 0); 935 return (size); 936 } 937 938 /* 939 * Send the data (TPM commands) to the Data IO register 940 */ 941 static int 942 tis_send_data(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz) { 943 int ret; 944 uint8_t status; 945 uint16_t burstcnt; 946 uint32_t ordinal; 947 size_t count = 0; 948 char *myname = "tis_send_data"; 949 950 ASSERT(tpm != NULL && buf != NULL); 951 952 if (bufsiz == 0) { 953 #ifdef DEBUG 954 cmn_err(CE_WARN, "!%s: bufsiz arg is zero", myname); 955 #endif 956 return (DDI_FAILURE); 957 } 958 959 /* Put the TPM in ready state */ 960 status = tis_get_status(tpm); 961 962 if (!(status & TPM_STS_CMD_READY)) { 963 tpm_set_ready(tpm); 964 ret = tpm_wait_for_stat(tpm, TPM_STS_CMD_READY, tpm->timeout_b); 965 if (ret != DDI_SUCCESS) { 966 #ifdef DEBUG 967 cmn_err(CE_WARN, "!%s: could not put the TPM " 968 "in the command ready state:" 969 "tpm_wait_for_stat returned error", 970 myname); 971 #endif 972 goto FAIL; 973 } 974 } 975 976 /* 977 * Now we are ready to send command 978 * TPM's burstcount dictates how many bytes we can write at a time 979 * Burstcount is dynamic if INTF_CAPABILITY for static burstcount is 980 * not set. 981 */ 982 while (count < bufsiz - 1) { 983 burstcnt = tpm_get_burstcount(tpm); 984 if (burstcnt == 0) { 985 #ifdef DEBUG 986 cmn_err(CE_WARN, "!%s: tpm_get_burstcnt returned error", 987 myname); 988 #endif 989 ret = DDI_FAILURE; 990 goto FAIL; 991 } 992 993 for (; burstcnt > 0 && count < bufsiz - 1; burstcnt--) { 994 tpm_put8(tpm, TPM_DATA_FIFO, buf[count]); 995 count++; 996 } 997 /* Wait for TPM to indicate that it is ready for more data */ 998 ret = tpm_wait_for_stat(tpm, 999 (TPM_STS_VALID | TPM_STS_DATA_EXPECT), tpm->timeout_c); 1000 if (ret != DDI_SUCCESS) { 1001 #ifdef DEBUG 1002 cmn_err(CE_WARN, "!%s: TPM didn't enter STS_VALID " 1003 "state", myname); 1004 #endif 1005 goto FAIL; 1006 } 1007 } 1008 /* We can't exit the loop above unless we wrote bufsiz-1 bytes */ 1009 1010 /* Write last byte */ 1011 tpm_put8(tpm, TPM_DATA_FIFO, buf[count]); 1012 count++; 1013 1014 /* Wait for the TPM to enter Valid State */ 1015 ret = tpm_wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c); 1016 if (ret == DDI_FAILURE) { 1017 #ifdef DEBUG 1018 cmn_err(CE_WARN, "!%s: tpm didn't enter STS_VALID state", 1019 myname); 1020 #endif 1021 goto FAIL; 1022 } 1023 1024 status = tis_get_status(tpm); 1025 /* The TPM should NOT be expecing more data at this point */ 1026 if ((status & TPM_STS_DATA_EXPECT) != 0) { 1027 #ifdef DEBUG 1028 cmn_err(CE_WARN, "!%s: DATA_EXPECT should not be set after " 1029 "writing the last byte: status=0x%08X", myname, status); 1030 #endif 1031 ret = DDI_FAILURE; 1032 goto FAIL; 1033 } 1034 1035 /* 1036 * Final step: Writing TPM_STS_GO to TPM_STS 1037 * register will actually send the command. 1038 */ 1039 tpm_put8(tpm, TPM_STS, TPM_STS_GO); 1040 1041 /* Ordinal/Command_code is located in buf[6..9] */ 1042 ordinal = load32(buf, TPM_COMMAND_CODE_OFFSET); 1043 1044 ret = tpm_wait_for_stat(tpm, TPM_STS_DATA_AVAIL | TPM_STS_VALID, 1045 tpm_get_ordinal_duration(tpm, ordinal)); 1046 if (ret == DDI_FAILURE) { 1047 #ifdef DEBUG 1048 status = tis_get_status(tpm); 1049 if (!(status & TPM_STS_DATA_AVAIL) || 1050 !(status & TPM_STS_VALID)) { 1051 cmn_err(CE_WARN, "!%s: TPM not ready or valid " 1052 "(ordinal = %d timeout = %ld status = 0x%0x)", 1053 myname, ordinal, 1054 tpm_get_ordinal_duration(tpm, ordinal), 1055 status); 1056 } else { 1057 cmn_err(CE_WARN, "!%s: tpm_wait_for_stat " 1058 "(DATA_AVAIL | VALID) failed status = 0x%0X", 1059 myname, status); 1060 } 1061 #endif 1062 goto FAIL; 1063 } 1064 return (DDI_SUCCESS); 1065 1066 FAIL: 1067 tpm_set_ready(tpm); 1068 tis_release_locality(tpm, tpm->locality, 0); 1069 return (ret); 1070 } 1071 1072 /* 1073 * Clear XrequestUse and Xactivelocality, where X is the current locality 1074 */ 1075 static void 1076 tis_release_locality(tpm_state_t *tpm, char locality, int force) { 1077 ASSERT(tpm != NULL && locality >= 0 && locality < 5); 1078 1079 if (force || 1080 (tpm_get8(tpm, TPM_ACCESS) & 1081 (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == 1082 (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) { 1083 /* 1084 * Writing 1 to active locality bit in TPM_ACCESS 1085 * register reliquishes the control of the locality 1086 */ 1087 tpm_put8(tpm, TPM_ACCESS, TPM_ACCESS_ACTIVE_LOCALITY); 1088 } 1089 } 1090 1091 /* 1092 * Checks whether the given locality is active 1093 * Use TPM_ACCESS register and the masks TPM_ACCESS_VALID,TPM_ACTIVE_LOCALITY 1094 */ 1095 static int 1096 tis_check_active_locality(tpm_state_t *tpm, char locality) { 1097 uint8_t access_bits; 1098 uint8_t old_locality; 1099 1100 ASSERT(tpm != NULL && locality >= 0 && locality < 5); 1101 1102 old_locality = tpm->locality; 1103 tpm->locality = locality; 1104 1105 /* Just check to see if the requested locality works */ 1106 access_bits = tpm_get8(tpm, TPM_ACCESS); 1107 access_bits &= (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID); 1108 1109 /* this was just a check, not a request to switch */ 1110 tpm->locality = old_locality; 1111 1112 if (access_bits == (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { 1113 return (DDI_SUCCESS); 1114 } else { 1115 return (DDI_FAILURE); 1116 } 1117 } 1118 1119 /* Request the TPM to be in the given locality */ 1120 static int 1121 tis_request_locality(tpm_state_t *tpm, char locality) { 1122 clock_t timeout; 1123 int ret; 1124 char *myname = "tis_request_locality"; 1125 1126 ASSERT(tpm != NULL && locality >= 0 && locality < 5); 1127 1128 ret = tis_check_active_locality(tpm, locality); 1129 1130 if (ret == DDI_SUCCESS) { 1131 /* Locality is already active */ 1132 tpm->locality = locality; 1133 return (DDI_SUCCESS); 1134 } 1135 1136 tpm_put8(tpm, TPM_ACCESS, TPM_ACCESS_REQUEST_USE); 1137 timeout = ddi_get_lbolt() + tpm->timeout_a; 1138 1139 /* Using polling */ 1140 while (tis_check_active_locality(tpm, locality) 1141 != DDI_SUCCESS) { 1142 if (ddi_get_lbolt() >= timeout) { 1143 #ifdef DEBUG 1144 cmn_err(CE_WARN, "!%s: (interrupt-disabled) " 1145 "tis_request_locality timed out (timeout_a = %ld)", 1146 myname, tpm->timeout_a); 1147 #endif 1148 return (DDI_FAILURE); 1149 } 1150 delay(tpm->timeout_poll); 1151 } 1152 1153 tpm->locality = locality; 1154 return (DDI_SUCCESS); 1155 } 1156 1157 /* Read the status register */ 1158 static uint8_t 1159 tis_get_status(tpm_state_t *tpm) { 1160 return (tpm_get8(tpm, TPM_STS)); 1161 } 1162 1163 static int 1164 tpm_wait_for_stat(tpm_state_t *tpm, uint8_t mask, clock_t timeout) { 1165 char *myname = "tpm_wait_for_stat"; 1166 clock_t absolute_timeout = ddi_get_lbolt() + timeout; 1167 1168 /* Using polling */ 1169 while ((tis_get_status(tpm) & mask) != mask) { 1170 if (ddi_get_lbolt() >= absolute_timeout) { 1171 /* Timeout reached */ 1172 #ifdef DEBUG 1173 cmn_err(CE_WARN, "!%s: using " 1174 "polling - reached timeout (%ld usecs)", 1175 myname, drv_hztousec(timeout)); 1176 #endif 1177 return (DDI_FAILURE); 1178 } 1179 delay(tpm->timeout_poll); 1180 } 1181 return (DDI_SUCCESS); 1182 } 1183 1184 /* 1185 * Initialize TPM device 1186 * 1. Find out supported interrupt capabilities 1187 * 2. Set up interrupt handler if supported (some BIOSes don't support 1188 * interrupts for TPMS, in which case we set up polling) 1189 * 3. Determine timeouts and commands duration 1190 */ 1191 static int 1192 tis_init(tpm_state_t *tpm) { 1193 uint32_t intf_caps; 1194 int ret; 1195 char *myname = "tis_init"; 1196 1197 /* 1198 * Temporarily set up timeouts before we get the real timeouts 1199 * by issuing TPM_CAP commands (but to issue TPM_CAP commands, 1200 * you need TIMEOUTs defined...chicken and egg problem here. 1201 * TPM timeouts: Convert the milliseconds to clock cycles 1202 */ 1203 tpm->timeout_a = drv_usectohz(TIS_TIMEOUT_A); 1204 tpm->timeout_b = drv_usectohz(TIS_TIMEOUT_B); 1205 tpm->timeout_c = drv_usectohz(TIS_TIMEOUT_C); 1206 tpm->timeout_d = drv_usectohz(TIS_TIMEOUT_D); 1207 /* 1208 * Do the same with the duration (real duration will be filled out 1209 * when we call TPM_GetCapability to get the duration values from 1210 * the TPM itself). 1211 */ 1212 tpm->duration[TPM_SHORT] = drv_usectohz(TPM_DEFAULT_DURATION); 1213 tpm->duration[TPM_MEDIUM] = drv_usectohz(TPM_DEFAULT_DURATION); 1214 tpm->duration[TPM_LONG] = drv_usectohz(TPM_DEFAULT_DURATION); 1215 tpm->duration[TPM_UNDEFINED] = drv_usectohz(TPM_DEFAULT_DURATION); 1216 1217 /* Find out supported capabilities */ 1218 intf_caps = tpm_get32(tpm, TPM_INTF_CAP); 1219 1220 /* Upper 3 bytes should always return 0 */ 1221 if (intf_caps & 0x7FFFFF00) { 1222 cmn_err(CE_WARN, "!%s: bad intf_caps value 0x%0X", 1223 myname, intf_caps); 1224 return (DDI_FAILURE); 1225 } 1226 1227 /* These two interrupts are mandatory */ 1228 if (!(intf_caps & TPM_INTF_INT_LOCALITY_CHANGE_INT)) { 1229 cmn_err(CE_WARN, 1230 "!%s: Mandatory capability Locality Change Int " 1231 "not supported", myname); 1232 return (DDI_FAILURE); 1233 } 1234 if (!(intf_caps & TPM_INTF_INT_DATA_AVAIL_INT)) { 1235 cmn_err(CE_WARN, "!%s: Mandatory capability Data Available Int " 1236 "not supported.", myname); 1237 return (DDI_FAILURE); 1238 } 1239 1240 /* 1241 * Before we start writing anything to TPM's registers, 1242 * make sure we are in locality 0 1243 */ 1244 ret = tis_request_locality(tpm, DEFAULT_LOCALITY); 1245 if (ret != DDI_SUCCESS) { 1246 cmn_err(CE_WARN, "!%s: Unable to request locality %d", myname, 1247 DEFAULT_LOCALITY); 1248 return (DDI_FAILURE); 1249 } /* Now we can refer to the locality as tpm->locality */ 1250 1251 tpm->timeout_poll = drv_usectohz(TPM_POLLING_TIMEOUT); 1252 tpm->intr_enabled = 0; 1253 1254 /* Get the real timeouts from the TPM */ 1255 ret = tpm_get_timeouts(tpm); 1256 if (ret != DDI_SUCCESS) { 1257 cmn_err(CE_WARN, "!%s: tpm_get_timeouts error", myname); 1258 return (DDI_FAILURE); 1259 } 1260 1261 ret = tpm_get_duration(tpm); 1262 if (ret != DDI_SUCCESS) { 1263 cmn_err(CE_WARN, "!%s: tpm_get_duration error", myname); 1264 return (DDI_FAILURE); 1265 } 1266 1267 /* This gets the TPM version information */ 1268 ret = tpm_get_version(tpm); 1269 if (ret != DDI_SUCCESS) { 1270 cmn_err(CE_WARN, "!%s: tpm_get_version error", myname); 1271 return (DDI_FAILURE); 1272 } 1273 1274 /* 1275 * Unless the TPM completes the test of its commands, 1276 * it can return an error when the untested commands are called 1277 */ 1278 ret = tpm_continue_selftest(tpm); 1279 if (ret != DDI_SUCCESS) { 1280 cmn_err(CE_WARN, "!%s: tpm_continue_selftest error", myname); 1281 return (DDI_FAILURE); 1282 } 1283 return (DDI_SUCCESS); 1284 } 1285 1286 /* 1287 * Module Entry points 1288 */ 1289 int 1290 _init(void) 1291 { 1292 int ret; 1293 1294 ret = ddi_soft_state_init(&statep, sizeof (tpm_state_t), 1); 1295 if (ret) { 1296 #ifdef DEBUG 1297 cmn_err(CE_WARN, "!ddi_soft_state_init failed: %d", ret); 1298 #endif 1299 return (ret); 1300 } 1301 ret = mod_install(&tpm_ml); 1302 if (ret != 0) { 1303 #ifdef DEBUG 1304 cmn_err(CE_WARN, "!_init: mod_install returned non-zero"); 1305 #endif 1306 ddi_soft_state_fini(&statep); 1307 return (ret); 1308 } 1309 1310 return (ret); 1311 } 1312 1313 int 1314 _info(struct modinfo *modinfop) 1315 { 1316 int ret; 1317 ret = mod_info(&tpm_ml, modinfop); 1318 #ifdef DEBUG 1319 if (ret == 0) 1320 cmn_err(CE_WARN, "!mod_info failed: %d", ret); 1321 #endif 1322 1323 return (ret); 1324 } 1325 1326 int 1327 _fini() 1328 { 1329 int ret; 1330 1331 ret = mod_remove(&tpm_ml); 1332 if (ret != 0) 1333 return (ret); 1334 1335 ddi_soft_state_fini(&statep); 1336 1337 return (ret); 1338 } 1339 /* End of driver configuration functions */ 1340 1341 static int 1342 tpm_resume(tpm_state_t *tpm) 1343 { 1344 mutex_enter(&tpm->pm_mutex); 1345 if (!tpm->suspended) { 1346 mutex_exit(&tpm->pm_mutex); 1347 return (DDI_FAILURE); 1348 } 1349 tpm->suspended = 0; 1350 cv_broadcast(&tpm->suspend_cv); 1351 mutex_exit(&tpm->pm_mutex); 1352 1353 return (DDI_SUCCESS); 1354 } 1355 1356 #ifdef sun4v 1357 static uint64_t hsvc_tpm_minor = 0; 1358 static hsvc_info_t hsvc_tpm = { 1359 HSVC_REV_1, NULL, HSVC_GROUP_TPM, 1, 0, NULL 1360 }; 1361 #endif 1362 1363 /* 1364 * Sun DDI/DDK entry points 1365 */ 1366 static int 1367 tpm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 1368 { 1369 int ret; 1370 int instance; 1371 #ifndef sun4v 1372 int idx, nregs; 1373 #endif 1374 char *myname = "tpm_attach"; 1375 tpm_state_t *tpm = NULL; 1376 1377 ASSERT(dip != NULL); 1378 1379 instance = ddi_get_instance(dip); 1380 if (instance < 0) 1381 return (DDI_FAILURE); 1382 1383 /* Nothing out of ordinary here */ 1384 switch (cmd) { 1385 case DDI_ATTACH: 1386 if (ddi_soft_state_zalloc(statep, instance) == DDI_SUCCESS) { 1387 tpm = ddi_get_soft_state(statep, instance); 1388 if (tpm == NULL) { 1389 #ifdef DEBUG 1390 cmn_err(CE_WARN, 1391 "!%s: cannot get state information.", 1392 myname); 1393 #endif 1394 return (DDI_FAILURE); 1395 } 1396 tpm->dip = dip; 1397 } else { 1398 #ifdef DEBUG 1399 cmn_err(CE_WARN, 1400 "!%s: cannot allocate state information.", 1401 myname); 1402 #endif 1403 return (DDI_FAILURE); 1404 } 1405 break; 1406 case DDI_RESUME: 1407 tpm = ddi_get_soft_state(statep, instance); 1408 if (tpm == NULL) { 1409 #ifdef DEBUG 1410 cmn_err(CE_WARN, "!%s: cannot get state information.", 1411 myname); 1412 #endif 1413 return (DDI_FAILURE); 1414 } 1415 return (tpm_resume(tpm)); 1416 default: 1417 #ifdef DEBUG 1418 cmn_err(CE_WARN, "!%s: cmd %d is not implemented", myname, cmd); 1419 #endif 1420 ret = DDI_FAILURE; 1421 goto FAIL; 1422 } 1423 1424 /* Zeroize the flag, which is used to keep track of what is allocated */ 1425 tpm->flags = 0; 1426 1427 #ifdef sun4v 1428 ret = hsvc_register(&hsvc_tpm, &hsvc_tpm_minor); 1429 if (ret != 0) { 1430 cmn_err(CE_WARN, "!%s: failed to register with " 1431 "hypervisor: 0x%0x", myname, ret); 1432 goto FAIL; 1433 } 1434 tpm->flags |= TPM_HSVC_REGISTERED; 1435 #else 1436 tpm->accattr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 1437 tpm->accattr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 1438 tpm->accattr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 1439 1440 idx = 0; 1441 ret = ddi_dev_nregs(tpm->dip, &nregs); 1442 if (ret != DDI_SUCCESS) 1443 goto FAIL; 1444 1445 /* 1446 * TPM vendors put the TPM registers in different 1447 * slots in their register lists. They are not always 1448 * the 1st set of registers, for instance. 1449 * Loop until we find the set that matches the expected 1450 * register size (0x5000). 1451 */ 1452 for (idx = 0; idx < nregs; idx++) { 1453 off_t regsize; 1454 1455 if ((ret = ddi_dev_regsize(tpm->dip, idx, ®size)) != 1456 DDI_SUCCESS) 1457 goto FAIL; 1458 /* The TIS spec says the TPM registers must be 0x5000 bytes */ 1459 if (regsize == 0x5000) 1460 break; 1461 } 1462 if (idx == nregs) { 1463 ret = DDI_FAILURE; 1464 goto FAIL; 1465 } 1466 1467 ret = ddi_regs_map_setup(tpm->dip, idx, (caddr_t *)&tpm->addr, 1468 (offset_t)0, (offset_t)0x5000, 1469 &tpm->accattr, &tpm->handle); 1470 1471 if (ret != DDI_SUCCESS) { 1472 goto FAIL; 1473 } 1474 tpm->flags |= TPM_DIDREGSMAP; 1475 #endif 1476 /* Enable TPM device according to the TIS specification */ 1477 ret = tis_init(tpm); 1478 if (ret != DDI_SUCCESS) { 1479 #ifdef DEBUG 1480 cmn_err(CE_WARN, "!%s: tis_init() failed with error %d", 1481 myname, ret); 1482 #endif 1483 1484 /* We need to clean up the ddi_regs_map_setup call */ 1485 if (tpm->flags & TPM_DIDREGSMAP) { 1486 ddi_regs_map_free(&tpm->handle); 1487 tpm->handle = NULL; 1488 tpm->flags &= ~TPM_DIDREGSMAP; 1489 } 1490 goto FAIL; 1491 } 1492 1493 /* Initialize the inter-process lock */ 1494 mutex_init(&tpm->dev_lock, NULL, MUTEX_DRIVER, NULL); 1495 mutex_init(&tpm->pm_mutex, NULL, MUTEX_DRIVER, NULL); 1496 cv_init(&tpm->suspend_cv, NULL, CV_DRIVER, NULL); 1497 1498 /* Set the suspend/resume property */ 1499 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, 1500 "pm-hardware-state", "needs-suspend-resume"); 1501 1502 mutex_enter(&tpm->pm_mutex); 1503 tpm->suspended = 0; 1504 mutex_exit(&tpm->pm_mutex); 1505 1506 tpm->flags |= TPM_DID_MUTEX; 1507 1508 /* Initialize the buffer and the lock associated with it */ 1509 tpm->bufsize = TPM_IO_BUF_SIZE; 1510 tpm->iobuf = kmem_zalloc((sizeof (uint8_t))*(tpm->bufsize), KM_SLEEP); 1511 tpm->flags |= TPM_DID_IO_ALLOC; 1512 1513 mutex_init(&tpm->iobuf_lock, NULL, MUTEX_DRIVER, NULL); 1514 tpm->flags |= TPM_DID_IO_MUTEX; 1515 1516 cv_init(&tpm->iobuf_cv, NULL, CV_DRIVER, NULL); 1517 tpm->flags |= TPM_DID_IO_CV; 1518 1519 /* Create minor node */ 1520 ret = ddi_create_minor_node(dip, "tpm", S_IFCHR, ddi_get_instance(dip), 1521 DDI_PSEUDO, 0); 1522 if (ret != DDI_SUCCESS) { 1523 #ifdef DEBUG 1524 cmn_err(CE_WARN, "!%s: ddi_create_minor_node failed", myname); 1525 #endif 1526 goto FAIL; 1527 } 1528 tpm->flags |= TPM_DIDMINOR; 1529 1530 #ifdef KCF_TPM_RNG_PROVIDER 1531 /* register RNG with kcf */ 1532 if (tpmrng_register(tpm) != DDI_SUCCESS) 1533 cmn_err(CE_WARN, "!%s: tpm RNG failed to register with kcf", 1534 myname); 1535 #endif 1536 1537 return (DDI_SUCCESS); 1538 FAIL: 1539 if (tpm != NULL) { 1540 tpm_cleanup(dip, tpm); 1541 ddi_soft_state_free(statep, instance); 1542 tpm = NULL; 1543 } 1544 1545 return (DDI_FAILURE); 1546 } 1547 1548 /* 1549 * Called by tpm_detach and tpm_attach (only on failure) 1550 * Free up the resources that are allocated 1551 */ 1552 static void 1553 tpm_cleanup(dev_info_t *dip, tpm_state_t *tpm) 1554 { 1555 if (tpm == NULL) 1556 return; 1557 1558 #ifdef KCF_TPM_RNG_PROVIDER 1559 (void) tpmrng_unregister(tpm); 1560 #endif 1561 1562 #ifdef sun4v 1563 if (tpm->flags & TPM_HSVC_REGISTERED) { 1564 (void) hsvc_unregister(&hsvc_tpm); 1565 tpm->flags &= ~(TPM_HSVC_REGISTERED); 1566 } 1567 #endif 1568 if (tpm->flags & TPM_DID_MUTEX) { 1569 mutex_destroy(&tpm->dev_lock); 1570 mutex_destroy(&tpm->pm_mutex); 1571 cv_destroy(&tpm->suspend_cv); 1572 tpm->flags &= ~(TPM_DID_MUTEX); 1573 } 1574 if (tpm->flags & TPM_DID_IO_ALLOC) { 1575 ASSERT(tpm->iobuf != NULL); 1576 kmem_free(tpm->iobuf, (sizeof (uint8_t))*(tpm->bufsize)); 1577 tpm->flags &= ~(TPM_DID_IO_ALLOC); 1578 } 1579 if (tpm->flags & TPM_DID_IO_MUTEX) { 1580 mutex_destroy(&tpm->iobuf_lock); 1581 tpm->flags &= ~(TPM_DID_IO_MUTEX); 1582 } 1583 if (tpm->flags & TPM_DID_IO_CV) { 1584 cv_destroy(&tpm->iobuf_cv); 1585 tpm->flags &= ~(TPM_DID_IO_CV); 1586 } 1587 if (tpm->flags & TPM_DIDREGSMAP) { 1588 /* Free the mapped addresses */ 1589 if (tpm->handle != NULL) 1590 ddi_regs_map_free(&tpm->handle); 1591 tpm->flags &= ~(TPM_DIDREGSMAP); 1592 } 1593 if (tpm->flags & TPM_DIDMINOR) { 1594 /* Remove minor node */ 1595 ddi_remove_minor_node(dip, NULL); 1596 tpm->flags &= ~(TPM_DIDMINOR); 1597 } 1598 } 1599 1600 static int 1601 tpm_suspend(tpm_state_t *tpm) 1602 { 1603 if (tpm == NULL) 1604 return (DDI_FAILURE); 1605 mutex_enter(&tpm->pm_mutex); 1606 if (tpm->suspended) { 1607 mutex_exit(&tpm->pm_mutex); 1608 return (DDI_SUCCESS); 1609 } 1610 tpm->suspended = 1; 1611 mutex_exit(&tpm->pm_mutex); 1612 1613 return (DDI_SUCCESS); 1614 } 1615 1616 static int 1617 tpm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1618 { 1619 char *myname = "tpm_detach"; 1620 int instance; 1621 tpm_state_t *tpm; 1622 1623 ASSERT(dip != NULL); 1624 1625 instance = ddi_get_instance(dip); 1626 if (instance < 0) 1627 return (DDI_FAILURE); 1628 1629 if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) { 1630 #ifdef DEBUG 1631 cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL", 1632 myname); 1633 #endif 1634 return (ENXIO); 1635 } 1636 1637 switch (cmd) { 1638 case DDI_DETACH: 1639 /* Body is after the switch stmt */ 1640 break; 1641 case DDI_SUSPEND: 1642 return (tpm_suspend(tpm)); 1643 default: 1644 #ifdef DEBUG 1645 cmn_err(CE_WARN, "!%s: case %d not implemented", myname, cmd); 1646 #endif 1647 return (DDI_FAILURE); 1648 } 1649 1650 /* Since we are freeing tpm structure, we need to gain the lock */ 1651 tpm_cleanup(dip, tpm); 1652 1653 /* Free the soft state */ 1654 ddi_soft_state_free(statep, instance); 1655 tpm = NULL; 1656 1657 return (DDI_SUCCESS); 1658 } 1659 1660 /*ARGSUSED*/ 1661 static int 1662 tpm_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp) 1663 { 1664 char *myname = "tpm_getinfo"; 1665 int instance; 1666 tpm_state_t *tpm; 1667 1668 instance = ddi_get_instance(dip); 1669 if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) { 1670 #ifdef DEBUG 1671 cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL", 1672 myname); 1673 #endif 1674 return (DDI_FAILURE); 1675 } 1676 1677 switch (cmd) { 1678 case DDI_INFO_DEVT2DEVINFO: 1679 *resultp = tpm->dip; 1680 break; 1681 case DDI_INFO_DEVT2INSTANCE: 1682 *resultp = 0; 1683 break; 1684 default: 1685 #ifdef DEBUG 1686 cmn_err(CE_WARN, "!%s: cmd %d is not implemented", myname, cmd); 1687 #endif 1688 return (DDI_FAILURE); 1689 } 1690 return (DDI_SUCCESS); 1691 } 1692 1693 /* 1694 * Driver entry points 1695 */ 1696 1697 /*ARGSUSED*/ 1698 static int 1699 tpm_open(dev_t *devp, int flag, int otyp, cred_t *cred) 1700 { 1701 char *myname = "tpm_open"; 1702 int instance; 1703 tpm_state_t *tpm; 1704 1705 ASSERT(devp != NULL); 1706 1707 instance = getminor(*devp); 1708 if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) { 1709 #ifdef DEBUG 1710 cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL", 1711 myname); 1712 #endif 1713 return (ENXIO); 1714 } 1715 if (otyp != OTYP_CHR) { 1716 #ifdef DEBUG 1717 cmn_err(CE_WARN, "!%s: otyp(%d) != OTYP_CHR(%d)", 1718 myname, otyp, OTYP_CHR); 1719 #endif 1720 return (EINVAL); 1721 } 1722 TPM_EXCLUSIVE_LOCK(tpm); 1723 1724 mutex_enter(&tpm->dev_lock); 1725 if (tpm->dev_held) { 1726 #ifdef DEBUG 1727 cmn_err(CE_WARN, "!%s: the device is already being used", 1728 myname); 1729 #endif 1730 mutex_exit(&tpm->dev_lock); 1731 return (EBUSY); 1732 } 1733 1734 /* The device is free so mark it busy */ 1735 tpm->dev_held = 1; 1736 mutex_exit(&tpm->dev_lock); 1737 1738 return (0); 1739 } 1740 1741 /*ARGSUSED*/ 1742 static int 1743 tpm_close(dev_t dev, int flag, int otyp, cred_t *cred) 1744 { 1745 char *myname = "tpm_close"; 1746 int instance; 1747 tpm_state_t *tpm; 1748 1749 instance = getminor(dev); 1750 if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) { 1751 #ifdef DEBUG 1752 cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL", 1753 myname); 1754 #endif 1755 return (ENXIO); 1756 } 1757 if (otyp != OTYP_CHR) { 1758 #ifdef DEBUG 1759 cmn_err(CE_WARN, "!%s: otyp(%d) != OTYP_CHR(%d)", 1760 myname, otyp, OTYP_CHR); 1761 #endif 1762 return (EINVAL); 1763 } 1764 TPM_EXCLUSIVE_LOCK(tpm); 1765 1766 ASSERT(tpm->dev_held); 1767 1768 mutex_enter(&tpm->dev_lock); 1769 ASSERT(mutex_owned(&tpm->dev_lock)); 1770 tpm->dev_held = 0; 1771 mutex_exit(&tpm->dev_lock); 1772 1773 return (0); 1774 } 1775 1776 /*ARGSUSED*/ 1777 static int 1778 tpm_read(dev_t dev, struct uio *uiop, cred_t *credp) 1779 { 1780 int ret; 1781 uint32_t size; 1782 char *myname = "tpm_read"; 1783 int instance; 1784 tpm_state_t *tpm; 1785 1786 instance = getminor(dev); 1787 if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) { 1788 #ifdef DEBUG 1789 cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL", 1790 myname); 1791 #endif 1792 return (ENXIO); 1793 } 1794 if (uiop == NULL) { 1795 #ifdef DEBUG 1796 cmn_err(CE_WARN, "!%s: passed in uiop is NULL", myname); 1797 #endif 1798 return (EFAULT); 1799 } 1800 1801 TPM_EXCLUSIVE_LOCK(tpm); 1802 1803 /* Receive the data after requiring the lock */ 1804 ret = tpm_io_lock(tpm); 1805 1806 /* Timeout reached */ 1807 if (ret) 1808 return (ret); 1809 1810 if (uiop->uio_resid > tpm->bufsize) { 1811 #ifdef DEBUG 1812 cmn_err(CE_WARN, "!%s: read_in data is bigger " 1813 "than tpm->bufsize:read in:%d, bufsiz:%d", 1814 myname, (int)uiop->uio_resid, (int)tpm->bufsize); 1815 #endif 1816 ret = EIO; 1817 goto OUT; 1818 } 1819 1820 ret = tis_recv_data(tpm, tpm->iobuf, tpm->bufsize); 1821 if (ret < TPM_HEADER_SIZE) { 1822 #ifdef DEBUG 1823 cmn_err(CE_WARN, "!%s: tis_recv_data returned error", myname); 1824 #endif 1825 ret = EIO; 1826 goto OUT; 1827 } 1828 1829 size = load32(tpm->iobuf, 2); 1830 if (ret != size) { 1831 #ifdef DEBUG 1832 cmn_err(CE_WARN, "!%s: tis_recv_data:" 1833 "expected size=%d, actually read=%d", 1834 myname, size, ret); 1835 #endif 1836 ret = EIO; 1837 goto OUT; 1838 } 1839 1840 /* Send the buffer from the kernel to the userspace */ 1841 ret = uiomove(tpm->iobuf, size, UIO_READ, uiop); 1842 if (ret) { 1843 #ifdef DEBUG 1844 cmn_err(CE_WARN, "!%s: uiomove returned error", myname); 1845 #endif 1846 goto OUT; 1847 } 1848 1849 /* Zeroize the buffer... */ 1850 bzero(tpm->iobuf, tpm->bufsize); 1851 ret = DDI_SUCCESS; 1852 OUT: 1853 /* We are done now: wake up the waiting threads */ 1854 tpm_unlock(tpm); 1855 1856 return (ret); 1857 } 1858 1859 /*ARGSUSED*/ 1860 static int 1861 tpm_write(dev_t dev, struct uio *uiop, cred_t *credp) 1862 { 1863 int ret; 1864 size_t len; 1865 uint32_t size; 1866 char *myname = "tpm_write"; 1867 int instance; 1868 tpm_state_t *tpm; 1869 1870 instance = getminor(dev); 1871 if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) { 1872 #ifdef DEBUG 1873 cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL", 1874 myname); 1875 #endif 1876 return (ENXIO); 1877 } 1878 1879 if (uiop == NULL) { 1880 #ifdef DEBUG 1881 cmn_err(CE_WARN, "!%s: passed in uiop is NULL", myname); 1882 #endif 1883 return (EFAULT); 1884 } 1885 1886 TPM_EXCLUSIVE_LOCK(tpm); 1887 1888 len = uiop->uio_resid; 1889 if (len == 0) { 1890 #ifdef DEBUG 1891 cmn_err(CE_WARN, "!%s: requested read of len 0", myname); 1892 #endif 1893 return (0); 1894 } 1895 1896 /* Get the lock for using iobuf */ 1897 ret = tpm_io_lock(tpm); 1898 /* Timeout Reached */ 1899 if (ret) 1900 return (ret); 1901 1902 /* Copy the header and parse the structure to find out the size... */ 1903 ret = uiomove(tpm->iobuf, TPM_HEADER_SIZE, UIO_WRITE, uiop); 1904 if (ret) { 1905 #ifdef DEBUG 1906 cmn_err(CE_WARN, "!%s: uiomove returned error" 1907 "while getting the the header", 1908 myname); 1909 #endif 1910 goto OUT; 1911 } 1912 1913 /* Get the buffersize from the command buffer structure */ 1914 size = load32(tpm->iobuf, TPM_PARAMSIZE_OFFSET); 1915 1916 /* Copy the command to the contiguous buffer */ 1917 if (size > tpm->bufsize) { 1918 #ifdef DEBUG 1919 cmn_err(CE_WARN, "!%s: size %d is greater than " 1920 "the tpm input buffer size %d", 1921 myname, (int)size, (int)tpm->bufsize); 1922 #endif 1923 ret = ENXIO; 1924 goto OUT; 1925 } 1926 1927 /* Copy the buffer from the userspace to kernel */ 1928 ret = uiomove(tpm->iobuf+TPM_HEADER_SIZE, size-TPM_HEADER_SIZE, 1929 UIO_WRITE, uiop); 1930 1931 if (ret) { 1932 #ifdef DEBUG 1933 cmn_err(CE_WARN, "!%s: uiomove returned error" 1934 "while getting the rest of the command", myname); 1935 #endif 1936 goto OUT; 1937 } 1938 1939 /* Send the command */ 1940 ret = tis_send_data(tpm, tpm->iobuf, size); 1941 if (ret != DDI_SUCCESS) { 1942 #ifdef DEBUG 1943 cmn_err(CE_WARN, "!%s: tis_send_data returned error", myname); 1944 #endif 1945 ret = EFAULT; 1946 goto OUT; 1947 } 1948 1949 /* Zeroize the buffer... */ 1950 bzero(tpm->iobuf, tpm->bufsize); 1951 ret = DDI_SUCCESS; 1952 OUT: 1953 tpm_unlock(tpm); 1954 return (ret); 1955 } 1956 1957 /* 1958 * This is to deal with the contentions for the iobuf 1959 */ 1960 static inline int 1961 tpm_io_lock(tpm_state_t *tpm) 1962 { 1963 int ret; 1964 clock_t timeout; 1965 1966 mutex_enter(&tpm->iobuf_lock); 1967 ASSERT(mutex_owned(&tpm->iobuf_lock)); 1968 1969 timeout = ddi_get_lbolt() + drv_usectohz(TPM_IO_TIMEOUT); 1970 1971 /* Wait until the iobuf becomes free with the timeout */ 1972 while (tpm->iobuf_inuse) { 1973 ret = cv_timedwait(&tpm->iobuf_cv, &tpm->iobuf_lock, timeout); 1974 if (ret <= 0) { 1975 /* Timeout reached */ 1976 mutex_exit(&tpm->iobuf_lock); 1977 #ifdef DEBUG 1978 cmn_err(CE_WARN, "!tpm_io_lock:iorequest timed out"); 1979 #endif 1980 return (ETIME); 1981 } 1982 } 1983 tpm->iobuf_inuse = 1; 1984 mutex_exit(&tpm->iobuf_lock); 1985 return (0); 1986 } 1987 1988 /* 1989 * This is to deal with the contentions for the iobuf 1990 */ 1991 static inline void 1992 tpm_unlock(tpm_state_t *tpm) 1993 { 1994 /* Wake up the waiting threads */ 1995 mutex_enter(&tpm->iobuf_lock); 1996 ASSERT(tpm->iobuf_inuse == 1 && mutex_owned(&tpm->iobuf_lock)); 1997 tpm->iobuf_inuse = 0; 1998 cv_broadcast(&tpm->iobuf_cv); 1999 mutex_exit(&tpm->iobuf_lock); 2000 } 2001 2002 #ifdef KCF_TPM_RNG_PROVIDER 2003 /* 2004 * Random number generator entry points 2005 */ 2006 static void 2007 strncpy_spacepad(uchar_t *s1, char *s2, int n) 2008 { 2009 int s2len = strlen(s2); 2010 (void) strncpy((char *)s1, s2, n); 2011 if (s2len < n) 2012 (void) memset(s1 + s2len, ' ', n - s2len); 2013 } 2014 2015 /*ARGSUSED*/ 2016 static int 2017 tpmrng_ext_info(crypto_provider_handle_t prov, 2018 crypto_provider_ext_info_t *ext_info, 2019 crypto_req_handle_t cfreq) 2020 { 2021 tpm_state_t *tpm = (tpm_state_t *)prov; 2022 char buf[64]; 2023 2024 if (tpm == NULL) 2025 return (DDI_FAILURE); 2026 2027 strncpy_spacepad(ext_info->ei_manufacturerID, 2028 (char *)tpm->vers_info.tpmVendorID, 2029 sizeof (ext_info->ei_manufacturerID)); 2030 2031 strncpy_spacepad(ext_info->ei_model, "0", 2032 sizeof (ext_info->ei_model)); 2033 strncpy_spacepad(ext_info->ei_serial_number, "0", 2034 sizeof (ext_info->ei_serial_number)); 2035 2036 ext_info->ei_flags = CRYPTO_EXTF_RNG | CRYPTO_EXTF_SO_PIN_LOCKED; 2037 ext_info->ei_max_session_count = CRYPTO_EFFECTIVELY_INFINITE; 2038 ext_info->ei_max_pin_len = 0; 2039 ext_info->ei_min_pin_len = 0; 2040 ext_info->ei_total_public_memory = CRYPTO_UNAVAILABLE_INFO; 2041 ext_info->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO; 2042 ext_info->ei_total_private_memory = CRYPTO_UNAVAILABLE_INFO; 2043 ext_info->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO; 2044 ext_info->ei_time[0] = 0; 2045 2046 ext_info->ei_hardware_version.cv_major = tpm->vers_info.version.major; 2047 ext_info->ei_hardware_version.cv_minor = tpm->vers_info.version.minor; 2048 ext_info->ei_firmware_version.cv_major = 2049 tpm->vers_info.version.revMajor; 2050 ext_info->ei_firmware_version.cv_minor = 2051 tpm->vers_info.version.revMinor; 2052 2053 (void) snprintf(buf, sizeof (buf), "tpmrng TPM RNG"); 2054 2055 strncpy_spacepad(ext_info->ei_label, buf, 2056 sizeof (ext_info->ei_label)); 2057 #undef BUFSZ 2058 return (CRYPTO_SUCCESS); 2059 2060 } 2061 2062 static int 2063 tpmrng_register(tpm_state_t *tpm) 2064 { 2065 int ret; 2066 char ID[64]; 2067 crypto_mech_name_t *rngmech; 2068 2069 ASSERT(tpm != NULL); 2070 2071 (void) snprintf(ID, sizeof (ID), "tpmrng %s", IDENT_TPMRNG); 2072 2073 tpmrng_prov_info.pi_provider_description = ID; 2074 tpmrng_prov_info.pi_provider_dev.pd_hw = tpm->dip; 2075 tpmrng_prov_info.pi_provider_handle = tpm; 2076 2077 ret = crypto_register_provider(&tpmrng_prov_info, &tpm->n_prov); 2078 if (ret != CRYPTO_SUCCESS) { 2079 tpm->n_prov = NULL; 2080 return (DDI_FAILURE); 2081 } 2082 2083 crypto_provider_notification(tpm->n_prov, CRYPTO_PROVIDER_READY); 2084 2085 rngmech = kmem_zalloc(strlen("random") + 1, KM_SLEEP); 2086 (void) memcpy(rngmech, "random", 6); 2087 ret = crypto_load_dev_disabled("tpm", ddi_get_instance(tpm->dip), 2088 1, rngmech); 2089 #ifdef DEBUG 2090 if (ret != CRYPTO_SUCCESS) 2091 cmn_err(CE_WARN, "!crypto_load_dev_disabled failed (%d)", ret); 2092 #endif 2093 return (DDI_SUCCESS); 2094 } 2095 2096 static int 2097 tpmrng_unregister(tpm_state_t *tpm) 2098 { 2099 int ret; 2100 ASSERT(tpm != NULL); 2101 if (tpm->n_prov) { 2102 ret = crypto_unregister_provider(tpm->n_prov); 2103 tpm->n_prov = NULL; 2104 if (ret != CRYPTO_SUCCESS) 2105 return (DDI_FAILURE); 2106 } 2107 return (DDI_SUCCESS); 2108 } 2109 2110 /*ARGSUSED*/ 2111 static void 2112 tpmrng_provider_status(crypto_provider_handle_t provider, uint_t *status) 2113 { 2114 *status = CRYPTO_PROVIDER_READY; 2115 } 2116 2117 /*ARGSUSED*/ 2118 static int 2119 tpmrng_seed_random(crypto_provider_handle_t provider, crypto_session_id_t sid, 2120 uchar_t *buf, size_t len, uint_t entropy_est, uint32_t flags, 2121 crypto_req_handle_t req) 2122 { 2123 int ret; 2124 tpm_state_t *tpm; 2125 uint32_t len32; 2126 /* Max length of seed is 256 bytes, add 14 for header. */ 2127 uint8_t cmdbuf[270] = { 2128 0, 193, /* TPM_TAG_RQU COMMAND */ 2129 0, 0, 0, 0x0A, /* paramsize in bytes */ 2130 0, 0, 0, TPM_ORD_StirRandom, 2131 0, 0, 0, 0 /* number of input bytes (< 256) */ 2132 }; 2133 uint32_t buflen; 2134 2135 if (len == 0 || len > 255 || buf == NULL) 2136 return (CRYPTO_ARGUMENTS_BAD); 2137 2138 tpm = (tpm_state_t *)provider; 2139 if (tpm == NULL) 2140 return (CRYPTO_INVALID_CONTEXT); 2141 2142 /* Acquire lock for exclusive use of TPM */ 2143 TPM_EXCLUSIVE_LOCK(tpm); 2144 2145 ret = tpm_io_lock(tpm); 2146 /* Timeout reached */ 2147 if (ret) 2148 return (CRYPTO_BUSY); 2149 2150 /* TPM only handles 32 bit length, so truncate if too big. */ 2151 len32 = (uint32_t)len; 2152 buflen = len32 + 14; 2153 2154 /* The length must be in network order */ 2155 buflen = htonl(buflen); 2156 bcopy(&buflen, cmdbuf + 2, sizeof (uint32_t)); 2157 2158 /* Convert it back */ 2159 buflen = ntohl(buflen); 2160 2161 /* length must be in network order */ 2162 len32 = htonl(len32); 2163 bcopy(&len32, cmdbuf + 10, sizeof (uint32_t)); 2164 2165 /* convert it back */ 2166 len32 = ntohl(len32); 2167 2168 bcopy(buf, cmdbuf + 14, len32); 2169 2170 ret = itpm_command(tpm, cmdbuf, buflen); 2171 tpm_unlock(tpm); 2172 2173 if (ret != DDI_SUCCESS) { 2174 #ifdef DEBUG 2175 cmn_err(CE_WARN, "!tpmrng_seed_random failed"); 2176 #endif 2177 return (CRYPTO_FAILED); 2178 } 2179 2180 return (CRYPTO_SUCCESS); 2181 } 2182 2183 /* ARGSUSED */ 2184 static int 2185 tpmrng_generate_random(crypto_provider_handle_t provider, 2186 crypto_session_id_t sid, uchar_t *buf, size_t len, crypto_req_handle_t req) 2187 { 2188 int ret; 2189 tpm_state_t *tpm; 2190 uint8_t hdr[14] = { 2191 0, 193, /* TPM_TAG_RQU COMMAND */ 2192 0, 0, 0, 14, /* paramsize in bytes */ 2193 0, 0, 0, TPM_ORD_GetRandom, 2194 0, 0, 0, 0 2195 }; 2196 uint8_t *cmdbuf = NULL; 2197 uint32_t len32 = (uint32_t)len; 2198 uint32_t buflen = len32 + sizeof (hdr); 2199 2200 if (len == 0 || buf == NULL) 2201 return (CRYPTO_ARGUMENTS_BAD); 2202 2203 tpm = (tpm_state_t *)provider; 2204 if (tpm == NULL) 2205 return (CRYPTO_INVALID_CONTEXT); 2206 2207 TPM_EXCLUSIVE_LOCK(tpm); 2208 2209 ret = tpm_io_lock(tpm); 2210 /* Timeout reached */ 2211 if (ret) 2212 return (CRYPTO_BUSY); 2213 2214 cmdbuf = kmem_zalloc(buflen, KM_SLEEP); 2215 bcopy(hdr, cmdbuf, sizeof (hdr)); 2216 2217 /* Length is written in network byte order */ 2218 len32 = htonl(len32); 2219 bcopy(&len32, cmdbuf + 10, sizeof (uint32_t)); 2220 2221 ret = itpm_command(tpm, cmdbuf, buflen); 2222 if (ret != DDI_SUCCESS) { 2223 #ifdef DEBUG 2224 cmn_err(CE_WARN, "!tpmrng_generate_random failed"); 2225 #endif 2226 kmem_free(cmdbuf, buflen); 2227 tpm_unlock(tpm); 2228 return (CRYPTO_FAILED); 2229 } 2230 2231 /* Find out how many bytes were really returned */ 2232 len32 = load32(cmdbuf, 10); 2233 2234 /* Copy the random bytes back to the callers buffer */ 2235 bcopy(cmdbuf + 14, buf, len32); 2236 2237 kmem_free(cmdbuf, buflen); 2238 tpm_unlock(tpm); 2239 2240 return (CRYPTO_SUCCESS); 2241 } 2242 #endif /* KCF_TPM_RNG_PROVIDER */