Commit 84d4e8b6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull tpm updates from Jarkko Sakkinen:

 - Disable TCG_TPM2_HMAC from defconfig

   It causes performance issues, and breaks some atypical
   configurations.

 - simplify code using the new crypto library

 - misc fixes and cleanups

* tag 'tpmdd-next-v6.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd:
  tpm: Prevent local DOS via tpm/tpm0/ppi/*operations
  tpm: use a map for tpm2_calc_ordinal_duration()
  tpm_tis: Fix incorrect arguments in tpm_tis_probe_irq_single
  tpm: Use HMAC-SHA256 library instead of open-coded HMAC
  tpm: Compare HMAC values in constant time
  tpm: Disable TPM2_TCG_HMAC by default
parents 5472d60c a29ad21b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -29,10 +29,11 @@ if TCG_TPM

config TCG_TPM2_HMAC
	bool "Use HMAC and encrypted transactions on the TPM bus"
	default X86_64
	default n
	select CRYPTO_ECDH
	select CRYPTO_LIB_AESCFB
	select CRYPTO_LIB_SHA256
	select CRYPTO_LIB_UTILS
	help
	  Setting this causes us to deploy a scheme which uses request
	  and response HMACs in addition to encryption for
+1 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(suspend_pcr,
unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
{
	if (chip->flags & TPM_CHIP_FLAG_TPM2)
		return tpm2_calc_ordinal_duration(chip, ordinal);
		return tpm2_calc_ordinal_duration(ordinal);
	else
		return tpm1_calc_ordinal_duration(chip, ordinal);
}
+1 −1
Original line number Diff line number Diff line
@@ -299,7 +299,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip);
int tpm2_auto_startup(struct tpm_chip *chip);
void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
unsigned long tpm2_calc_ordinal_duration(u32 ordinal);
int tpm2_probe(struct tpm_chip *chip);
int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip);
int tpm2_find_cc(struct tpm_chip *chip, u32 cc);
+32 −95
Original line number Diff line number Diff line
@@ -28,120 +28,57 @@ static struct tpm2_hash tpm2_hash_map[] = {

int tpm2_get_timeouts(struct tpm_chip *chip)
{
	/* Fixed timeouts for TPM2 */
	chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
	chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B);
	chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C);
	chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D);

	/* PTP spec timeouts */
	chip->duration[TPM_SHORT] = msecs_to_jiffies(TPM2_DURATION_SHORT);
	chip->duration[TPM_MEDIUM] = msecs_to_jiffies(TPM2_DURATION_MEDIUM);
	chip->duration[TPM_LONG] = msecs_to_jiffies(TPM2_DURATION_LONG);

	/* Key creation commands long timeouts */
	chip->duration[TPM_LONG_LONG] =
		msecs_to_jiffies(TPM2_DURATION_LONG_LONG);

	chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS;

	return 0;
}

/**
 * tpm2_ordinal_duration_index() - returns an index to the chip duration table
 * @ordinal: TPM command ordinal.
 *
 * The function returns an index to the chip duration table
 * (enum tpm_duration), that describes the maximum amount of
 * time the chip could take to return the result for a  particular ordinal.
 *
 * The values of the MEDIUM, and LONG durations are taken
 * from the PC Client Profile (PTP) specification (750, 2000 msec)
 *
 * LONG_LONG is for commands that generates keys which empirically takes
 * a longer time on some systems.
 *
 * Return:
 * * TPM_MEDIUM
 * * TPM_LONG
 * * TPM_LONG_LONG
 * * TPM_UNDEFINED
/*
 * Contains the maximum durations in milliseconds for TPM2 commands.
 */
static u8 tpm2_ordinal_duration_index(u32 ordinal)
{
	switch (ordinal) {
	/* Startup */
	case TPM2_CC_STARTUP:                 /* 144 */
		return TPM_MEDIUM;

	case TPM2_CC_SELF_TEST:               /* 143 */
		return TPM_LONG;

	case TPM2_CC_GET_RANDOM:              /* 17B */
		return TPM_LONG;

	case TPM2_CC_SEQUENCE_UPDATE:         /* 15C */
		return TPM_MEDIUM;
	case TPM2_CC_SEQUENCE_COMPLETE:       /* 13E */
		return TPM_MEDIUM;
	case TPM2_CC_EVENT_SEQUENCE_COMPLETE: /* 185 */
		return TPM_MEDIUM;
	case TPM2_CC_HASH_SEQUENCE_START:     /* 186 */
		return TPM_MEDIUM;

	case TPM2_CC_VERIFY_SIGNATURE:        /* 177 */
		return TPM_LONG_LONG;

	case TPM2_CC_PCR_EXTEND:              /* 182 */
		return TPM_MEDIUM;

	case TPM2_CC_HIERARCHY_CONTROL:       /* 121 */
		return TPM_LONG;
	case TPM2_CC_HIERARCHY_CHANGE_AUTH:   /* 129 */
		return TPM_LONG;

	case TPM2_CC_GET_CAPABILITY:          /* 17A */
		return TPM_MEDIUM;

	case TPM2_CC_NV_READ:                 /* 14E */
		return TPM_LONG;

	case TPM2_CC_CREATE_PRIMARY:          /* 131 */
		return TPM_LONG_LONG;
	case TPM2_CC_CREATE:                  /* 153 */
		return TPM_LONG_LONG;
	case TPM2_CC_CREATE_LOADED:           /* 191 */
		return TPM_LONG_LONG;

	default:
		return TPM_UNDEFINED;
	}
}
static const struct {
	unsigned long ordinal;
	unsigned long duration;
} tpm2_ordinal_duration_map[] = {
	{TPM2_CC_STARTUP, 750},
	{TPM2_CC_SELF_TEST, 3000},
	{TPM2_CC_GET_RANDOM, 2000},
	{TPM2_CC_SEQUENCE_UPDATE, 750},
	{TPM2_CC_SEQUENCE_COMPLETE, 750},
	{TPM2_CC_EVENT_SEQUENCE_COMPLETE, 750},
	{TPM2_CC_HASH_SEQUENCE_START, 750},
	{TPM2_CC_VERIFY_SIGNATURE, 30000},
	{TPM2_CC_PCR_EXTEND, 750},
	{TPM2_CC_HIERARCHY_CONTROL, 2000},
	{TPM2_CC_HIERARCHY_CHANGE_AUTH, 2000},
	{TPM2_CC_GET_CAPABILITY, 750},
	{TPM2_CC_NV_READ, 2000},
	{TPM2_CC_CREATE_PRIMARY, 30000},
	{TPM2_CC_CREATE, 30000},
	{TPM2_CC_CREATE_LOADED, 30000},
};

/**
 * tpm2_calc_ordinal_duration() - calculate the maximum command duration
 * @chip:    TPM chip to use.
 * tpm2_calc_ordinal_duration() - Calculate the maximum command duration
 * @ordinal: TPM command ordinal.
 *
 * The function returns the maximum amount of time the chip could take
 * to return the result for a particular ordinal in jiffies.
 *
 * Return: A maximal duration time for an ordinal in jiffies.
 * Returns the maximum amount of time the chip is expected by kernel to
 * take in jiffies.
 */
unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
unsigned long tpm2_calc_ordinal_duration(u32 ordinal)
{
	unsigned int index;
	int i;

	index = tpm2_ordinal_duration_index(ordinal);
	for (i = 0; i < ARRAY_SIZE(tpm2_ordinal_duration_map); i++)
		if (ordinal == tpm2_ordinal_duration_map[i].ordinal)
			return msecs_to_jiffies(tpm2_ordinal_duration_map[i].duration);

	if (index != TPM_UNDEFINED)
		return chip->duration[index];
	else
	return msecs_to_jiffies(TPM2_DURATION_DEFAULT);
}


struct tpm2_pcr_read_out {
	__be32	update_cnt;
	__be32	pcr_selects_cnt;
+30 −74
Original line number Diff line number Diff line
@@ -69,8 +69,8 @@
#include <linux/unaligned.h>
#include <crypto/kpp.h>
#include <crypto/ecdh.h>
#include <crypto/hash.h>
#include <crypto/hmac.h>
#include <crypto/sha2.h>
#include <crypto/utils.h>

/* maximum number of names the TPM must remember for authorization */
#define AUTH_MAX_NAMES	3
@@ -384,51 +384,6 @@ EXPORT_SYMBOL_GPL(tpm_buf_append_hmac_session);
static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy,
			       u32 *handle, u8 *name);

/*
 * It turns out the crypto hmac(sha256) is hard for us to consume
 * because it assumes a fixed key and the TPM seems to change the key
 * on every operation, so we weld the hmac init and final functions in
 * here to give it the same usage characteristics as a regular hash
 */
static void tpm2_hmac_init(struct sha256_ctx *sctx, u8 *key, u32 key_len)
{
	u8 pad[SHA256_BLOCK_SIZE];
	int i;

	sha256_init(sctx);
	for (i = 0; i < sizeof(pad); i++) {
		if (i < key_len)
			pad[i] = key[i];
		else
			pad[i] = 0;
		pad[i] ^= HMAC_IPAD_VALUE;
	}
	sha256_update(sctx, pad, sizeof(pad));
}

static void tpm2_hmac_final(struct sha256_ctx *sctx, u8 *key, u32 key_len,
			    u8 *out)
{
	u8 pad[SHA256_BLOCK_SIZE];
	int i;

	for (i = 0; i < sizeof(pad); i++) {
		if (i < key_len)
			pad[i] = key[i];
		else
			pad[i] = 0;
		pad[i] ^= HMAC_OPAD_VALUE;
	}

	/* collect the final hash;  use out as temporary storage */
	sha256_final(sctx, out);

	sha256_init(sctx);
	sha256_update(sctx, pad, sizeof(pad));
	sha256_update(sctx, out, SHA256_DIGEST_SIZE);
	sha256_final(sctx, out);
}

/*
 * assume hash sha256 and nonces u, v of size SHA256_DIGEST_SIZE but
 * otherwise standard tpm2_KDFa.  Note output is in bytes not bits.
@@ -440,16 +395,16 @@ static void tpm2_KDFa(u8 *key, u32 key_len, const char *label, u8 *u,
	const __be32 bits = cpu_to_be32(bytes * 8);

	while (bytes > 0) {
		struct sha256_ctx sctx;
		struct hmac_sha256_ctx hctx;
		__be32 c = cpu_to_be32(counter);

		tpm2_hmac_init(&sctx, key, key_len);
		sha256_update(&sctx, (u8 *)&c, sizeof(c));
		sha256_update(&sctx, label, strlen(label)+1);
		sha256_update(&sctx, u, SHA256_DIGEST_SIZE);
		sha256_update(&sctx, v, SHA256_DIGEST_SIZE);
		sha256_update(&sctx, (u8 *)&bits, sizeof(bits));
		tpm2_hmac_final(&sctx, key, key_len, out);
		hmac_sha256_init_usingrawkey(&hctx, key, key_len);
		hmac_sha256_update(&hctx, (u8 *)&c, sizeof(c));
		hmac_sha256_update(&hctx, label, strlen(label) + 1);
		hmac_sha256_update(&hctx, u, SHA256_DIGEST_SIZE);
		hmac_sha256_update(&hctx, v, SHA256_DIGEST_SIZE);
		hmac_sha256_update(&hctx, (u8 *)&bits, sizeof(bits));
		hmac_sha256_final(&hctx, out);

		bytes -= SHA256_DIGEST_SIZE;
		counter++;
@@ -593,6 +548,7 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
	u32 attrs;
	u8 cphash[SHA256_DIGEST_SIZE];
	struct sha256_ctx sctx;
	struct hmac_sha256_ctx hctx;

	if (!auth)
		return;
@@ -704,14 +660,14 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
	sha256_final(&sctx, cphash);

	/* now calculate the hmac */
	tpm2_hmac_init(&sctx, auth->session_key, sizeof(auth->session_key)
		       + auth->passphrase_len);
	sha256_update(&sctx, cphash, sizeof(cphash));
	sha256_update(&sctx, auth->our_nonce, sizeof(auth->our_nonce));
	sha256_update(&sctx, auth->tpm_nonce, sizeof(auth->tpm_nonce));
	sha256_update(&sctx, &auth->attrs, 1);
	tpm2_hmac_final(&sctx, auth->session_key, sizeof(auth->session_key)
			+ auth->passphrase_len, hmac);
	hmac_sha256_init_usingrawkey(&hctx, auth->session_key,
				     sizeof(auth->session_key) +
					     auth->passphrase_len);
	hmac_sha256_update(&hctx, cphash, sizeof(cphash));
	hmac_sha256_update(&hctx, auth->our_nonce, sizeof(auth->our_nonce));
	hmac_sha256_update(&hctx, auth->tpm_nonce, sizeof(auth->tpm_nonce));
	hmac_sha256_update(&hctx, &auth->attrs, 1);
	hmac_sha256_final(&hctx, hmac);
}
EXPORT_SYMBOL(tpm_buf_fill_hmac_session);

@@ -751,6 +707,7 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
	u8 rphash[SHA256_DIGEST_SIZE];
	u32 attrs, cc;
	struct sha256_ctx sctx;
	struct hmac_sha256_ctx hctx;
	u16 tag = be16_to_cpu(head->tag);
	int parm_len, len, i, handles;

@@ -820,21 +777,20 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
	sha256_final(&sctx, rphash);

	/* now calculate the hmac */
	tpm2_hmac_init(&sctx, auth->session_key, sizeof(auth->session_key)
		       + auth->passphrase_len);
	sha256_update(&sctx, rphash, sizeof(rphash));
	sha256_update(&sctx, auth->tpm_nonce, sizeof(auth->tpm_nonce));
	sha256_update(&sctx, auth->our_nonce, sizeof(auth->our_nonce));
	sha256_update(&sctx, &auth->attrs, 1);
	hmac_sha256_init_usingrawkey(&hctx, auth->session_key,
				     sizeof(auth->session_key) +
					     auth->passphrase_len);
	hmac_sha256_update(&hctx, rphash, sizeof(rphash));
	hmac_sha256_update(&hctx, auth->tpm_nonce, sizeof(auth->tpm_nonce));
	hmac_sha256_update(&hctx, auth->our_nonce, sizeof(auth->our_nonce));
	hmac_sha256_update(&hctx, &auth->attrs, 1);
	/* we're done with the rphash, so put our idea of the hmac there */
	tpm2_hmac_final(&sctx, auth->session_key, sizeof(auth->session_key)
			+ auth->passphrase_len, rphash);
	if (memcmp(rphash, &buf->data[offset_s], SHA256_DIGEST_SIZE) == 0) {
		rc = 0;
	} else {
	hmac_sha256_final(&hctx, rphash);
	if (crypto_memneq(rphash, &buf->data[offset_s], SHA256_DIGEST_SIZE)) {
		dev_err(&chip->dev, "TPM: HMAC check failed\n");
		goto out;
	}
	rc = 0;

	/* now do response decryption */
	if (auth->attrs & TPM2_SA_ENCRYPT) {
Loading