Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aad887f6 authored by Jarkko Sakkinen's avatar Jarkko Sakkinen
Browse files

tpm: use struct tpm_chip for tpm_chip_find_get()



Device number (the character device index) is not a stable identifier
for a TPM chip. That is the reason why every call site passes
TPM_ANY_NUM to tpm_chip_find_get().

This commit changes the API in a way that instead a struct tpm_chip
instance is given and NULL means the default chip. In addition, this
commit refines the documentation to be up to date with the
implementation.

Suggested-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> (@chip_num -> @chip part)
Signed-off-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Reviewed-by: default avatarJason Gunthorpe <jgg@ziepe.ca>
Tested-by: default avatarPrasannaKumar Muralidharan <prasannatsmkumar@gmail.com>
parent 58cc1e4f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@

static int tpm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
	return tpm_get_random(TPM_ANY_NUM, data, max);
	return tpm_get_random(NULL, data, max);
}

static struct hwrng tpm_rng = {
+14 −10
Original line number Diff line number Diff line
@@ -81,21 +81,26 @@ void tpm_put_ops(struct tpm_chip *chip)
EXPORT_SYMBOL_GPL(tpm_put_ops);

/**
 * tpm_chip_find_get() - return tpm_chip for a given chip number
 * @chip_num: id to find
 * tpm_chip_find_get() - find and reserve a TPM chip
 * @chip:	a &struct tpm_chip instance, %NULL for the default chip
 *
 * The return'd chip has been tpm_try_get_ops'd and must be released via
 * tpm_put_ops
 * Finds a TPM chip and reserves its class device and operations. The chip must
 * be released with tpm_chip_put_ops() after use.
 *
 * Return:
 * A reserved &struct tpm_chip instance.
 * %NULL if a chip is not found.
 * %NULL if the chip is not available.
 */
struct tpm_chip *tpm_chip_find_get(int chip_num)
struct tpm_chip *tpm_chip_find_get(struct tpm_chip *chip)
{
	struct tpm_chip *chip, *res = NULL;
	struct tpm_chip *res = NULL;
	int chip_num = 0;
	int chip_prev;

	mutex_lock(&idr_lock);

	if (chip_num == TPM_ANY_NUM) {
		chip_num = 0;
	if (!chip) {
		do {
			chip_prev = chip_num;
			chip = idr_get_next(&dev_nums_idr, &chip_num);
@@ -105,8 +110,7 @@ struct tpm_chip *tpm_chip_find_get(int chip_num)
			}
		} while (chip_prev != chip_num);
	} else {
		chip = idr_find(&dev_nums_idr, chip_num);
		if (chip && !tpm_try_get_ops(chip))
		if (!tpm_try_get_ops(chip))
			res = chip;
	}

+71 −64
Original line number Diff line number Diff line
@@ -809,19 +809,20 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
}

/**
 * tpm_is_tpm2 - is the chip a TPM2 chip?
 * @chip_num:	tpm idx # or ANY
 * tpm_is_tpm2 - do we a have a TPM2 chip?
 * @chip:	a &struct tpm_chip instance, %NULL for the default chip
 *
 * Returns < 0 on error, and 1 or 0 on success depending whether the chip
 * is a TPM2 chip.
 * Return:
 * 1 if we have a TPM2 chip.
 * 0 if we don't have a TPM2 chip.
 * A negative number for system errors (errno).
 */
int tpm_is_tpm2(u32 chip_num)
int tpm_is_tpm2(struct tpm_chip *chip)
{
	struct tpm_chip *chip;
	int rc;

	chip = tpm_chip_find_get(chip_num);
	if (chip == NULL)
	chip = tpm_chip_find_get(chip);
	if (!chip)
		return -ENODEV;

	rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0;
@@ -833,23 +834,19 @@ int tpm_is_tpm2(u32 chip_num)
EXPORT_SYMBOL_GPL(tpm_is_tpm2);

/**
 * tpm_pcr_read - read a pcr value
 * @chip_num:	tpm idx # or ANY
 * @pcr_idx:	pcr idx to retrieve
 * @res_buf:	TPM_PCR value
 *		size of res_buf is 20 bytes (or NULL if you don't care)
 * tpm_pcr_read - read a PCR value from SHA1 bank
 * @chip:	a &struct tpm_chip instance, %NULL for the default chip
 * @pcr_idx:	the PCR to be retrieved
 * @res_buf:	the value of the PCR
 *
 * The TPM driver should be built-in, but for whatever reason it
 * isn't, protect against the chip disappearing, by incrementing
 * the module usage count.
 * Return: same as with tpm_transmit_cmd()
 */
int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf)
int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
{
	struct tpm_chip *chip;
	int rc;

	chip = tpm_chip_find_get(chip_num);
	if (chip == NULL)
	chip = tpm_chip_find_get(chip);
	if (!chip)
		return -ENODEV;
	if (chip->flags & TPM_CHIP_FLAG_TPM2)
		rc = tpm2_pcr_read(chip, pcr_idx, res_buf);
@@ -889,25 +886,26 @@ static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
}

/**
 * tpm_pcr_extend - extend pcr value with hash
 * @chip_num:	tpm idx # or AN&
 * @pcr_idx:	pcr idx to extend
 * @hash:	hash value used to extend pcr value
 * tpm_pcr_extend - extend a PCR value in SHA1 bank.
 * @chip:	a &struct tpm_chip instance, %NULL for the default chip
 * @pcr_idx:	the PCR to be retrieved
 * @hash:	the hash value used to extend the PCR value
 *
 * The TPM driver should be built-in, but for whatever reason it
 * isn't, protect against the chip disappearing, by incrementing
 * the module usage count.
 * Note: with TPM 2.0 extends also those banks with a known digest size to the
 * cryto subsystem in order to prevent malicious use of those PCR banks. In the
 * future we should dynamically determine digest sizes.
 *
 * Return: same as with tpm_transmit_cmd()
 */
int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
{
	int rc;
	struct tpm_chip *chip;
	struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)];
	u32 count = 0;
	int i;

	chip = tpm_chip_find_get(chip_num);
	if (chip == NULL)
	chip = tpm_chip_find_get(chip);
	if (!chip)
		return -ENODEV;

	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
@@ -1019,17 +1017,24 @@ int tpm1_auto_startup(struct tpm_chip *chip)
	return rc;
}

int tpm_send(u32 chip_num, void *cmd, size_t buflen)
/**
 * tpm_send - send a TPM command
 * @chip:	a &struct tpm_chip instance, %NULL for the default chip
 * @cmd:	a TPM command buffer
 * @buflen:	the length of the TPM command buffer
 *
 * Return: same as with tpm_transmit_cmd()
 */
int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)
{
	struct tpm_chip *chip;
	int rc;

	chip = tpm_chip_find_get(chip_num);
	if (chip == NULL)
	chip = tpm_chip_find_get(chip);
	if (!chip)
		return -ENODEV;

	rc = tpm_transmit_cmd(chip, NULL, cmd, buflen, 0, 0,
			      "attempting tpm_cmd");
			      "attempting to a send a command");
	tpm_put_ops(chip);
	return rc;
}
@@ -1127,16 +1132,15 @@ static const struct tpm_input_header tpm_getrandom_header = {
};

/**
 * tpm_get_random() - Get random bytes from the tpm's RNG
 * @chip_num: A specific chip number for the request or TPM_ANY_NUM
 * tpm_get_random() - get random bytes from the TPM's RNG
 * @chip:	a &struct tpm_chip instance, %NULL for the default chip
 * @out:	destination buffer for the random bytes
 * @max:	the max number of bytes to write to @out
 *
 * Returns < 0 on error and the number of bytes read on success
 * Return: same as with tpm_transmit_cmd()
 */
int tpm_get_random(u32 chip_num, u8 *out, size_t max)
int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
{
	struct tpm_chip *chip;
	struct tpm_cmd_t tpm_cmd;
	u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA), rlength;
	int err, total = 0, retries = 5;
@@ -1145,8 +1149,8 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
	if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
		return -EINVAL;

	chip = tpm_chip_find_get(chip_num);
	if (chip == NULL)
	chip = tpm_chip_find_get(chip);
	if (!chip)
		return -ENODEV;

	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
@@ -1188,22 +1192,23 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
EXPORT_SYMBOL_GPL(tpm_get_random);

/**
 * tpm_seal_trusted() - seal a trusted key
 * @chip_num: A specific chip number for the request or TPM_ANY_NUM
 * tpm_seal_trusted() - seal a trusted key payload
 * @chip:	a &struct tpm_chip instance, %NULL for the default chip
 * @options:	authentication values and other options
 * @payload:	the key data in clear and encrypted form
 *
 * Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips
 * are supported.
 * Note: only TPM 2.0 chip are supported. TPM 1.x implementation is located in
 * the keyring subsystem.
 *
 * Return: same as with tpm_transmit_cmd()
 */
int tpm_seal_trusted(u32 chip_num, struct trusted_key_payload *payload,
int tpm_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload,
		     struct trusted_key_options *options)
{
	struct tpm_chip *chip;
	int rc;

	chip = tpm_chip_find_get(chip_num);
	if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2))
	chip = tpm_chip_find_get(chip);
	if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2))
		return -ENODEV;

	rc = tpm2_seal_trusted(chip, payload, options);
@@ -1215,21 +1220,23 @@ EXPORT_SYMBOL_GPL(tpm_seal_trusted);

/**
 * tpm_unseal_trusted() - unseal a trusted key
 * @chip_num: A specific chip number for the request or TPM_ANY_NUM
 * @chip:	a &struct tpm_chip instance, %NULL for the default chip
 * @options:	authentication values and other options
 * @payload:	the key data in clear and encrypted form
 *
 * Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips
 * are supported.
 * Note: only TPM 2.0 chip are supported. TPM 1.x implementation is located in
 * the keyring subsystem.
 *
 * Return: same as with tpm_transmit_cmd()
 */
int tpm_unseal_trusted(u32 chip_num, struct trusted_key_payload *payload,
int tpm_unseal_trusted(struct tpm_chip *chip,
		       struct trusted_key_payload *payload,
		       struct trusted_key_options *options)
{
	struct tpm_chip *chip;
	int rc;

	chip = tpm_chip_find_get(chip_num);
	if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2))
	chip = tpm_chip_find_get(chip);
	if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2))
		return -ENODEV;

	rc = tpm2_unseal_trusted(chip, payload, options);
+1 −1
Original line number Diff line number Diff line
@@ -516,7 +516,7 @@ static inline void tpm_msleep(unsigned int delay_msec)
		     delay_msec * 1000);
};

struct tpm_chip *tpm_chip_find_get(int chip_num);
struct tpm_chip *tpm_chip_find_get(struct tpm_chip *chip);
__must_check int tpm_try_get_ops(struct tpm_chip *chip);
void tpm_put_ops(struct tpm_chip *chip);

+19 −19
Original line number Diff line number Diff line
@@ -24,11 +24,6 @@

#define TPM_DIGEST_SIZE 20	/* Max TPM v1.2 PCR size */

/*
 * Chip num is this value or a valid tpm idx
 */
#define	TPM_ANY_NUM 0xFFFF

struct tpm_chip;
struct trusted_key_payload;
struct trusted_key_options;
@@ -54,42 +49,47 @@ struct tpm_class_ops {

#if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)

extern int tpm_is_tpm2(u32 chip_num);
extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
extern int tpm_send(u32 chip_num, void *cmd, size_t buflen);
extern int tpm_get_random(u32 chip_num, u8 *data, size_t max);
extern int tpm_seal_trusted(u32 chip_num,
extern int tpm_is_tpm2(struct tpm_chip *chip);
extern int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
extern int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash);
extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen);
extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max);
extern int tpm_seal_trusted(struct tpm_chip *chip,
			    struct trusted_key_payload *payload,
			    struct trusted_key_options *options);
extern int tpm_unseal_trusted(u32 chip_num,
extern int tpm_unseal_trusted(struct tpm_chip *chip,
			      struct trusted_key_payload *payload,
			      struct trusted_key_options *options);
#else
static inline int tpm_is_tpm2(u32 chip_num)
static inline int tpm_is_tpm2(struct tpm_chip *chip)
{
	return -ENODEV;
}
static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
{
	return -ENODEV;
}
static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) {
static inline int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx,
				 const u8 *hash)
{
	return -ENODEV;
}
static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) {
static inline int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)
{
	return -ENODEV;
}
static inline int tpm_get_random(u32 chip_num, u8 *data, size_t max) {
static inline int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max)
{
	return -ENODEV;
}

static inline int tpm_seal_trusted(u32 chip_num,
static inline int tpm_seal_trusted(struct tpm_chip *chip,
				   struct trusted_key_payload *payload,
				   struct trusted_key_options *options)
{
	return -ENODEV;
}
static inline int tpm_unseal_trusted(u32 chip_num,
static inline int tpm_unseal_trusted(struct tpm_chip *chip,
				     struct trusted_key_payload *payload,
				     struct trusted_key_options *options)
{
Loading