0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <linux/poll.h>
0023 #include <linux/slab.h>
0024 #include <linux/mutex.h>
0025 #include <linux/spinlock.h>
0026 #include <linux/suspend.h>
0027 #include <linux/freezer.h>
0028 #include <linux/tpm_eventlog.h>
0029
0030 #include "tpm.h"
0031
0032
0033
0034
0035
0036
0037 static u32 tpm_suspend_pcr;
0038 module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);
0039 MODULE_PARM_DESC(suspend_pcr,
0040 "PCR to use for dummy writes to facilitate flush on suspend.");
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
0053 {
0054 if (chip->flags & TPM_CHIP_FLAG_TPM2)
0055 return tpm2_calc_ordinal_duration(chip, ordinal);
0056 else
0057 return tpm1_calc_ordinal_duration(chip, ordinal);
0058 }
0059 EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
0060
0061 static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz)
0062 {
0063 struct tpm_header *header = buf;
0064 int rc;
0065 ssize_t len = 0;
0066 u32 count, ordinal;
0067 unsigned long stop;
0068
0069 if (bufsiz < TPM_HEADER_SIZE)
0070 return -EINVAL;
0071
0072 if (bufsiz > TPM_BUFSIZE)
0073 bufsiz = TPM_BUFSIZE;
0074
0075 count = be32_to_cpu(header->length);
0076 ordinal = be32_to_cpu(header->ordinal);
0077 if (count == 0)
0078 return -ENODATA;
0079 if (count > bufsiz) {
0080 dev_err(&chip->dev,
0081 "invalid count value %x %zx\n", count, bufsiz);
0082 return -E2BIG;
0083 }
0084
0085 rc = chip->ops->send(chip, buf, count);
0086 if (rc < 0) {
0087 if (rc != -EPIPE)
0088 dev_err(&chip->dev,
0089 "%s: send(): error %d\n", __func__, rc);
0090 return rc;
0091 }
0092
0093
0094
0095
0096 if (rc > 0) {
0097 dev_warn(&chip->dev,
0098 "%s: send(): invalid value %d\n", __func__, rc);
0099 rc = 0;
0100 }
0101
0102 if (chip->flags & TPM_CHIP_FLAG_IRQ)
0103 goto out_recv;
0104
0105 stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
0106 do {
0107 u8 status = chip->ops->status(chip);
0108 if ((status & chip->ops->req_complete_mask) ==
0109 chip->ops->req_complete_val)
0110 goto out_recv;
0111
0112 if (chip->ops->req_canceled(chip, status)) {
0113 dev_err(&chip->dev, "Operation Canceled\n");
0114 return -ECANCELED;
0115 }
0116
0117 tpm_msleep(TPM_TIMEOUT_POLL);
0118 rmb();
0119 } while (time_before(jiffies, stop));
0120
0121 chip->ops->cancel(chip);
0122 dev_err(&chip->dev, "Operation Timed out\n");
0123 return -ETIME;
0124
0125 out_recv:
0126 len = chip->ops->recv(chip, buf, bufsiz);
0127 if (len < 0) {
0128 rc = len;
0129 dev_err(&chip->dev, "tpm_transmit: tpm_recv: error %d\n", rc);
0130 } else if (len < TPM_HEADER_SIZE || len != be32_to_cpu(header->length))
0131 rc = -EFAULT;
0132
0133 return rc ? rc : len;
0134 }
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153 ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz)
0154 {
0155 struct tpm_header *header = (struct tpm_header *)buf;
0156
0157 u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)];
0158 unsigned int delay_msec = TPM2_DURATION_SHORT;
0159 u32 rc = 0;
0160 ssize_t ret;
0161 const size_t save_size = min(sizeof(save), bufsiz);
0162
0163 u32 cc = be32_to_cpu(header->return_code);
0164
0165
0166
0167
0168
0169
0170 memcpy(save, buf, save_size);
0171
0172 for (;;) {
0173 ret = tpm_try_transmit(chip, buf, bufsiz);
0174 if (ret < 0)
0175 break;
0176 rc = be32_to_cpu(header->return_code);
0177 if (rc != TPM2_RC_RETRY && rc != TPM2_RC_TESTING)
0178 break;
0179
0180
0181
0182
0183 if (rc == TPM2_RC_TESTING && cc == TPM2_CC_SELF_TEST)
0184 break;
0185
0186 if (delay_msec > TPM2_DURATION_LONG) {
0187 if (rc == TPM2_RC_RETRY)
0188 dev_err(&chip->dev, "in retry loop\n");
0189 else
0190 dev_err(&chip->dev,
0191 "self test is still running\n");
0192 break;
0193 }
0194 tpm_msleep(delay_msec);
0195 delay_msec *= 2;
0196 memcpy(buf, save, save_size);
0197 }
0198 return ret;
0199 }
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213 ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf,
0214 size_t min_rsp_body_length, const char *desc)
0215 {
0216 const struct tpm_header *header = (struct tpm_header *)buf->data;
0217 int err;
0218 ssize_t len;
0219
0220 len = tpm_transmit(chip, buf->data, PAGE_SIZE);
0221 if (len < 0)
0222 return len;
0223
0224 err = be32_to_cpu(header->return_code);
0225 if (err != 0 && err != TPM_ERR_DISABLED && err != TPM_ERR_DEACTIVATED
0226 && err != TPM2_RC_TESTING && desc)
0227 dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err,
0228 desc);
0229 if (err)
0230 return err;
0231
0232 if (len < min_rsp_body_length + TPM_HEADER_SIZE)
0233 return -EFAULT;
0234
0235 return 0;
0236 }
0237 EXPORT_SYMBOL_GPL(tpm_transmit_cmd);
0238
0239 int tpm_get_timeouts(struct tpm_chip *chip)
0240 {
0241 if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS)
0242 return 0;
0243
0244 if (chip->flags & TPM_CHIP_FLAG_TPM2)
0245 return tpm2_get_timeouts(chip);
0246 else
0247 return tpm1_get_timeouts(chip);
0248 }
0249 EXPORT_SYMBOL_GPL(tpm_get_timeouts);
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260 int tpm_is_tpm2(struct tpm_chip *chip)
0261 {
0262 int rc;
0263
0264 chip = tpm_find_get_ops(chip);
0265 if (!chip)
0266 return -ENODEV;
0267
0268 rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0;
0269
0270 tpm_put_ops(chip);
0271
0272 return rc;
0273 }
0274 EXPORT_SYMBOL_GPL(tpm_is_tpm2);
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284 int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
0285 struct tpm_digest *digest)
0286 {
0287 int rc;
0288
0289 chip = tpm_find_get_ops(chip);
0290 if (!chip)
0291 return -ENODEV;
0292
0293 if (chip->flags & TPM_CHIP_FLAG_TPM2)
0294 rc = tpm2_pcr_read(chip, pcr_idx, digest, NULL);
0295 else
0296 rc = tpm1_pcr_read(chip, pcr_idx, digest->digest);
0297
0298 tpm_put_ops(chip);
0299 return rc;
0300 }
0301 EXPORT_SYMBOL_GPL(tpm_pcr_read);
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314 int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
0315 struct tpm_digest *digests)
0316 {
0317 int rc;
0318 int i;
0319
0320 chip = tpm_find_get_ops(chip);
0321 if (!chip)
0322 return -ENODEV;
0323
0324 for (i = 0; i < chip->nr_allocated_banks; i++) {
0325 if (digests[i].alg_id != chip->allocated_banks[i].alg_id) {
0326 rc = -EINVAL;
0327 goto out;
0328 }
0329 }
0330
0331 if (chip->flags & TPM_CHIP_FLAG_TPM2) {
0332 rc = tpm2_pcr_extend(chip, pcr_idx, digests);
0333 goto out;
0334 }
0335
0336 rc = tpm1_pcr_extend(chip, pcr_idx, digests[0].digest,
0337 "attempting extend a PCR value");
0338
0339 out:
0340 tpm_put_ops(chip);
0341 return rc;
0342 }
0343 EXPORT_SYMBOL_GPL(tpm_pcr_extend);
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353 int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)
0354 {
0355 struct tpm_buf buf;
0356 int rc;
0357
0358 chip = tpm_find_get_ops(chip);
0359 if (!chip)
0360 return -ENODEV;
0361
0362 buf.data = cmd;
0363 rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to a send a command");
0364
0365 tpm_put_ops(chip);
0366 return rc;
0367 }
0368 EXPORT_SYMBOL_GPL(tpm_send);
0369
0370 int tpm_auto_startup(struct tpm_chip *chip)
0371 {
0372 int rc;
0373
0374 if (!(chip->ops->flags & TPM_OPS_AUTO_STARTUP))
0375 return 0;
0376
0377 if (chip->flags & TPM_CHIP_FLAG_TPM2)
0378 rc = tpm2_auto_startup(chip);
0379 else
0380 rc = tpm1_auto_startup(chip);
0381
0382 return rc;
0383 }
0384
0385
0386
0387
0388
0389 int tpm_pm_suspend(struct device *dev)
0390 {
0391 struct tpm_chip *chip = dev_get_drvdata(dev);
0392 int rc = 0;
0393
0394 if (!chip)
0395 return -ENODEV;
0396
0397 if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
0398 goto suspended;
0399
0400 if ((chip->flags & TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED) &&
0401 !pm_suspend_via_firmware())
0402 goto suspended;
0403
0404 if (!tpm_chip_start(chip)) {
0405 if (chip->flags & TPM_CHIP_FLAG_TPM2)
0406 tpm2_shutdown(chip, TPM2_SU_STATE);
0407 else
0408 rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
0409
0410 tpm_chip_stop(chip);
0411 }
0412
0413 suspended:
0414 return rc;
0415 }
0416 EXPORT_SYMBOL_GPL(tpm_pm_suspend);
0417
0418
0419
0420
0421
0422 int tpm_pm_resume(struct device *dev)
0423 {
0424 struct tpm_chip *chip = dev_get_drvdata(dev);
0425
0426 if (chip == NULL)
0427 return -ENODEV;
0428
0429 return 0;
0430 }
0431 EXPORT_SYMBOL_GPL(tpm_pm_resume);
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441 int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
0442 {
0443 int rc;
0444
0445 if (!out || max > TPM_MAX_RNG_DATA)
0446 return -EINVAL;
0447
0448 chip = tpm_find_get_ops(chip);
0449 if (!chip)
0450 return -ENODEV;
0451
0452 if (chip->flags & TPM_CHIP_FLAG_TPM2)
0453 rc = tpm2_get_random(chip, out, max);
0454 else
0455 rc = tpm1_get_random(chip, out, max);
0456
0457 tpm_put_ops(chip);
0458 return rc;
0459 }
0460 EXPORT_SYMBOL_GPL(tpm_get_random);
0461
0462 static int __init tpm_init(void)
0463 {
0464 int rc;
0465
0466 tpm_class = class_create(THIS_MODULE, "tpm");
0467 if (IS_ERR(tpm_class)) {
0468 pr_err("couldn't create tpm class\n");
0469 return PTR_ERR(tpm_class);
0470 }
0471
0472 tpmrm_class = class_create(THIS_MODULE, "tpmrm");
0473 if (IS_ERR(tpmrm_class)) {
0474 pr_err("couldn't create tpmrm class\n");
0475 rc = PTR_ERR(tpmrm_class);
0476 goto out_destroy_tpm_class;
0477 }
0478
0479 rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES, "tpm");
0480 if (rc < 0) {
0481 pr_err("tpm: failed to allocate char dev region\n");
0482 goto out_destroy_tpmrm_class;
0483 }
0484
0485 rc = tpm_dev_common_init();
0486 if (rc) {
0487 pr_err("tpm: failed to allocate char dev region\n");
0488 goto out_unreg_chrdev;
0489 }
0490
0491 return 0;
0492
0493 out_unreg_chrdev:
0494 unregister_chrdev_region(tpm_devt, 2 * TPM_NUM_DEVICES);
0495 out_destroy_tpmrm_class:
0496 class_destroy(tpmrm_class);
0497 out_destroy_tpm_class:
0498 class_destroy(tpm_class);
0499
0500 return rc;
0501 }
0502
0503 static void __exit tpm_exit(void)
0504 {
0505 idr_destroy(&dev_nums_idr);
0506 class_destroy(tpm_class);
0507 class_destroy(tpmrm_class);
0508 unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES);
0509 tpm_dev_common_exit();
0510 }
0511
0512 subsys_initcall(tpm_init);
0513 module_exit(tpm_exit);
0514
0515 MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
0516 MODULE_DESCRIPTION("TPM Driver");
0517 MODULE_VERSION("2.0");
0518 MODULE_LICENSE("GPL");