[tpmdd-devel] [PATCH v3 6/6] tpm: pass multiple digests to tpm_pcr_extend()

Jarkko Sakkinen jarkko.sakkinen at linux.intel.com
Fri Jun 23 10:37:52 UTC 2017


On Wed, Jun 21, 2017 at 04:29:41PM +0200, Roberto Sassu wrote:
> This patch modifies the parameters of tpm_pcr_extend() by replacing the
> SHA1 digest with an array of digests and the number of array elements.
> 
> This completes the changes necessary to correctly extend PCRs of a TPM 2.0.

There is not well defined order before you are in the mainline.

> Each PCR bank will be extended with a digest calculated with the PCR bank
> algorithm. If the digest for a PCR bank has not been provided, the TPM
> driver pads/truncates the first digest, to extend that bank. TPM users
> should indicate in the event log in which sequence digests were passed
> to the TPM driver (if they didn't provide all the digests), or should
> pass to the driver a digest for each PCR bank.
> 
> Callers of tpm_pcr_extend(), pcrlock() and ima_pcr_extend(), have been
> modified to pass the new arguments. They pass to tpm_pcr_extend() an array
> with one element, containing the same SHA1 digest they were passing before
> this patch.
> 
> Signed-off-by: Roberto Sassu <roberto.sassu at huawei.com>

Please just do a function that takes crypto ID.

/Jarkko


> ---
>  drivers/char/tpm/tpm-interface.c   | 51 ++++++++++++++++++++++++++++++++------
>  drivers/char/tpm/tpm.h             |  6 -----
>  include/linux/tpm.h                | 12 +++++++--
>  security/integrity/ima/ima_queue.c |  4 ++-
>  security/keys/trusted.c            |  6 ++---
>  5 files changed, 59 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> index cf0cdb2..3b0d7a2 100644
> --- a/drivers/char/tpm/tpm-interface.c
> +++ b/drivers/char/tpm/tpm-interface.c
> @@ -871,44 +871,79 @@ static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
>  	return rc;
>  }
>  
> +static u32 tpm_get_digest_size(struct tpm_chip *chip, enum tpm2_algorithms algo)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(chip->active_banks) &&
> +	     chip->active_banks[i].alg_id != TPM2_ALG_ERROR; i++)
> +		if (chip->active_banks[i].alg_id == algo)
> +			return chip->active_banks[i].digest_size;
> +
> +	/* Callers should have checked which algorithms the TPM supports,
> +	 * or should have provided a SHA1 digest, which is always supported.
> +	 * If the passed algorithm is unknown, return the size of SHA1.
> +	 */
> +	return hash_digest_size[HASH_ALGO_SHA1];
> +}
> +
>  /**
>   * 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
> + * @count:	number of digests
> + * @digests:	array of digests
>   *
>   * 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.
>   */
> -int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
> +int tpm_pcr_extend(u32 chip_num, int pcr_idx, u32 count,
> +		   struct tpm2_digest *digests)
>  {
>  	int rc;
>  	struct tpm_chip *chip;
>  	struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)];
> -	u32 count = 0;
> -	int i;
> +	u32 first_digest_size;
> +	int i, j;
> +
> +	if (count == 0)
> +		return -EINVAL;
>  
>  	chip = tpm_chip_find_get(chip_num);
>  	if (chip == NULL)
>  		return -ENODEV;
>  
> +	first_digest_size = tpm_get_digest_size(chip, digests[0].alg_id);
> +
>  	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
>  		memset(digest_list, 0, sizeof(digest_list));
>  
>  		for (i = 0; i < ARRAY_SIZE(chip->active_banks) &&
>  		     chip->active_banks[i].alg_id != TPM2_ALG_ERROR; i++) {
> +			struct tpm_pcr_bank_info *bank = &chip->active_banks[i];
> +			u8 *cur_digest = digests[0].digest;
> +			u32 cur_digest_size = first_digest_size;
> +
> +			for (j = 0; j < count; j++) {
> +				if (digests[j].alg_id == bank->alg_id) {
> +					cur_digest = digests[j].digest;
> +					cur_digest_size = bank->digest_size;
> +					break;
> +				}
> +			}
> +
>  			digest_list[i].alg_id = chip->active_banks[i].alg_id;
> -			memcpy(digest_list[i].digest, hash, TPM_DIGEST_SIZE);
> -			count++;
> +			memcpy(digest_list[i].digest, cur_digest,
> +			       cur_digest_size);
>  		}
>  
> -		rc = tpm2_pcr_extend(chip, pcr_idx, count, digest_list);
> +		rc = tpm2_pcr_extend(chip, pcr_idx, i, digest_list);
>  		tpm_put_ops(chip);
>  		return rc;
>  	}
>  
> -	rc = tpm1_pcr_extend(chip, pcr_idx, hash,
> +	rc = tpm1_pcr_extend(chip, pcr_idx, digests[0].digest,
>  			     "attempting extend a PCR value");
>  	tpm_put_ops(chip);
>  	return rc;
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 75ec0d1..7c2f30b 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -34,7 +34,6 @@
>  #include <linux/acpi.h>
>  #include <linux/cdev.h>
>  #include <linux/highmem.h>
> -#include <crypto/hash_info.h>
>  
>  enum tpm_const {
>  	TPM_MINOR = 224,	/* officially assigned */
> @@ -386,11 +385,6 @@ struct tpm_cmd_t {
>  	tpm_cmd_params	params;
>  } __packed;
>  
> -struct tpm2_digest {
> -	u16 alg_id;
> -	u8 digest[SHA512_DIGEST_SIZE];
> -} __packed;
> -
>  /* A string buffer type for constructing TPM commands. This is based on the
>   * ideas of string buffer code in security/keys/trusted.h but is heap based
>   * in order to keep the stack usage minimal.
> diff --git a/include/linux/tpm.h b/include/linux/tpm.h
> index 49ec8fc..254d632 100644
> --- a/include/linux/tpm.h
> +++ b/include/linux/tpm.h
> @@ -36,6 +36,11 @@ struct tpm_chip;
>  struct trusted_key_payload;
>  struct trusted_key_options;
>  
> +struct tpm2_digest {
> +	u16 alg_id;
> +	u8 digest[SHA512_DIGEST_SIZE];
> +} __packed;
> +
>  enum TPM_OPS_FLAGS {
>  	TPM_OPS_AUTO_STARTUP = BIT(0),
>  };
> @@ -76,7 +81,8 @@ struct tpm_pcr_bank_info {
>  
>  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_pcr_extend(u32 chip_num, int pcr_idx, u32 count,
> +			  struct tpm2_digest *digests);
>  extern int tpm_get_pcr_banks_info(u32 chip_num,
>  				  struct tpm_pcr_bank_info *active_banks);
>  extern int tpm_send(u32 chip_num, void *cmd, size_t buflen);
> @@ -95,7 +101,9 @@ static inline int tpm_is_tpm2(u32 chip_num)
>  static inline int tpm_pcr_read(u32 chip_num, 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(u32 chip_num, int pcr_idx, u32 count,
> +				 struct tpm2_digest *digests)
> +{
>  	return -ENODEV;
>  }
>  static inline int tpm_get_pcr_banks_info(u32 chip_num,
> diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
> index d9aa5ab..f628968 100644
> --- a/security/integrity/ima/ima_queue.c
> +++ b/security/integrity/ima/ima_queue.c
> @@ -140,12 +140,14 @@ unsigned long ima_get_binary_runtime_size(void)
>  
>  static int ima_pcr_extend(const u8 *hash, int pcr)
>  {
> +	struct tpm2_digest digestarg = {.alg_id = TPM2_ALG_SHA1};
>  	int result = 0;
>  
>  	if (!ima_used_chip)
>  		return result;
>  
> -	result = tpm_pcr_extend(TPM_ANY_NUM, pcr, hash);
> +	memcpy(digestarg.digest, hash, IMA_DIGEST_SIZE);
> +	result = tpm_pcr_extend(TPM_ANY_NUM, pcr, 1, &digestarg);
>  	if (result != 0)
>  		pr_err("Error Communicating to TPM chip, result: %d\n", result);
>  	return result;
> diff --git a/security/keys/trusted.c b/security/keys/trusted.c
> index 435e86e..d6c0db8 100644
> --- a/security/keys/trusted.c
> +++ b/security/keys/trusted.c
> @@ -377,15 +377,15 @@ static int trusted_tpm_send(const u32 chip_num, unsigned char *cmd,
>   */
>  static int pcrlock(const int pcrnum)
>  {
> -	unsigned char hash[SHA1_DIGEST_SIZE];
> +	struct tpm2_digest digestarg = {.alg_id = TPM2_ALG_SHA1};
>  	int ret;
>  
>  	if (!capable(CAP_SYS_ADMIN))
>  		return -EPERM;
> -	ret = tpm_get_random(TPM_ANY_NUM, hash, SHA1_DIGEST_SIZE);
> +	ret = tpm_get_random(TPM_ANY_NUM, digestarg.digest, SHA1_DIGEST_SIZE);
>  	if (ret != SHA1_DIGEST_SIZE)
>  		return ret;
> -	return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0;
> +	return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, 1, &digestarg) ? -EINVAL : 0;
>  }
>  
>  /*
> -- 
> 2.9.3
> 
> 
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> tpmdd-devel mailing list
> tpmdd-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/tpmdd-devel
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the Linux-security-module-archive mailing list