1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2016 Intel Corporation 4 * 5 * Authors: 6 * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> 7 * 8 * Maintained by: <tpmdd-devel@lists.sourceforge.net> 9 * 10 * This file contains TPM2 protocol implementations of the commands 11 * used by the kernel internally. 12 */ 13 14 #include <linux/gfp.h> 15 #include <linux/unaligned.h> 16 #include "tpm.h" 17 18 static void tpm2_flush_sessions(struct tpm_chip *chip, struct tpm_space *space) 19 { 20 int i; 21 22 for (i = 0; i < ARRAY_SIZE(space->session_tbl); i++) { 23 if (space->session_tbl[i]) 24 tpm2_flush_context(chip, space->session_tbl[i]); 25 } 26 } 27 28 int tpm2_init_space(struct tpm_space *space, unsigned int buf_size) 29 { 30 space->context_buf = kzalloc(buf_size, GFP_KERNEL); 31 if (!space->context_buf) 32 return -ENOMEM; 33 34 space->session_buf = kzalloc(buf_size, GFP_KERNEL); 35 if (space->session_buf == NULL) { 36 kfree(space->context_buf); 37 /* Prevent caller getting a dangling pointer. */ 38 space->context_buf = NULL; 39 return -ENOMEM; 40 } 41 42 space->buf_size = buf_size; 43 return 0; 44 } 45 46 void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space) 47 { 48 49 if (tpm_try_get_ops(chip) == 0) { 50 tpm2_flush_sessions(chip, space); 51 tpm_put_ops(chip); 52 } 53 54 kfree(space->context_buf); 55 kfree(space->session_buf); 56 } 57 58 int tpm2_load_context(struct tpm_chip *chip, u8 *buf, 59 unsigned int *offset, u32 *handle) 60 { 61 struct tpm2_context *ctx; 62 unsigned int body_size; 63 int rc; 64 65 struct tpm_buf *tbuf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); 66 if (!tbuf) 67 return -ENOMEM; 68 69 tpm_buf_init(tbuf, TPM_BUFSIZE); 70 tpm_buf_reset(tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD); 71 72 ctx = (struct tpm2_context *)&buf[*offset]; 73 body_size = sizeof(*ctx) + be16_to_cpu(ctx->blob_size); 74 tpm_buf_append(tbuf, &buf[*offset], body_size); 75 76 rc = tpm_transmit_cmd(chip, tbuf, 4, NULL); 77 if (rc < 0) { 78 dev_warn(&chip->dev, "%s: failed with a system error %d\n", 79 __func__, rc); 80 return -EFAULT; 81 } else if (tpm2_rc_value(rc) == TPM2_RC_HANDLE || 82 rc == TPM2_RC_REFERENCE_H0) { 83 /* 84 * TPM_RC_HANDLE means that the session context can't 85 * be loaded because of an internal counter mismatch 86 * that makes the TPM think there might have been a 87 * replay. This might happen if the context was saved 88 * and loaded outside the space. 89 * 90 * TPM_RC_REFERENCE_H0 means the session has been 91 * flushed outside the space 92 */ 93 *handle = 0; 94 return -ENOENT; 95 } else if (tpm2_rc_value(rc) == TPM2_RC_INTEGRITY) { 96 return -EINVAL; 97 } else if (rc > 0) { 98 dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n", 99 __func__, rc); 100 return -EFAULT; 101 } 102 103 *handle = be32_to_cpup((__be32 *)&tbuf->data[TPM_HEADER_SIZE]); 104 *offset += body_size; 105 return 0; 106 } 107 108 int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf, 109 unsigned int buf_size, unsigned int *offset) 110 { 111 unsigned int body_size; 112 int rc; 113 114 struct tpm_buf *tbuf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); 115 if (!tbuf) 116 return -ENOMEM; 117 118 tpm_buf_init(tbuf, TPM_BUFSIZE); 119 tpm_buf_reset(tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE); 120 tpm_buf_append_u32(tbuf, handle); 121 122 rc = tpm_transmit_cmd(chip, tbuf, 0, NULL); 123 if (rc < 0) { 124 dev_warn(&chip->dev, "%s: failed with a system error %d\n", 125 __func__, rc); 126 return -EFAULT; 127 } else if (tpm2_rc_value(rc) == TPM2_RC_REFERENCE_H0) { 128 return -ENOENT; 129 } else if (rc) { 130 dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n", 131 __func__, rc); 132 return -EFAULT; 133 } 134 135 body_size = tpm_buf_length(tbuf) - TPM_HEADER_SIZE; 136 if ((*offset + body_size) > buf_size) { 137 dev_warn(&chip->dev, "%s: out of backing storage\n", __func__); 138 return -ENOMEM; 139 } 140 141 memcpy(&buf[*offset], &tbuf->data[TPM_HEADER_SIZE], body_size); 142 *offset += body_size; 143 return 0; 144 } 145 146 void tpm2_flush_space(struct tpm_chip *chip) 147 { 148 struct tpm_space *space = &chip->work_space; 149 int i; 150 151 if (!space) 152 return; 153 154 for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) 155 if (space->context_tbl[i] && ~space->context_tbl[i]) 156 tpm2_flush_context(chip, space->context_tbl[i]); 157 158 tpm2_flush_sessions(chip, space); 159 } 160 161 static int tpm2_load_space(struct tpm_chip *chip) 162 { 163 struct tpm_space *space = &chip->work_space; 164 unsigned int offset; 165 int i; 166 int rc; 167 168 for (i = 0, offset = 0; i < ARRAY_SIZE(space->context_tbl); i++) { 169 if (!space->context_tbl[i]) 170 continue; 171 172 /* sanity check, should never happen */ 173 if (~space->context_tbl[i]) { 174 dev_err(&chip->dev, "context table is inconsistent"); 175 return -EFAULT; 176 } 177 178 rc = tpm2_load_context(chip, space->context_buf, &offset, 179 &space->context_tbl[i]); 180 if (rc) 181 return rc; 182 } 183 184 for (i = 0, offset = 0; i < ARRAY_SIZE(space->session_tbl); i++) { 185 u32 handle; 186 187 if (!space->session_tbl[i]) 188 continue; 189 190 rc = tpm2_load_context(chip, space->session_buf, 191 &offset, &handle); 192 if (rc == -ENOENT) { 193 /* load failed, just forget session */ 194 space->session_tbl[i] = 0; 195 } else if (rc) { 196 tpm2_flush_space(chip); 197 return rc; 198 } 199 if (handle != space->session_tbl[i]) { 200 dev_warn(&chip->dev, "session restored to wrong handle\n"); 201 tpm2_flush_space(chip); 202 return -EFAULT; 203 } 204 } 205 206 return 0; 207 } 208 209 static bool tpm2_map_to_phandle(struct tpm_space *space, void *handle) 210 { 211 u32 vhandle = be32_to_cpup((__be32 *)handle); 212 u32 phandle; 213 int i; 214 215 i = 0xFFFFFF - (vhandle & 0xFFFFFF); 216 if (i >= ARRAY_SIZE(space->context_tbl) || !space->context_tbl[i]) 217 return false; 218 219 phandle = space->context_tbl[i]; 220 *((__be32 *)handle) = cpu_to_be32(phandle); 221 return true; 222 } 223 224 static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd) 225 { 226 struct tpm_space *space = &chip->work_space; 227 unsigned int nr_handles; 228 u32 attrs; 229 __be32 *handle; 230 int i; 231 232 i = tpm2_find_cc(chip, cc); 233 if (i < 0) 234 return -EINVAL; 235 236 attrs = chip->cc_attrs_tbl[i]; 237 nr_handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0); 238 239 handle = (__be32 *)&cmd[TPM_HEADER_SIZE]; 240 for (i = 0; i < nr_handles; i++, handle++) { 241 if ((be32_to_cpu(*handle) & 0xFF000000) == TPM2_HT_TRANSIENT) { 242 if (!tpm2_map_to_phandle(space, handle)) 243 return -EINVAL; 244 } 245 } 246 247 return 0; 248 } 249 250 static int tpm_find_and_validate_cc(struct tpm_chip *chip, 251 struct tpm_space *space, 252 const void *cmd, size_t len) 253 { 254 const struct tpm_header *header = (const void *)cmd; 255 int i; 256 u32 cc; 257 u32 attrs; 258 unsigned int nr_handles; 259 260 if (len < TPM_HEADER_SIZE || !chip->nr_commands) 261 return -EINVAL; 262 263 cc = be32_to_cpu(header->ordinal); 264 265 i = tpm2_find_cc(chip, cc); 266 if (i < 0) { 267 dev_dbg(&chip->dev, "0x%04X is an invalid command\n", 268 cc); 269 return -EOPNOTSUPP; 270 } 271 272 attrs = chip->cc_attrs_tbl[i]; 273 nr_handles = 274 4 * ((attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0)); 275 if (len < TPM_HEADER_SIZE + 4 * nr_handles) 276 goto err_len; 277 278 return cc; 279 err_len: 280 dev_dbg(&chip->dev, "%s: insufficient command length %zu", __func__, 281 len); 282 return -EINVAL; 283 } 284 285 int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd, 286 size_t cmdsiz) 287 { 288 int rc; 289 int cc; 290 291 if (!space) 292 return 0; 293 294 cc = tpm_find_and_validate_cc(chip, space, cmd, cmdsiz); 295 if (cc < 0) 296 return cc; 297 298 memcpy(&chip->work_space.context_tbl, &space->context_tbl, 299 sizeof(space->context_tbl)); 300 memcpy(&chip->work_space.session_tbl, &space->session_tbl, 301 sizeof(space->session_tbl)); 302 memcpy(chip->work_space.context_buf, space->context_buf, 303 space->buf_size); 304 memcpy(chip->work_space.session_buf, space->session_buf, 305 space->buf_size); 306 307 rc = tpm2_load_space(chip); 308 if (rc) { 309 tpm2_flush_space(chip); 310 return rc; 311 } 312 313 rc = tpm2_map_command(chip, cc, cmd); 314 if (rc) { 315 tpm2_flush_space(chip); 316 return rc; 317 } 318 319 chip->last_cc = cc; 320 return 0; 321 } 322 323 static bool tpm2_add_session(struct tpm_chip *chip, u32 handle) 324 { 325 struct tpm_space *space = &chip->work_space; 326 int i; 327 328 for (i = 0; i < ARRAY_SIZE(space->session_tbl); i++) 329 if (space->session_tbl[i] == 0) 330 break; 331 332 if (i == ARRAY_SIZE(space->session_tbl)) 333 return false; 334 335 space->session_tbl[i] = handle; 336 return true; 337 } 338 339 static u32 tpm2_map_to_vhandle(struct tpm_space *space, u32 phandle, bool alloc) 340 { 341 int i; 342 343 for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) { 344 if (alloc) { 345 if (!space->context_tbl[i]) { 346 space->context_tbl[i] = phandle; 347 break; 348 } 349 } else if (space->context_tbl[i] == phandle) 350 break; 351 } 352 353 if (i == ARRAY_SIZE(space->context_tbl)) 354 return 0; 355 356 return TPM2_HT_TRANSIENT | (0xFFFFFF - i); 357 } 358 359 static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp, 360 size_t len) 361 { 362 struct tpm_space *space = &chip->work_space; 363 struct tpm_header *header = (struct tpm_header *)rsp; 364 u32 phandle; 365 u32 phandle_type; 366 u32 vhandle; 367 u32 attrs; 368 int i; 369 370 if (be32_to_cpu(header->return_code) != TPM2_RC_SUCCESS) 371 return 0; 372 373 i = tpm2_find_cc(chip, cc); 374 /* sanity check, should never happen */ 375 if (i < 0) 376 return -EFAULT; 377 378 attrs = chip->cc_attrs_tbl[i]; 379 if (!((attrs >> TPM2_CC_ATTR_RHANDLE) & 1)) 380 return 0; 381 382 phandle = be32_to_cpup((__be32 *)&rsp[TPM_HEADER_SIZE]); 383 phandle_type = phandle & 0xFF000000; 384 385 switch (phandle_type) { 386 case TPM2_HT_TRANSIENT: 387 vhandle = tpm2_map_to_vhandle(space, phandle, true); 388 if (!vhandle) 389 goto out_no_slots; 390 391 *(__be32 *)&rsp[TPM_HEADER_SIZE] = cpu_to_be32(vhandle); 392 break; 393 case TPM2_HT_HMAC_SESSION: 394 case TPM2_HT_POLICY_SESSION: 395 if (!tpm2_add_session(chip, phandle)) 396 goto out_no_slots; 397 break; 398 default: 399 dev_err(&chip->dev, "%s: unknown handle 0x%08X\n", 400 __func__, phandle); 401 break; 402 } 403 404 return 0; 405 out_no_slots: 406 tpm2_flush_context(chip, phandle); 407 dev_warn(&chip->dev, "%s: out of slots for 0x%08X\n", __func__, 408 phandle); 409 return -ENOMEM; 410 } 411 412 struct tpm2_cap_handles { 413 u8 more_data; 414 __be32 capability; 415 __be32 count; 416 __be32 handles[]; 417 } __packed; 418 419 static int tpm2_map_response_body(struct tpm_chip *chip, u32 cc, u8 *rsp, 420 size_t len) 421 { 422 struct tpm_space *space = &chip->work_space; 423 struct tpm_header *header = (struct tpm_header *)rsp; 424 struct tpm2_cap_handles *data; 425 u32 phandle; 426 u32 phandle_type; 427 u32 vhandle; 428 int i; 429 int j; 430 431 if (cc != TPM2_CC_GET_CAPABILITY || 432 be32_to_cpu(header->return_code) != TPM2_RC_SUCCESS) { 433 return 0; 434 } 435 436 if (len < TPM_HEADER_SIZE + 9) 437 return -EFAULT; 438 439 data = (void *)&rsp[TPM_HEADER_SIZE]; 440 if (be32_to_cpu(data->capability) != TPM2_CAP_HANDLES) 441 return 0; 442 443 if (be32_to_cpu(data->count) > (UINT_MAX - TPM_HEADER_SIZE - 9) / 4) 444 return -EFAULT; 445 446 if (len != TPM_HEADER_SIZE + 9 + 4 * be32_to_cpu(data->count)) 447 return -EFAULT; 448 449 for (i = 0, j = 0; i < be32_to_cpu(data->count); i++) { 450 phandle = be32_to_cpup((__be32 *)&data->handles[i]); 451 phandle_type = phandle & 0xFF000000; 452 453 switch (phandle_type) { 454 case TPM2_HT_TRANSIENT: 455 vhandle = tpm2_map_to_vhandle(space, phandle, false); 456 if (!vhandle) 457 break; 458 459 data->handles[j] = cpu_to_be32(vhandle); 460 j++; 461 break; 462 463 default: 464 data->handles[j] = cpu_to_be32(phandle); 465 j++; 466 break; 467 } 468 469 } 470 471 header->length = cpu_to_be32(TPM_HEADER_SIZE + 9 + 4 * j); 472 data->count = cpu_to_be32(j); 473 return 0; 474 } 475 476 static int tpm2_save_space(struct tpm_chip *chip) 477 { 478 struct tpm_space *space = &chip->work_space; 479 unsigned int offset; 480 int i; 481 int rc; 482 483 for (i = 0, offset = 0; i < ARRAY_SIZE(space->context_tbl); i++) { 484 if (!(space->context_tbl[i] && ~space->context_tbl[i])) 485 continue; 486 487 rc = tpm2_save_context(chip, space->context_tbl[i], 488 space->context_buf, space->buf_size, 489 &offset); 490 if (rc == -ENOENT) { 491 space->context_tbl[i] = 0; 492 continue; 493 } else if (rc) 494 return rc; 495 496 tpm2_flush_context(chip, space->context_tbl[i]); 497 space->context_tbl[i] = ~0; 498 } 499 500 for (i = 0, offset = 0; i < ARRAY_SIZE(space->session_tbl); i++) { 501 if (!space->session_tbl[i]) 502 continue; 503 504 rc = tpm2_save_context(chip, space->session_tbl[i], 505 space->session_buf, space->buf_size, 506 &offset); 507 if (rc == -ENOENT) { 508 /* handle error saving session, just forget it */ 509 space->session_tbl[i] = 0; 510 } else if (rc < 0) { 511 tpm2_flush_space(chip); 512 return rc; 513 } 514 } 515 516 return 0; 517 } 518 519 int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, 520 void *buf, size_t *bufsiz) 521 { 522 struct tpm_header *header = buf; 523 int rc; 524 525 if (!space) 526 return 0; 527 528 rc = tpm2_map_response_header(chip, chip->last_cc, buf, *bufsiz); 529 if (rc) { 530 tpm2_flush_space(chip); 531 goto out; 532 } 533 534 rc = tpm2_map_response_body(chip, chip->last_cc, buf, *bufsiz); 535 if (rc) { 536 tpm2_flush_space(chip); 537 goto out; 538 } 539 540 rc = tpm2_save_space(chip); 541 if (rc) { 542 tpm2_flush_space(chip); 543 goto out; 544 } 545 546 *bufsiz = be32_to_cpu(header->length); 547 548 memcpy(&space->context_tbl, &chip->work_space.context_tbl, 549 sizeof(space->context_tbl)); 550 memcpy(&space->session_tbl, &chip->work_space.session_tbl, 551 sizeof(space->session_tbl)); 552 memcpy(space->context_buf, chip->work_space.context_buf, 553 space->buf_size); 554 memcpy(space->session_buf, chip->work_space.session_buf, 555 space->buf_size); 556 557 return 0; 558 out: 559 dev_err(&chip->dev, "%s: error %d\n", __func__, rc); 560 return rc; 561 } 562 563 /* 564 * Put the reference to the main device. 565 */ 566 static void tpm_devs_release(struct device *dev) 567 { 568 struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs); 569 570 /* release the master device reference */ 571 put_device(&chip->dev); 572 } 573 574 /* 575 * Remove the device file for exposed TPM spaces and release the device 576 * reference. This may also release the reference to the master device. 577 */ 578 void tpm_devs_remove(struct tpm_chip *chip) 579 { 580 cdev_device_del(&chip->cdevs, &chip->devs); 581 put_device(&chip->devs); 582 } 583 584 /* 585 * Add a device file to expose TPM spaces. Also take a reference to the 586 * main device. 587 */ 588 int tpm_devs_add(struct tpm_chip *chip) 589 { 590 int rc; 591 592 device_initialize(&chip->devs); 593 chip->devs.parent = chip->dev.parent; 594 chip->devs.class = &tpmrm_class; 595 596 /* 597 * Get extra reference on main device to hold on behalf of devs. 598 * This holds the chip structure while cdevs is in use. The 599 * corresponding put is in the tpm_devs_release. 600 */ 601 get_device(&chip->dev); 602 chip->devs.release = tpm_devs_release; 603 chip->devs.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES); 604 cdev_init(&chip->cdevs, &tpmrm_fops); 605 chip->cdevs.owner = THIS_MODULE; 606 607 rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num); 608 if (rc) 609 goto err_put_devs; 610 611 rc = cdev_device_add(&chip->cdevs, &chip->devs); 612 if (rc) { 613 dev_err(&chip->devs, 614 "unable to cdev_device_add() %s, major %d, minor %d, err=%d\n", 615 dev_name(&chip->devs), MAJOR(chip->devs.devt), 616 MINOR(chip->devs.devt), rc); 617 goto err_put_devs; 618 } 619 620 return 0; 621 622 err_put_devs: 623 put_device(&chip->devs); 624 625 return rc; 626 } 627