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