19deb0eb7SJason Gunthorpe /* 29deb0eb7SJason Gunthorpe * Copyright (C) 2004 IBM Corporation 3afb5abc2SJarkko Sakkinen * Copyright (C) 2014 Intel Corporation 49deb0eb7SJason Gunthorpe * 59deb0eb7SJason Gunthorpe * Authors: 69deb0eb7SJason Gunthorpe * Leendert van Doorn <leendert@watson.ibm.com> 79deb0eb7SJason Gunthorpe * Dave Safford <safford@watson.ibm.com> 89deb0eb7SJason Gunthorpe * Reiner Sailer <sailer@watson.ibm.com> 99deb0eb7SJason Gunthorpe * Kylene Hall <kjhall@us.ibm.com> 109deb0eb7SJason Gunthorpe * 119deb0eb7SJason Gunthorpe * Maintained by: <tpmdd-devel@lists.sourceforge.net> 129deb0eb7SJason Gunthorpe * 139deb0eb7SJason Gunthorpe * Device driver for TCG/TCPA TPM (trusted platform module). 149deb0eb7SJason Gunthorpe * Specifications at www.trustedcomputinggroup.org 159deb0eb7SJason Gunthorpe * 169deb0eb7SJason Gunthorpe * This program is free software; you can redistribute it and/or 179deb0eb7SJason Gunthorpe * modify it under the terms of the GNU General Public License as 189deb0eb7SJason Gunthorpe * published by the Free Software Foundation, version 2 of the 199deb0eb7SJason Gunthorpe * License. 209deb0eb7SJason Gunthorpe * 219deb0eb7SJason Gunthorpe * Note, the TPM chip is not interrupt driven (only polling) 229deb0eb7SJason Gunthorpe * and can have very long timeouts (minutes!). Hence the unusual 239deb0eb7SJason Gunthorpe * calls to msleep. 249deb0eb7SJason Gunthorpe * 259deb0eb7SJason Gunthorpe */ 269deb0eb7SJason Gunthorpe 279deb0eb7SJason Gunthorpe #include <linux/poll.h> 289deb0eb7SJason Gunthorpe #include <linux/slab.h> 299deb0eb7SJason Gunthorpe #include <linux/mutex.h> 309deb0eb7SJason Gunthorpe #include <linux/spinlock.h> 319deb0eb7SJason Gunthorpe #include <linux/freezer.h> 32fd3ec366SThiebaud Weksteen #include <linux/tpm_eventlog.h> 339deb0eb7SJason Gunthorpe 349deb0eb7SJason Gunthorpe #include "tpm.h" 359deb0eb7SJason Gunthorpe 369deb0eb7SJason Gunthorpe /* 379deb0eb7SJason Gunthorpe * Bug workaround - some TPM's don't flush the most 389deb0eb7SJason Gunthorpe * recently changed pcr on suspend, so force the flush 399deb0eb7SJason Gunthorpe * with an extend to the selected _unused_ non-volatile pcr. 409deb0eb7SJason Gunthorpe */ 4195adc6b4STomas Winkler static u32 tpm_suspend_pcr; 429deb0eb7SJason Gunthorpe module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); 439deb0eb7SJason Gunthorpe MODULE_PARM_DESC(suspend_pcr, 4439f5712bSDmitry Torokhov "PCR to use for dummy writes to facilitate flush on suspend."); 459deb0eb7SJason Gunthorpe 46d856c00fSTomas Winkler /** 47d856c00fSTomas Winkler * tpm_calc_ordinal_duration() - calculate the maximum command duration 48d856c00fSTomas Winkler * @chip: TPM chip to use. 49d856c00fSTomas Winkler * @ordinal: TPM command ordinal. 50d856c00fSTomas Winkler * 51d856c00fSTomas Winkler * The function returns the maximum amount of time the chip could take 52d856c00fSTomas Winkler * to return the result for a particular ordinal in jiffies. 53d856c00fSTomas Winkler * 54d856c00fSTomas Winkler * Return: A maximal duration time for an ordinal in jiffies. 55d856c00fSTomas Winkler */ 56d856c00fSTomas Winkler unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) 57d856c00fSTomas Winkler { 58d856c00fSTomas Winkler if (chip->flags & TPM_CHIP_FLAG_TPM2) 59d856c00fSTomas Winkler return tpm2_calc_ordinal_duration(chip, ordinal); 60d856c00fSTomas Winkler else 61d856c00fSTomas Winkler return tpm1_calc_ordinal_duration(chip, ordinal); 62d856c00fSTomas Winkler } 63d856c00fSTomas Winkler EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); 64d856c00fSTomas Winkler 65*47a6c28bSJarkko Sakkinen static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz) 669deb0eb7SJason Gunthorpe { 67b34b77a9SJarkko Sakkinen struct tpm_header *header = buf; 68745b361eSJarkko Sakkinen int rc; 69745b361eSJarkko Sakkinen ssize_t len = 0; 709deb0eb7SJason Gunthorpe u32 count, ordinal; 719deb0eb7SJason Gunthorpe unsigned long stop; 729deb0eb7SJason Gunthorpe 73c3465a37SJarkko Sakkinen if (bufsiz < TPM_HEADER_SIZE) 74c3465a37SJarkko Sakkinen return -EINVAL; 75ebfd7532SJarkko Sakkinen 769deb0eb7SJason Gunthorpe if (bufsiz > TPM_BUFSIZE) 779deb0eb7SJason Gunthorpe bufsiz = TPM_BUFSIZE; 789deb0eb7SJason Gunthorpe 79720b0711SJarkko Sakkinen count = be32_to_cpu(header->length); 80720b0711SJarkko Sakkinen ordinal = be32_to_cpu(header->ordinal); 819deb0eb7SJason Gunthorpe if (count == 0) 829deb0eb7SJason Gunthorpe return -ENODATA; 839deb0eb7SJason Gunthorpe if (count > bufsiz) { 848cfffc9dSJason Gunthorpe dev_err(&chip->dev, 859deb0eb7SJason Gunthorpe "invalid count value %x %zx\n", count, bufsiz); 869deb0eb7SJason Gunthorpe return -E2BIG; 879deb0eb7SJason Gunthorpe } 889deb0eb7SJason Gunthorpe 8962c09e12SWinkler, Tomas rc = chip->ops->send(chip, buf, count); 909deb0eb7SJason Gunthorpe if (rc < 0) { 91402149c6SStefan Berger if (rc != -EPIPE) 928cfffc9dSJason Gunthorpe dev_err(&chip->dev, 93f5595f5bSJarkko Sakkinen "%s: send(): error %d\n", __func__, rc); 9429b47ce9SJarkko Sakkinen return rc; 959deb0eb7SJason Gunthorpe } 969deb0eb7SJason Gunthorpe 97f5595f5bSJarkko Sakkinen /* A sanity check. send() should just return zero on success e.g. 98f5595f5bSJarkko Sakkinen * not the command length. 99f5595f5bSJarkko Sakkinen */ 100f5595f5bSJarkko Sakkinen if (rc > 0) { 101f5595f5bSJarkko Sakkinen dev_warn(&chip->dev, 102f5595f5bSJarkko Sakkinen "%s: send(): invalid value %d\n", __func__, rc); 103f5595f5bSJarkko Sakkinen rc = 0; 104f5595f5bSJarkko Sakkinen } 105f5595f5bSJarkko Sakkinen 106570a3609SChristophe Ricard if (chip->flags & TPM_CHIP_FLAG_IRQ) 1079deb0eb7SJason Gunthorpe goto out_recv; 1089deb0eb7SJason Gunthorpe 109d856c00fSTomas Winkler stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); 1109deb0eb7SJason Gunthorpe do { 1115f82e9f0SJason Gunthorpe u8 status = chip->ops->status(chip); 1125f82e9f0SJason Gunthorpe if ((status & chip->ops->req_complete_mask) == 1135f82e9f0SJason Gunthorpe chip->ops->req_complete_val) 1149deb0eb7SJason Gunthorpe goto out_recv; 1159deb0eb7SJason Gunthorpe 1165f82e9f0SJason Gunthorpe if (chip->ops->req_canceled(chip, status)) { 1178cfffc9dSJason Gunthorpe dev_err(&chip->dev, "Operation Canceled\n"); 11829b47ce9SJarkko Sakkinen return -ECANCELED; 1199deb0eb7SJason Gunthorpe } 1209deb0eb7SJason Gunthorpe 12159f5a6b0SNayna Jain tpm_msleep(TPM_TIMEOUT_POLL); 1229deb0eb7SJason Gunthorpe rmb(); 1239deb0eb7SJason Gunthorpe } while (time_before(jiffies, stop)); 1249deb0eb7SJason Gunthorpe 1255f82e9f0SJason Gunthorpe chip->ops->cancel(chip); 1268cfffc9dSJason Gunthorpe dev_err(&chip->dev, "Operation Timed out\n"); 12729b47ce9SJarkko Sakkinen return -ETIME; 1289deb0eb7SJason Gunthorpe 1299deb0eb7SJason Gunthorpe out_recv: 13062c09e12SWinkler, Tomas len = chip->ops->recv(chip, buf, bufsiz); 131745b361eSJarkko Sakkinen if (len < 0) { 132745b361eSJarkko Sakkinen rc = len; 133304ff672SJarkko Sakkinen dev_err(&chip->dev, "tpm_transmit: tpm_recv: error %d\n", rc); 134304ff672SJarkko Sakkinen } else if (len < TPM_HEADER_SIZE || len != be32_to_cpu(header->length)) 135a147918eSJarkko Sakkinen rc = -EFAULT; 136a147918eSJarkko Sakkinen 137745b361eSJarkko Sakkinen return rc ? rc : len; 1389deb0eb7SJason Gunthorpe } 1399deb0eb7SJason Gunthorpe 140f865c196SWinkler, Tomas /** 141e2fb992dSJames Bottomley * tpm_transmit - Internal kernel interface to transmit TPM commands. 142412eb585SJarkko Sakkinen * @chip: a TPM chip to use 143412eb585SJarkko Sakkinen * @buf: a TPM command buffer 144e2fb992dSJames Bottomley * @bufsiz: length of the TPM command buffer 145e2fb992dSJames Bottomley * 146412eb585SJarkko Sakkinen * A wrapper around tpm_try_transmit() that handles TPM2_RC_RETRY returns from 147412eb585SJarkko Sakkinen * the TPM and retransmits the command after a delay up to a maximum wait of 148412eb585SJarkko Sakkinen * TPM2_DURATION_LONG. 149e2fb992dSJames Bottomley * 150412eb585SJarkko Sakkinen * Note that TPM 1.x never returns TPM2_RC_RETRY so the retry logic is TPM 2.0 151412eb585SJarkko Sakkinen * only. 152e2fb992dSJames Bottomley * 153e2fb992dSJames Bottomley * Return: 154412eb585SJarkko Sakkinen * * The response length - OK 155412eb585SJarkko Sakkinen * * -errno - A system error 156e2fb992dSJames Bottomley */ 157*47a6c28bSJarkko Sakkinen ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz) 158e2fb992dSJames Bottomley { 159b34b77a9SJarkko Sakkinen struct tpm_header *header = (struct tpm_header *)buf; 160e2fb992dSJames Bottomley /* space for header and handles */ 161e2fb992dSJames Bottomley u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)]; 162e2fb992dSJames Bottomley unsigned int delay_msec = TPM2_DURATION_SHORT; 163e2fb992dSJames Bottomley u32 rc = 0; 164e2fb992dSJames Bottomley ssize_t ret; 1655faafbabSJarkko Sakkinen const size_t save_size = min(sizeof(save), bufsiz); 1662be8ffedSJames Bottomley /* the command code is where the return code will be */ 1672be8ffedSJames Bottomley u32 cc = be32_to_cpu(header->return_code); 168e2fb992dSJames Bottomley 169e2fb992dSJames Bottomley /* 170e2fb992dSJames Bottomley * Subtlety here: if we have a space, the handles will be 171e2fb992dSJames Bottomley * transformed, so when we restore the header we also have to 172e2fb992dSJames Bottomley * restore the handles. 173e2fb992dSJames Bottomley */ 174e2fb992dSJames Bottomley memcpy(save, buf, save_size); 175e2fb992dSJames Bottomley 176e2fb992dSJames Bottomley for (;;) { 177*47a6c28bSJarkko Sakkinen ret = tpm_try_transmit(chip, buf, bufsiz); 178e2fb992dSJames Bottomley if (ret < 0) 179e2fb992dSJames Bottomley break; 180e2fb992dSJames Bottomley rc = be32_to_cpu(header->return_code); 1812be8ffedSJames Bottomley if (rc != TPM2_RC_RETRY && rc != TPM2_RC_TESTING) 1822be8ffedSJames Bottomley break; 1832be8ffedSJames Bottomley /* 1842be8ffedSJames Bottomley * return immediately if self test returns test 1852be8ffedSJames Bottomley * still running to shorten boot time. 1862be8ffedSJames Bottomley */ 1872be8ffedSJames Bottomley if (rc == TPM2_RC_TESTING && cc == TPM2_CC_SELF_TEST) 188e2fb992dSJames Bottomley break; 18992980756SNayna Jain 190e2fb992dSJames Bottomley if (delay_msec > TPM2_DURATION_LONG) { 1912be8ffedSJames Bottomley if (rc == TPM2_RC_RETRY) 1922be8ffedSJames Bottomley dev_err(&chip->dev, "in retry loop\n"); 1932be8ffedSJames Bottomley else 1942be8ffedSJames Bottomley dev_err(&chip->dev, 1952be8ffedSJames Bottomley "self test is still running\n"); 196e2fb992dSJames Bottomley break; 197e2fb992dSJames Bottomley } 198e2fb992dSJames Bottomley tpm_msleep(delay_msec); 19992980756SNayna Jain delay_msec *= 2; 200e2fb992dSJames Bottomley memcpy(buf, save, save_size); 201e2fb992dSJames Bottomley } 202e2fb992dSJames Bottomley return ret; 203e2fb992dSJames Bottomley } 204412eb585SJarkko Sakkinen 205e2fb992dSJames Bottomley /** 20665520d46SWinkler, Tomas * tpm_transmit_cmd - send a tpm command to the device 207412eb585SJarkko Sakkinen * @chip: a TPM chip to use 208412eb585SJarkko Sakkinen * @buf: a TPM command buffer 209c659af78SStefan Berger * @min_rsp_body_length: minimum expected length of response body 210f865c196SWinkler, Tomas * @desc: command description used in the error message 211f865c196SWinkler, Tomas * 212f865c196SWinkler, Tomas * Return: 213412eb585SJarkko Sakkinen * * 0 - OK 214412eb585SJarkko Sakkinen * * -errno - A system error 215412eb585SJarkko Sakkinen * * TPM_RC - A TPM error 216f865c196SWinkler, Tomas */ 2175faafbabSJarkko Sakkinen ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf, 218*47a6c28bSJarkko Sakkinen size_t min_rsp_body_length, const char *desc) 2199deb0eb7SJason Gunthorpe { 220b34b77a9SJarkko Sakkinen const struct tpm_header *header = (struct tpm_header *)buf->data; 2219deb0eb7SJason Gunthorpe int err; 222c659af78SStefan Berger ssize_t len; 2239deb0eb7SJason Gunthorpe 224*47a6c28bSJarkko Sakkinen len = tpm_transmit(chip, buf->data, PAGE_SIZE); 2259deb0eb7SJason Gunthorpe if (len < 0) 2269deb0eb7SJason Gunthorpe return len; 22787155b73SJarkko Sakkinen 22887155b73SJarkko Sakkinen err = be32_to_cpu(header->return_code); 2290d6d0d62SJavier Martinez Canillas if (err != 0 && err != TPM_ERR_DISABLED && err != TPM_ERR_DEACTIVATED 23008a8112aSJerry Snitselaar && err != TPM2_RC_TESTING && desc) 2318cfffc9dSJason Gunthorpe dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err, 23271ed848fSJarkko Sakkinen desc); 233c659af78SStefan Berger if (err) 2349deb0eb7SJason Gunthorpe return err; 235c659af78SStefan Berger 236c659af78SStefan Berger if (len < min_rsp_body_length + TPM_HEADER_SIZE) 237c659af78SStefan Berger return -EFAULT; 238c659af78SStefan Berger 239c659af78SStefan Berger return 0; 2409deb0eb7SJason Gunthorpe } 241be4c9acfSStefan Berger EXPORT_SYMBOL_GPL(tpm_transmit_cmd); 2429deb0eb7SJason Gunthorpe 2439deb0eb7SJason Gunthorpe int tpm_get_timeouts(struct tpm_chip *chip) 2449deb0eb7SJason Gunthorpe { 245d1d253cfSJason Gunthorpe if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS) 246d1d253cfSJason Gunthorpe return 0; 247d1d253cfSJason Gunthorpe 24870a3199aSTomas Winkler if (chip->flags & TPM_CHIP_FLAG_TPM2) 24970a3199aSTomas Winkler return tpm2_get_timeouts(chip); 25070a3199aSTomas Winkler else 25170a3199aSTomas Winkler return tpm1_get_timeouts(chip); 2529deb0eb7SJason Gunthorpe } 2539deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_get_timeouts); 2549deb0eb7SJason Gunthorpe 2559deb0eb7SJason Gunthorpe /** 256aad887f6SJarkko Sakkinen * tpm_is_tpm2 - do we a have a TPM2 chip? 257aad887f6SJarkko Sakkinen * @chip: a &struct tpm_chip instance, %NULL for the default chip 258954650efSJarkko Sakkinen * 259aad887f6SJarkko Sakkinen * Return: 260aad887f6SJarkko Sakkinen * 1 if we have a TPM2 chip. 261aad887f6SJarkko Sakkinen * 0 if we don't have a TPM2 chip. 262aad887f6SJarkko Sakkinen * A negative number for system errors (errno). 263954650efSJarkko Sakkinen */ 264aad887f6SJarkko Sakkinen int tpm_is_tpm2(struct tpm_chip *chip) 265954650efSJarkko Sakkinen { 266954650efSJarkko Sakkinen int rc; 267954650efSJarkko Sakkinen 268fc1d52b7SStefan Berger chip = tpm_find_get_ops(chip); 269aad887f6SJarkko Sakkinen if (!chip) 270954650efSJarkko Sakkinen return -ENODEV; 271954650efSJarkko Sakkinen 272954650efSJarkko Sakkinen rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0; 273954650efSJarkko Sakkinen 2744e26195fSJason Gunthorpe tpm_put_ops(chip); 275954650efSJarkko Sakkinen 276954650efSJarkko Sakkinen return rc; 277954650efSJarkko Sakkinen } 278954650efSJarkko Sakkinen EXPORT_SYMBOL_GPL(tpm_is_tpm2); 279954650efSJarkko Sakkinen 280954650efSJarkko Sakkinen /** 281aad887f6SJarkko Sakkinen * tpm_pcr_read - read a PCR value from SHA1 bank 282aad887f6SJarkko Sakkinen * @chip: a &struct tpm_chip instance, %NULL for the default chip 283aad887f6SJarkko Sakkinen * @pcr_idx: the PCR to be retrieved 284aad887f6SJarkko Sakkinen * @res_buf: the value of the PCR 2859deb0eb7SJason Gunthorpe * 286aad887f6SJarkko Sakkinen * Return: same as with tpm_transmit_cmd() 2879deb0eb7SJason Gunthorpe */ 28895adc6b4STomas Winkler int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) 2899deb0eb7SJason Gunthorpe { 2909deb0eb7SJason Gunthorpe int rc; 2919deb0eb7SJason Gunthorpe 292fc1d52b7SStefan Berger chip = tpm_find_get_ops(chip); 293aad887f6SJarkko Sakkinen if (!chip) 2949deb0eb7SJason Gunthorpe return -ENODEV; 295d4a31756STomas Winkler 2967a1d7e6dSJarkko Sakkinen if (chip->flags & TPM_CHIP_FLAG_TPM2) 2977a1d7e6dSJarkko Sakkinen rc = tpm2_pcr_read(chip, pcr_idx, res_buf); 2987a1d7e6dSJarkko Sakkinen else 299cfddcb05STomas Winkler rc = tpm1_pcr_read(chip, pcr_idx, res_buf); 300d4a31756STomas Winkler 3014e26195fSJason Gunthorpe tpm_put_ops(chip); 3029deb0eb7SJason Gunthorpe return rc; 3039deb0eb7SJason Gunthorpe } 3049deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_pcr_read); 3059deb0eb7SJason Gunthorpe 3069deb0eb7SJason Gunthorpe /** 307aad887f6SJarkko Sakkinen * tpm_pcr_extend - extend a PCR value in SHA1 bank. 308aad887f6SJarkko Sakkinen * @chip: a &struct tpm_chip instance, %NULL for the default chip 309aad887f6SJarkko Sakkinen * @pcr_idx: the PCR to be retrieved 310aad887f6SJarkko Sakkinen * @hash: the hash value used to extend the PCR value 3119deb0eb7SJason Gunthorpe * 312aad887f6SJarkko Sakkinen * Note: with TPM 2.0 extends also those banks with a known digest size to the 313aad887f6SJarkko Sakkinen * cryto subsystem in order to prevent malicious use of those PCR banks. In the 314aad887f6SJarkko Sakkinen * future we should dynamically determine digest sizes. 315aad887f6SJarkko Sakkinen * 316aad887f6SJarkko Sakkinen * Return: same as with tpm_transmit_cmd() 3179deb0eb7SJason Gunthorpe */ 31895adc6b4STomas Winkler int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash) 3199deb0eb7SJason Gunthorpe { 3209deb0eb7SJason Gunthorpe int rc; 321c1f92b4bSNayna Jain struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)]; 322c1f92b4bSNayna Jain u32 count = 0; 323c1f92b4bSNayna Jain int i; 3249deb0eb7SJason Gunthorpe 325fc1d52b7SStefan Berger chip = tpm_find_get_ops(chip); 326aad887f6SJarkko Sakkinen if (!chip) 3279deb0eb7SJason Gunthorpe return -ENODEV; 3289deb0eb7SJason Gunthorpe 3297a1d7e6dSJarkko Sakkinen if (chip->flags & TPM_CHIP_FLAG_TPM2) { 330c1f92b4bSNayna Jain memset(digest_list, 0, sizeof(digest_list)); 331c1f92b4bSNayna Jain 33270ea1636SDan Carpenter for (i = 0; i < ARRAY_SIZE(chip->active_banks) && 33370ea1636SDan Carpenter chip->active_banks[i] != TPM2_ALG_ERROR; i++) { 334c1f92b4bSNayna Jain digest_list[i].alg_id = chip->active_banks[i]; 335c1f92b4bSNayna Jain memcpy(digest_list[i].digest, hash, TPM_DIGEST_SIZE); 336c1f92b4bSNayna Jain count++; 337c1f92b4bSNayna Jain } 338c1f92b4bSNayna Jain 339c1f92b4bSNayna Jain rc = tpm2_pcr_extend(chip, pcr_idx, count, digest_list); 3404e26195fSJason Gunthorpe tpm_put_ops(chip); 3417a1d7e6dSJarkko Sakkinen return rc; 3427a1d7e6dSJarkko Sakkinen } 3437a1d7e6dSJarkko Sakkinen 344175d5b2aSRoberto Sassu rc = tpm1_pcr_extend(chip, pcr_idx, hash, 3459deb0eb7SJason Gunthorpe "attempting extend a PCR value"); 3464e26195fSJason Gunthorpe tpm_put_ops(chip); 3479deb0eb7SJason Gunthorpe return rc; 3489deb0eb7SJason Gunthorpe } 3499deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_pcr_extend); 3509deb0eb7SJason Gunthorpe 3519deb0eb7SJason Gunthorpe /** 352aad887f6SJarkko Sakkinen * tpm_send - send a TPM command 353aad887f6SJarkko Sakkinen * @chip: a &struct tpm_chip instance, %NULL for the default chip 354aad887f6SJarkko Sakkinen * @cmd: a TPM command buffer 355aad887f6SJarkko Sakkinen * @buflen: the length of the TPM command buffer 356aad887f6SJarkko Sakkinen * 357aad887f6SJarkko Sakkinen * Return: same as with tpm_transmit_cmd() 358aad887f6SJarkko Sakkinen */ 359aad887f6SJarkko Sakkinen int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen) 3609deb0eb7SJason Gunthorpe { 361412eb585SJarkko Sakkinen struct tpm_buf buf; 3629deb0eb7SJason Gunthorpe int rc; 3639deb0eb7SJason Gunthorpe 364fc1d52b7SStefan Berger chip = tpm_find_get_ops(chip); 365aad887f6SJarkko Sakkinen if (!chip) 3669deb0eb7SJason Gunthorpe return -ENODEV; 3679deb0eb7SJason Gunthorpe 368412eb585SJarkko Sakkinen rc = tpm_buf_init(&buf, 0, 0); 369412eb585SJarkko Sakkinen if (rc) 370412eb585SJarkko Sakkinen goto out; 371412eb585SJarkko Sakkinen 372412eb585SJarkko Sakkinen memcpy(buf.data, cmd, buflen); 373*47a6c28bSJarkko Sakkinen rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to a send a command"); 374412eb585SJarkko Sakkinen tpm_buf_destroy(&buf); 375412eb585SJarkko Sakkinen out: 3764e26195fSJason Gunthorpe tpm_put_ops(chip); 3779deb0eb7SJason Gunthorpe return rc; 3789deb0eb7SJason Gunthorpe } 3799deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_send); 3809deb0eb7SJason Gunthorpe 381b03c4370STomas Winkler int tpm_auto_startup(struct tpm_chip *chip) 382b03c4370STomas Winkler { 383b03c4370STomas Winkler int rc; 384b03c4370STomas Winkler 385b03c4370STomas Winkler if (!(chip->ops->flags & TPM_OPS_AUTO_STARTUP)) 386b03c4370STomas Winkler return 0; 387b03c4370STomas Winkler 388b03c4370STomas Winkler if (chip->flags & TPM_CHIP_FLAG_TPM2) 389b03c4370STomas Winkler rc = tpm2_auto_startup(chip); 390b03c4370STomas Winkler else 391b03c4370STomas Winkler rc = tpm1_auto_startup(chip); 392b03c4370STomas Winkler 393b03c4370STomas Winkler return rc; 394b03c4370STomas Winkler } 395b03c4370STomas Winkler 3969deb0eb7SJason Gunthorpe /* 3979deb0eb7SJason Gunthorpe * We are about to suspend. Save the TPM state 3989deb0eb7SJason Gunthorpe * so that it can be restored. 3999deb0eb7SJason Gunthorpe */ 4009deb0eb7SJason Gunthorpe int tpm_pm_suspend(struct device *dev) 4019deb0eb7SJason Gunthorpe { 402ec03c50bSStefan Berger struct tpm_chip *chip = dev_get_drvdata(dev); 403c82a330cSTomas Winkler int rc = 0; 4049deb0eb7SJason Gunthorpe 405c82a330cSTomas Winkler if (!chip) 4069deb0eb7SJason Gunthorpe return -ENODEV; 4079deb0eb7SJason Gunthorpe 408b5d0ebc9SEnric Balletbo i Serra if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED) 409b5d0ebc9SEnric Balletbo i Serra return 0; 410b5d0ebc9SEnric Balletbo i Serra 411a3fbfae8SJarkko Sakkinen if (chip->flags & TPM_CHIP_FLAG_TPM2) { 412a3fbfae8SJarkko Sakkinen mutex_lock(&chip->tpm_mutex); 413*47a6c28bSJarkko Sakkinen if (!tpm_chip_start(chip)) { 41474d6b3ceSJarkko Sakkinen tpm2_shutdown(chip, TPM2_SU_STATE); 415*47a6c28bSJarkko Sakkinen tpm_chip_stop(chip); 416a3fbfae8SJarkko Sakkinen } 417a3fbfae8SJarkko Sakkinen mutex_unlock(&chip->tpm_mutex); 418a3fbfae8SJarkko Sakkinen } else { 419c82a330cSTomas Winkler rc = tpm1_pm_suspend(chip, tpm_suspend_pcr); 420a3fbfae8SJarkko Sakkinen } 4219deb0eb7SJason Gunthorpe 4229deb0eb7SJason Gunthorpe return rc; 4239deb0eb7SJason Gunthorpe } 4249deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_pm_suspend); 4259deb0eb7SJason Gunthorpe 4269deb0eb7SJason Gunthorpe /* 4279deb0eb7SJason Gunthorpe * Resume from a power safe. The BIOS already restored 4289deb0eb7SJason Gunthorpe * the TPM state. 4299deb0eb7SJason Gunthorpe */ 4309deb0eb7SJason Gunthorpe int tpm_pm_resume(struct device *dev) 4319deb0eb7SJason Gunthorpe { 432ec03c50bSStefan Berger struct tpm_chip *chip = dev_get_drvdata(dev); 4339deb0eb7SJason Gunthorpe 4349deb0eb7SJason Gunthorpe if (chip == NULL) 4359deb0eb7SJason Gunthorpe return -ENODEV; 4369deb0eb7SJason Gunthorpe 4379deb0eb7SJason Gunthorpe return 0; 4389deb0eb7SJason Gunthorpe } 4399deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_pm_resume); 4409deb0eb7SJason Gunthorpe 4419deb0eb7SJason Gunthorpe /** 442aad887f6SJarkko Sakkinen * tpm_get_random() - get random bytes from the TPM's RNG 443aad887f6SJarkko Sakkinen * @chip: a &struct tpm_chip instance, %NULL for the default chip 4449deb0eb7SJason Gunthorpe * @out: destination buffer for the random bytes 4459deb0eb7SJason Gunthorpe * @max: the max number of bytes to write to @out 4469deb0eb7SJason Gunthorpe * 4477aee9c52STomas Winkler * Return: number of random bytes read or a negative error value. 4489deb0eb7SJason Gunthorpe */ 449aad887f6SJarkko Sakkinen int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max) 4509deb0eb7SJason Gunthorpe { 451433d390fSTomas Winkler int rc; 4529deb0eb7SJason Gunthorpe 453433d390fSTomas Winkler if (!out || max > TPM_MAX_RNG_DATA) 4543e14d83eSJarkko Sakkinen return -EINVAL; 4553e14d83eSJarkko Sakkinen 456fc1d52b7SStefan Berger chip = tpm_find_get_ops(chip); 457aad887f6SJarkko Sakkinen if (!chip) 4589deb0eb7SJason Gunthorpe return -ENODEV; 4599deb0eb7SJason Gunthorpe 460433d390fSTomas Winkler if (chip->flags & TPM_CHIP_FLAG_TPM2) 461433d390fSTomas Winkler rc = tpm2_get_random(chip, out, max); 462433d390fSTomas Winkler else 463433d390fSTomas Winkler rc = tpm1_get_random(chip, out, max); 4649deb0eb7SJason Gunthorpe 4654e26195fSJason Gunthorpe tpm_put_ops(chip); 466433d390fSTomas Winkler return rc; 4679deb0eb7SJason Gunthorpe } 4689deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_get_random); 4699deb0eb7SJason Gunthorpe 470954650efSJarkko Sakkinen /** 471aad887f6SJarkko Sakkinen * tpm_seal_trusted() - seal a trusted key payload 472aad887f6SJarkko Sakkinen * @chip: a &struct tpm_chip instance, %NULL for the default chip 473954650efSJarkko Sakkinen * @options: authentication values and other options 474954650efSJarkko Sakkinen * @payload: the key data in clear and encrypted form 475954650efSJarkko Sakkinen * 476aad887f6SJarkko Sakkinen * Note: only TPM 2.0 chip are supported. TPM 1.x implementation is located in 477aad887f6SJarkko Sakkinen * the keyring subsystem. 478aad887f6SJarkko Sakkinen * 479aad887f6SJarkko Sakkinen * Return: same as with tpm_transmit_cmd() 480954650efSJarkko Sakkinen */ 481aad887f6SJarkko Sakkinen int tpm_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, 482954650efSJarkko Sakkinen struct trusted_key_options *options) 483954650efSJarkko Sakkinen { 484954650efSJarkko Sakkinen int rc; 485954650efSJarkko Sakkinen 486fc1d52b7SStefan Berger chip = tpm_find_get_ops(chip); 487aad887f6SJarkko Sakkinen if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2)) 488954650efSJarkko Sakkinen return -ENODEV; 489954650efSJarkko Sakkinen 490954650efSJarkko Sakkinen rc = tpm2_seal_trusted(chip, payload, options); 491954650efSJarkko Sakkinen 4924e26195fSJason Gunthorpe tpm_put_ops(chip); 493954650efSJarkko Sakkinen return rc; 494954650efSJarkko Sakkinen } 495954650efSJarkko Sakkinen EXPORT_SYMBOL_GPL(tpm_seal_trusted); 496954650efSJarkko Sakkinen 497954650efSJarkko Sakkinen /** 498954650efSJarkko Sakkinen * tpm_unseal_trusted() - unseal a trusted key 499aad887f6SJarkko Sakkinen * @chip: a &struct tpm_chip instance, %NULL for the default chip 500954650efSJarkko Sakkinen * @options: authentication values and other options 501954650efSJarkko Sakkinen * @payload: the key data in clear and encrypted form 502954650efSJarkko Sakkinen * 503aad887f6SJarkko Sakkinen * Note: only TPM 2.0 chip are supported. TPM 1.x implementation is located in 504aad887f6SJarkko Sakkinen * the keyring subsystem. 505aad887f6SJarkko Sakkinen * 506aad887f6SJarkko Sakkinen * Return: same as with tpm_transmit_cmd() 507954650efSJarkko Sakkinen */ 508aad887f6SJarkko Sakkinen int tpm_unseal_trusted(struct tpm_chip *chip, 509aad887f6SJarkko Sakkinen struct trusted_key_payload *payload, 510954650efSJarkko Sakkinen struct trusted_key_options *options) 511954650efSJarkko Sakkinen { 512954650efSJarkko Sakkinen int rc; 513954650efSJarkko Sakkinen 514fc1d52b7SStefan Berger chip = tpm_find_get_ops(chip); 515aad887f6SJarkko Sakkinen if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2)) 516954650efSJarkko Sakkinen return -ENODEV; 517954650efSJarkko Sakkinen 518954650efSJarkko Sakkinen rc = tpm2_unseal_trusted(chip, payload, options); 519954650efSJarkko Sakkinen 5204e26195fSJason Gunthorpe tpm_put_ops(chip); 5214e26195fSJason Gunthorpe 522954650efSJarkko Sakkinen return rc; 523954650efSJarkko Sakkinen } 524954650efSJarkko Sakkinen EXPORT_SYMBOL_GPL(tpm_unseal_trusted); 525954650efSJarkko Sakkinen 526313d21eeSJarkko Sakkinen static int __init tpm_init(void) 527313d21eeSJarkko Sakkinen { 528313d21eeSJarkko Sakkinen int rc; 529313d21eeSJarkko Sakkinen 530313d21eeSJarkko Sakkinen tpm_class = class_create(THIS_MODULE, "tpm"); 531313d21eeSJarkko Sakkinen if (IS_ERR(tpm_class)) { 532313d21eeSJarkko Sakkinen pr_err("couldn't create tpm class\n"); 533313d21eeSJarkko Sakkinen return PTR_ERR(tpm_class); 534313d21eeSJarkko Sakkinen } 535313d21eeSJarkko Sakkinen 536fdc915f7SJames Bottomley tpmrm_class = class_create(THIS_MODULE, "tpmrm"); 537fdc915f7SJames Bottomley if (IS_ERR(tpmrm_class)) { 538fdc915f7SJames Bottomley pr_err("couldn't create tpmrm class\n"); 5399e1b74a6STadeusz Struk rc = PTR_ERR(tpmrm_class); 5409e1b74a6STadeusz Struk goto out_destroy_tpm_class; 541fdc915f7SJames Bottomley } 542fdc915f7SJames Bottomley 543fdc915f7SJames Bottomley rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES, "tpm"); 544313d21eeSJarkko Sakkinen if (rc < 0) { 545313d21eeSJarkko Sakkinen pr_err("tpm: failed to allocate char dev region\n"); 5469e1b74a6STadeusz Struk goto out_destroy_tpmrm_class; 5479e1b74a6STadeusz Struk } 5489e1b74a6STadeusz Struk 5499e1b74a6STadeusz Struk rc = tpm_dev_common_init(); 5509e1b74a6STadeusz Struk if (rc) { 5519e1b74a6STadeusz Struk pr_err("tpm: failed to allocate char dev region\n"); 5529e1b74a6STadeusz Struk goto out_unreg_chrdev; 553313d21eeSJarkko Sakkinen } 554313d21eeSJarkko Sakkinen 555313d21eeSJarkko Sakkinen return 0; 5569e1b74a6STadeusz Struk 5579e1b74a6STadeusz Struk out_unreg_chrdev: 5589e1b74a6STadeusz Struk unregister_chrdev_region(tpm_devt, 2 * TPM_NUM_DEVICES); 5599e1b74a6STadeusz Struk out_destroy_tpmrm_class: 5609e1b74a6STadeusz Struk class_destroy(tpmrm_class); 5619e1b74a6STadeusz Struk out_destroy_tpm_class: 5629e1b74a6STadeusz Struk class_destroy(tpm_class); 5639e1b74a6STadeusz Struk 5649e1b74a6STadeusz Struk return rc; 565313d21eeSJarkko Sakkinen } 566313d21eeSJarkko Sakkinen 567313d21eeSJarkko Sakkinen static void __exit tpm_exit(void) 568313d21eeSJarkko Sakkinen { 56915516788SStefan Berger idr_destroy(&dev_nums_idr); 570313d21eeSJarkko Sakkinen class_destroy(tpm_class); 571fdc915f7SJames Bottomley class_destroy(tpmrm_class); 572fdc915f7SJames Bottomley unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES); 5739e1b74a6STadeusz Struk tpm_dev_common_exit(); 574313d21eeSJarkko Sakkinen } 575313d21eeSJarkko Sakkinen 576313d21eeSJarkko Sakkinen subsys_initcall(tpm_init); 577313d21eeSJarkko Sakkinen module_exit(tpm_exit); 578313d21eeSJarkko Sakkinen 5799deb0eb7SJason Gunthorpe MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); 5809deb0eb7SJason Gunthorpe MODULE_DESCRIPTION("TPM Driver"); 5819deb0eb7SJason Gunthorpe MODULE_VERSION("2.0"); 5829deb0eb7SJason Gunthorpe MODULE_LICENSE("GPL"); 583