1 /*- 2 * Copyright (c) 2018 Stormshield. 3 * Copyright (c) 2018 Semihalf. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/random.h> 29 #include <dev/random/randomdev.h> 30 31 #include <machine/atomic.h> 32 33 #include "tpm20.h" 34 35 #define TPM_HARVEST_SIZE 16 36 37 #define TPM2_ST_NO_SESSIONS 0x8001 38 #define TPM2_RC_SUCCESS 0x0000 39 #define TPM2_RC_INITIALIZE 0x0100 40 #define TPM2_RC_TESTING 0x090a 41 #define TPM2_RC_RETRY 0x0922 42 43 #define TPM2_SU_CLEAR 0x0000 44 #define TPM2_SU_STATE 0x0001 45 46 #define TPM2_RETRY_INITIAL_MS 20 47 #define TPM2_RETRY_MAX_MS (TPM_TIMEOUT_B / 1000) 48 /* 49 * Perform a harvest every 10 seconds. 50 * Since discrete TPMs are painfully slow 51 * we don't want to execute this too often 52 * as the chip is likely to be used by others too. 53 */ 54 #define TPM_HARVEST_INTERVAL 10 55 56 MALLOC_DEFINE(M_TPM20, "tpm_buffer", "buffer for tpm 2.0 driver"); 57 58 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM 59 static void tpm20_harvest(void *arg, int unused); 60 #endif 61 static int tpm20_command(device_t, uint32_t, uint16_t, uint32_t, 62 const char *); 63 static int tpm20_restart(device_t dev, bool clear); 64 static int tpm20_save_state(device_t dev, bool suspend); 65 66 static d_open_t tpm20_open; 67 static d_close_t tpm20_close; 68 static d_read_t tpm20_read; 69 static d_write_t tpm20_write; 70 static d_ioctl_t tpm20_ioctl; 71 72 static struct cdevsw tpm20_cdevsw = { 73 .d_version = D_VERSION, 74 .d_open = tpm20_open, 75 .d_close = tpm20_close, 76 .d_read = tpm20_read, 77 .d_write = tpm20_write, 78 .d_ioctl = tpm20_ioctl, 79 .d_name = "tpm20", 80 }; 81 82 int 83 tpm20_read(struct cdev *dev, struct uio *uio, int flags) 84 { 85 struct tpm_sc *sc; 86 struct tpm_priv *priv; 87 size_t bytes_to_transfer; 88 size_t offset; 89 ssize_t resid; 90 int result; 91 92 sc = (struct tpm_sc *)dev->si_drv1; 93 result = devfs_get_cdevpriv((void **)&priv); 94 if (result != 0) 95 return (result); 96 97 sx_xlock(&priv->io_lock); 98 sx_xlock(&sc->dev_lock); 99 if (atomic_load_bool(&sc->dying)) { 100 result = ENXIO; 101 goto out_locked; 102 } 103 if (sc->suspended) { 104 result = EBUSY; 105 goto out_locked; 106 } 107 offset = priv->offset; 108 bytes_to_transfer = MIN(priv->len, uio->uio_resid); 109 sx_xunlock(&sc->dev_lock); 110 111 if (bytes_to_transfer > 0) { 112 resid = uio->uio_resid; 113 result = uiomove((caddr_t)priv->buf + offset, 114 (int)bytes_to_transfer, uio); 115 bytes_to_transfer = resid - uio->uio_resid; 116 priv->offset += bytes_to_transfer; 117 priv->len -= bytes_to_transfer; 118 } else { 119 result = 0; 120 } 121 sx_xunlock(&priv->io_lock); 122 return (result); 123 124 out_locked: 125 sx_xunlock(&sc->dev_lock); 126 sx_xunlock(&priv->io_lock); 127 return (result); 128 } 129 130 int 131 tpm20_write(struct cdev *dev, struct uio *uio, int flags) 132 { 133 struct tpm_sc *sc; 134 struct tpm_priv *priv; 135 uint8_t *command; 136 size_t byte_count; 137 int result; 138 139 sc = (struct tpm_sc *)dev->si_drv1; 140 result = devfs_get_cdevpriv((void **)&priv); 141 if (result != 0) 142 return (result); 143 144 byte_count = uio->uio_resid; 145 if (byte_count < TPM_HEADER_SIZE) { 146 device_printf(sc->dev, 147 "Requested transfer is too small\n"); 148 return (EINVAL); 149 } 150 151 if (byte_count > TPM_BUFSIZE) { 152 device_printf(sc->dev, 153 "Requested transfer is too large\n"); 154 return (E2BIG); 155 } 156 157 command = malloc(byte_count, M_TPM20, M_WAITOK); 158 sx_xlock(&priv->io_lock); 159 result = uiomove(command, byte_count, uio); 160 if (result != 0) 161 goto out_priv; 162 163 sx_xlock(&sc->dev_lock); 164 if (atomic_load_bool(&sc->dying)) { 165 result = ENXIO; 166 goto out; 167 } 168 if (sc->suspended) { 169 result = EBUSY; 170 goto out; 171 } 172 173 memcpy(priv->buf, command, byte_count); 174 result = TPM_TRANSMIT(sc->dev, priv, byte_count); 175 176 out: 177 sx_xunlock(&sc->dev_lock); 178 if (result != 0) 179 uio->uio_resid = byte_count; 180 out_priv: 181 sx_xunlock(&priv->io_lock); 182 free(command, M_TPM20); 183 return (result); 184 } 185 186 static struct tpm_priv * 187 tpm20_priv_alloc(void) 188 { 189 struct tpm_priv *priv; 190 191 priv = malloc(sizeof (*priv), M_TPM20, M_WAITOK | M_ZERO); 192 sx_init(&priv->io_lock, "TPM per-open I/O lock"); 193 return (priv); 194 } 195 196 static void 197 tpm20_priv_dtor(void *data) 198 { 199 struct tpm_priv *priv = data; 200 201 sx_destroy(&priv->io_lock); 202 free(priv, M_TPM20); 203 } 204 205 int 206 tpm20_open(struct cdev *dev, int flag, int mode, struct thread *td) 207 { 208 struct tpm_sc *sc; 209 struct tpm_priv *priv; 210 int error; 211 212 sc = (struct tpm_sc *)dev->si_drv1; 213 sx_xlock(&sc->dev_lock); 214 if (atomic_load_bool(&sc->dying)) { 215 error = ENXIO; 216 goto out; 217 } 218 if (sc->suspended) { 219 error = EBUSY; 220 goto out; 221 } 222 priv = tpm20_priv_alloc(); 223 error = devfs_set_cdevpriv(priv, tpm20_priv_dtor); 224 if (error != 0) 225 tpm20_priv_dtor(priv); 226 227 out: 228 sx_xunlock(&sc->dev_lock); 229 return (error); 230 } 231 232 int 233 tpm20_close(struct cdev *dev, int flag, int mode, struct thread *td) 234 { 235 236 return (0); 237 } 238 239 int 240 tpm20_ioctl(struct cdev *dev, u_long cmd, caddr_t data, 241 int flags, struct thread *td) 242 { 243 244 return (ENOTTY); 245 } 246 247 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM 248 static const struct random_source random_tpm = { 249 .rs_ident = "TPM", 250 .rs_source = RANDOM_PURE_TPM, 251 }; 252 #endif 253 254 int 255 tpm20_init(struct tpm_sc *sc) 256 { 257 struct make_dev_args args; 258 int result; 259 260 atomic_store_bool(&sc->dying, false); 261 sc->suspended = false; 262 sc->internal_priv = tpm20_priv_alloc(); 263 264 make_dev_args_init(&args); 265 args.mda_devsw = &tpm20_cdevsw; 266 args.mda_uid = UID_ROOT; 267 args.mda_gid = GID_WHEEL; 268 args.mda_mode = TPM_CDEV_PERM_FLAG; 269 args.mda_si_drv1 = sc; 270 result = make_dev_s(&args, &sc->sc_cdev, TPM_CDEV_NAME); 271 if (result != 0) 272 return (result); 273 274 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM 275 random_source_register(&random_tpm); 276 TIMEOUT_TASK_INIT(taskqueue_thread, &sc->harvest_task, 0, 277 tpm20_harvest, sc); 278 taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task, 0); 279 #endif 280 sc->common_initialized = true; 281 282 return (result); 283 284 } 285 286 void 287 tpm20_release(struct tpm_sc *sc) 288 { 289 290 /* Publish teardown so a retrying command stops using the device. */ 291 atomic_store_bool(&sc->dying, true); 292 sx_xlock(&sc->dev_lock); 293 sx_xunlock(&sc->dev_lock); 294 295 /* Stop and drain character-device methods before freeing their state. */ 296 if (sc->sc_cdev != NULL) { 297 destroy_dev(sc->sc_cdev); 298 sc->sc_cdev = NULL; 299 } 300 if (!sc->common_initialized) 301 goto out; 302 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM 303 taskqueue_drain_timeout(taskqueue_thread, &sc->harvest_task); 304 random_source_deregister(&random_tpm); 305 #endif 306 sc->common_initialized = false; 307 out: 308 if (sc->internal_priv != NULL) { 309 tpm20_priv_dtor(sc->internal_priv); 310 sc->internal_priv = NULL; 311 } 312 sx_destroy(&sc->dev_lock); 313 } 314 315 int 316 tpm20_resume(device_t dev) 317 { 318 struct tpm_sc *sc; 319 int error; 320 321 sc = device_get_softc(dev); 322 sx_xlock(&sc->dev_lock); 323 if (atomic_load_bool(&sc->dying)) { 324 error = ENXIO; 325 goto out; 326 } 327 error = tpm20_restart(dev, false); 328 if (error == 0) 329 sc->suspended = false; 330 out: 331 sx_xunlock(&sc->dev_lock); 332 if (error != 0) 333 return (error); 334 335 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM 336 taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task, 337 hz * TPM_HARVEST_INTERVAL); 338 #endif 339 return (0); 340 } 341 342 int 343 tpm20_suspend(device_t dev) 344 { 345 struct tpm_sc *sc; 346 int error; 347 348 sc = device_get_softc(dev); 349 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM 350 taskqueue_drain_timeout(taskqueue_thread, &sc->harvest_task); 351 #endif 352 sx_xlock(&sc->dev_lock); 353 if (atomic_load_bool(&sc->dying)) { 354 error = ENXIO; 355 goto out; 356 } 357 if (sc->suspended) { 358 error = 0; 359 goto out; 360 } 361 error = tpm20_save_state(dev, true); 362 if (error == 0) 363 sc->suspended = true; 364 out: 365 sx_xunlock(&sc->dev_lock); 366 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM 367 if (error != 0) 368 taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task, 369 hz * TPM_HARVEST_INTERVAL); 370 #endif 371 return (error); 372 } 373 374 int 375 tpm20_shutdown(device_t dev) 376 { 377 struct tpm_sc *sc; 378 int error; 379 380 sc = device_get_softc(dev); 381 sx_xlock(&sc->dev_lock); 382 if (atomic_load_bool(&sc->dying)) 383 error = ENXIO; 384 else 385 error = tpm20_save_state(dev, false); 386 sx_xunlock(&sc->dev_lock); 387 return (error); 388 } 389 390 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM 391 /* 392 * Get TPM_HARVEST_SIZE random bytes and add them 393 * into system entropy pool. 394 */ 395 static void 396 tpm20_harvest(void *arg, int unused) 397 { 398 struct tpm_sc *sc; 399 struct tpm_priv *priv; 400 unsigned char entropy[TPM_HARVEST_SIZE]; 401 uint16_t entropy_size; 402 int result; 403 uint8_t cmd[] = { 404 0x80, 0x01, /* TPM_ST_NO_SESSIONS tag*/ 405 0x00, 0x00, 0x00, 0x0c, /* cmd length */ 406 0x00, 0x00, 0x01, 0x7b, /* cmd TPM_CC_GetRandom */ 407 0x00, TPM_HARVEST_SIZE /* number of bytes requested */ 408 }; 409 410 sc = arg; 411 sx_xlock(&sc->dev_lock); 412 if (atomic_load_bool(&sc->dying) || sc->suspended) { 413 sx_xunlock(&sc->dev_lock); 414 return; 415 } 416 417 priv = sc->internal_priv; 418 memcpy(priv->buf, cmd, sizeof(cmd)); 419 420 entropy_size = 0; 421 result = TPM_TRANSMIT(sc->dev, priv, sizeof(cmd)); 422 if (result == 0) { 423 /* The byte count is placed immediately after the header. */ 424 entropy_size = (uint16_t)priv->buf[TPM_HEADER_SIZE + 1]; 425 if (entropy_size > 0) { 426 entropy_size = MIN(entropy_size, TPM_HARVEST_SIZE); 427 memcpy(entropy, 428 priv->buf + TPM_HEADER_SIZE + sizeof(uint16_t), 429 entropy_size); 430 } 431 } 432 taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task, 433 hz * TPM_HARVEST_INTERVAL); 434 435 sx_xunlock(&sc->dev_lock); 436 if (entropy_size > 0) 437 random_harvest_queue(entropy, entropy_size, RANDOM_PURE_TPM); 438 } 439 #endif /* TPM_HARVEST */ 440 441 /* 442 * Send a TPM 2.0 command whose successful response contains only a header. 443 */ 444 static int 445 tpm20_command(device_t dev, uint32_t command, uint16_t parameter, 446 uint32_t alternate_rc, const char *name) 447 { 448 struct tpm_priv *priv; 449 struct tpm_sc *sc; 450 uint32_t response_rc, response_size; 451 uint8_t cmd[12]; 452 int delay_ms, error; 453 454 sc = device_get_softc(dev); 455 if (sc == NULL) 456 return (ENXIO); 457 458 sx_assert(&sc->dev_lock, SA_XLOCKED); 459 if (atomic_load_bool(&sc->dying)) 460 return (ENXIO); 461 priv = sc->internal_priv; 462 463 be16enc(cmd, TPM2_ST_NO_SESSIONS); 464 be32enc(cmd + 2, sizeof(cmd)); 465 be32enc(cmd + 6, command); 466 be16enc(cmd + 10, parameter); 467 468 delay_ms = TPM2_RETRY_INITIAL_MS; 469 for (;;) { 470 if (atomic_load_bool(&sc->dying)) 471 return (ENXIO); 472 memcpy(priv->buf, cmd, sizeof(cmd)); 473 error = TPM_TRANSMIT(sc->dev, priv, sizeof(cmd)); 474 if (error != 0) 475 break; 476 if (priv->len < TPM_HEADER_SIZE) { 477 error = EPROTO; 478 break; 479 } 480 481 response_size = be32dec(priv->buf + 2); 482 response_rc = be32dec(priv->buf + 6); 483 if (be16dec(priv->buf) != TPM2_ST_NO_SESSIONS || 484 response_size != TPM_HEADER_SIZE || 485 priv->len != response_size) { 486 error = EPROTO; 487 break; 488 } 489 if (response_rc != TPM2_RC_RETRY && 490 response_rc != TPM2_RC_TESTING) 491 break; 492 if (atomic_load_bool(&sc->dying)) 493 return (ENXIO); 494 if (delay_ms > TPM2_RETRY_MAX_MS) 495 break; 496 pause("tpm2retry", MAX(hz * delay_ms / 1000, 1)); 497 delay_ms *= 2; 498 } 499 if (error != 0) { 500 device_printf(dev, "%s command failed: %d\n", name, error); 501 return (error); 502 } 503 if (response_rc != TPM2_RC_SUCCESS && response_rc != alternate_rc) { 504 device_printf(dev, "%s failed: TPM error 0x%x\n", name, 505 response_rc); 506 return (EIO); 507 } 508 return (0); 509 } 510 511 static int 512 tpm20_restart(device_t dev, bool clear) 513 { 514 uint16_t startup_type; 515 516 startup_type = clear ? TPM2_SU_CLEAR : TPM2_SU_STATE; 517 return (tpm20_command(dev, TPM_CC_Startup, startup_type, 518 TPM2_RC_INITIALIZE, "Startup")); 519 } 520 521 static int 522 tpm20_save_state(device_t dev, bool suspend) 523 { 524 uint16_t shutdown_type; 525 526 shutdown_type = suspend ? TPM2_SU_STATE : TPM2_SU_CLEAR; 527 return (tpm20_command(dev, TPM_CC_Shutdown, shutdown_type, 528 TPM2_RC_SUCCESS, "Shutdown")); 529 } 530 531 int32_t 532 tpm20_get_timeout(uint32_t command) 533 { 534 int32_t timeout; 535 536 switch (command) { 537 case TPM_CC_CreatePrimary: 538 case TPM_CC_Create: 539 case TPM_CC_CreateLoaded: 540 timeout = TPM_TIMEOUT_LONG; 541 break; 542 case TPM_CC_SequenceComplete: 543 case TPM_CC_Startup: 544 case TPM_CC_SequenceUpdate: 545 case TPM_CC_GetCapability: 546 case TPM_CC_PCR_Extend: 547 case TPM_CC_EventSequenceComplete: 548 case TPM_CC_HashSequenceStart: 549 timeout = TPM_TIMEOUT_C; 550 break; 551 default: 552 timeout = TPM_TIMEOUT_B; 553 break; 554 } 555 return timeout; 556 } 557