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

Commit 33673dcb authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull security subsystem updates from James Morris:
 "This is basically a maintenance update for the TPM driver and EVM/IMA"

Fix up conflicts in lib/digsig.c and security/integrity/ima/ima_main.c

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (45 commits)
  tpm/ibmvtpm: build only when IBM pseries is configured
  ima: digital signature verification using asymmetric keys
  ima: rename hash calculation functions
  ima: use new crypto_shash API instead of old crypto_hash
  ima: add policy support for file system uuid
  evm: add file system uuid to EVM hmac
  tpm_tis: check pnp_acpi_device return code
  char/tpm/tpm_i2c_stm_st33: drop temporary variable for return value
  char/tpm/tpm_i2c_stm_st33: remove dead assignment in tpm_st33_i2c_probe
  char/tpm/tpm_i2c_stm_st33: Remove __devexit attribute
  char/tpm/tpm_i2c_stm_st33: Don't use memcpy for one byte assignment
  tpm_i2c_stm_st33: removed unused variables/code
  TPM: Wait for TPM_ACCESS tpmRegValidSts to go high at startup
  tpm: Fix cancellation of TPM commands (interrupt mode)
  tpm: Fix cancellation of TPM commands (polling mode)
  tpm: Store TPM vendor ID
  TPM: Work around buggy TPMs that block during continue self test
  tpm_i2c_stm_st33: fix oops when i2c client is unavailable
  char/tpm: Use struct dev_pm_ops for power management
  TPM: STMicroelectronics ST33 I2C BUILD STUFF
  ...
parents fe9453a1 5b266032
Loading
Loading
Loading
Loading
+185 −0
Original line number Diff line number Diff line
What:		/sys/class/misc/tpmX/device/
Date:		April 2005
KernelVersion:	2.6.12
Contact:	tpmdd-devel@lists.sf.net
Description:	The device/ directory under a specific TPM instance exposes
		the properties of that TPM chip


What:		/sys/class/misc/tpmX/device/active
Date:		April 2006
KernelVersion:	2.6.17
Contact:	tpmdd-devel@lists.sf.net
Description:	The "active" property prints a '1' if the TPM chip is accepting
		commands. An inactive TPM chip still contains all the state of
		an active chip (Storage Root Key, NVRAM, etc), and can be
		visible to the OS, but will only accept a restricted set of
		commands. See the TPM Main Specification part 2, Structures,
		section 17 for more information on which commands are
		available.

What:		/sys/class/misc/tpmX/device/cancel
Date:		June 2005
KernelVersion:	2.6.13
Contact:	tpmdd-devel@lists.sf.net
Description:	The "cancel" property allows you to cancel the currently
		pending TPM command. Writing any value to cancel will call the
		TPM vendor specific cancel operation.

What:		/sys/class/misc/tpmX/device/caps
Date:		April 2005
KernelVersion:	2.6.12
Contact:	tpmdd-devel@lists.sf.net
Description:	The "caps" property contains TPM manufacturer and version info.

		Example output:

		Manufacturer: 0x53544d20
		TCG version: 1.2
		Firmware version: 8.16

		Manufacturer is a hex dump of the 4 byte manufacturer info
		space in a TPM. TCG version shows the TCG TPM spec level that
		the chip supports. Firmware version is that of the chip and
		is manufacturer specific.

What:		/sys/class/misc/tpmX/device/durations
Date:		March 2011
KernelVersion:	3.1
Contact:	tpmdd-devel@lists.sf.net
Description:	The "durations" property shows the 3 vendor-specific values
		used to wait for a short, medium and long TPM command. All
		TPM commands are categorized as short, medium or long in
		execution time, so that the driver doesn't have to wait
		any longer than necessary before starting to poll for a
		result.

		Example output:

		3015000 4508000 180995000 [original]

		Here the short, medium and long durations are displayed in
		usecs. "[original]" indicates that the values are displayed
		unmodified from when they were queried from the chip.
		Durations can be modified in the case where a buggy chip
		reports them in msec instead of usec and they need to be
		scaled to be displayed in usecs. In this case "[adjusted]"
		will be displayed in place of "[original]".

What:		/sys/class/misc/tpmX/device/enabled
Date:		April 2006
KernelVersion:	2.6.17
Contact:	tpmdd-devel@lists.sf.net
Description:	The "enabled" property prints a '1' if the TPM chip is enabled,
		meaning that it should be visible to the OS. This property
		may be visible but produce a '0' after some operation that
		disables the TPM.

What:		/sys/class/misc/tpmX/device/owned
Date:		April 2006
KernelVersion:	2.6.17
Contact:	tpmdd-devel@lists.sf.net
Description:	The "owned" property produces a '1' if the TPM_TakeOwnership
		ordinal has been executed successfully in the chip. A '0'
		indicates that ownership hasn't been taken.

What:		/sys/class/misc/tpmX/device/pcrs
Date:		April 2005
KernelVersion:	2.6.12
Contact:	tpmdd-devel@lists.sf.net
Description:	The "pcrs" property will dump the current value of all Platform
		Configuration Registers in the TPM. Note that since these
		values may be constantly changing, the output is only valid
		for a snapshot in time.

		Example output:

		PCR-00: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
		PCR-01: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
		PCR-02: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
		PCR-03: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
		PCR-04: 3A 3F 78 0F 11 A4 B4 99 69 FC AA 80 CD 6E 39 57 C3 3B 22 75
		...

		The number of PCRs and hex bytes needed to represent a PCR
		value will vary depending on TPM chip version. For TPM 1.1 and
		1.2 chips, PCRs represent SHA-1 hashes, which are 20 bytes
		long. Use the "caps" property to determine TPM version.

What:		/sys/class/misc/tpmX/device/pubek
Date:		April 2005
KernelVersion:	2.6.12
Contact:	tpmdd-devel@lists.sf.net
Description:	The "pubek" property will return the TPM's public endorsement
		key if possible. If the TPM has had ownership established and
		is version 1.2, the pubek will not be available without the
		owner's authorization. Since the TPM driver doesn't store any
		secrets, it can't authorize its own request for the pubek,
		making it unaccessible. The public endorsement key is gener-
		ated at TPM menufacture time and exists for the life of the
		chip.

		Example output:

		Algorithm: 00 00 00 01
		Encscheme: 00 03
		Sigscheme: 00 01
		Parameters: 00 00 08 00 00 00 00 02 00 00 00 00
		Modulus length: 256
		Modulus:
		B4 76 41 82 C9 20 2C 10 18 40 BC 8B E5 44 4C 6C
		3A B2 92 0C A4 9B 2A 83 EB 5C 12 85 04 48 A0 B6
		1E E4 81 84 CE B2 F2 45 1C F0 85 99 61 02 4D EB
		86 C4 F7 F3 29 60 52 93 6B B2 E5 AB 8B A9 09 E3
		D7 0E 7D CA 41 BF 43 07 65 86 3C 8C 13 7A D0 8B
		82 5E 96 0B F8 1F 5F 34 06 DA A2 52 C1 A9 D5 26
		0F F4 04 4B D9 3F 2D F2 AC 2F 74 64 1F 8B CD 3E
		1E 30 38 6C 70 63 69 AB E2 50 DF 49 05 2E E1 8D
		6F 78 44 DA 57 43 69 EE 76 6C 38 8A E9 8E A3 F0
		A7 1F 3C A8 D0 12 15 3E CA 0E BD FA 24 CD 33 C6
		47 AE A4 18 83 8E 22 39 75 93 86 E6 FD 66 48 B6
		10 AD 94 14 65 F9 6A 17 78 BD 16 53 84 30 BF 70
		E0 DC 65 FD 3C C6 B0 1E BF B9 C1 B5 6C EF B1 3A
		F8 28 05 83 62 26 11 DC B4 6B 5A 97 FF 32 26 B6
		F7 02 71 CF 15 AE 16 DD D1 C1 8E A8 CF 9B 50 7B
		C3 91 FF 44 1E CF 7C 39 FE 17 77 21 20 BD CE 9B

		Possible values:

		Algorithm:	TPM_ALG_RSA			(1)
		Encscheme:	TPM_ES_RSAESPKCSv15		(2)
				TPM_ES_RSAESOAEP_SHA1_MGF1	(3)
		Sigscheme:	TPM_SS_NONE			(1)
		Parameters, a byte string of 3 u32 values:
			Key Length (bits):	00 00 08 00	(2048)
			Num primes:		00 00 00 02	(2)
			Exponent Size:		00 00 00 00	(0 means the
								 default exp)
		Modulus Length: 256 (bytes)
		Modulus:	The 256 byte Endorsement Key modulus

What:		/sys/class/misc/tpmX/device/temp_deactivated
Date:		April 2006
KernelVersion:	2.6.17
Contact:	tpmdd-devel@lists.sf.net
Description:	The "temp_deactivated" property returns a '1' if the chip has
		been temporarily dectivated, usually until the next power
		cycle. Whether a warm boot (reboot) will clear a TPM chip
		from a temp_deactivated state is platform specific.

What:		/sys/class/misc/tpmX/device/timeouts
Date:		March 2011
KernelVersion:	3.1
Contact:	tpmdd-devel@lists.sf.net
Description:	The "timeouts" property shows the 4 vendor-specific values
		for the TPM's interface spec timeouts. The use of these
		timeouts is defined by the TPM interface spec that the chip
		conforms to.

		Example output:

		750000 750000 750000 750000 [original]

		The four timeout values are shown in usecs, with a trailing
		"[original]" or "[adjusted]" depending on whether the values
		were scaled by the driver to be reported in usec from msecs.
+7 −3
Original line number Diff line number Diff line
@@ -18,17 +18,21 @@ Description:
		rule format: action [condition ...]

		action: measure | dont_measure | appraise | dont_appraise | audit
		condition:= base | lsm
			base:	[[func=] [mask=] [fsmagic=] [uid=] [fowner]]
		condition:= base | lsm  [option]
			base:	[[func=] [mask=] [fsmagic=] [fsuuid=] [uid=]
				 [fowner]]
			lsm:	[[subj_user=] [subj_role=] [subj_type=]
				 [obj_user=] [obj_role=] [obj_type=]]
			option:	[[appraise_type=]]

		base: 	func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK][MODULE_CHECK]
		base: 	func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
			mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
			fsmagic:= hex value
			fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6)
			uid:= decimal value
			fowner:=decimal value
		lsm:  	are LSM specific
		option:	appraise_type:= [imasig]

		default policy:
			# PROC_SUPER_MAGIC
+11 −1
Original line number Diff line number Diff line
@@ -75,10 +75,20 @@ config TCG_INFINEON

config TCG_IBMVTPM
	tristate "IBM VTPM Interface"
	depends on PPC64
	depends on PPC_PSERIES
	---help---
	  If you have IBM virtual TPM (VTPM) support say Yes and it
	  will be accessible from within Linux.  To compile this driver
	  as a module, choose M here; the module will be called tpm_ibmvtpm.

config TCG_ST33_I2C
        tristate "STMicroelectronics ST33 I2C TPM"
        depends on I2C
        depends on GPIOLIB
        ---help---
        If you have a TPM security chip from STMicroelectronics working with
        an I2C bus say Yes and it will be accessible from within Linux.
        To compile this driver as a module, choose M here; the module will be
        called tpm_stm_st33_i2c.

endif # TCG_TPM
+1 −0
Original line number Diff line number Diff line
@@ -17,3 +17,4 @@ obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o
obj-$(CONFIG_TCG_ST33_I2C) += tpm_i2c_stm_st33.o
+80 −34
Original line number Diff line number Diff line
@@ -40,8 +40,9 @@ enum tpm_duration {
};

#define TPM_MAX_ORDINAL 243
#define TPM_MAX_PROTECTED_ORDINAL 12
#define TPM_PROTECTED_ORDINAL_MASK 0xFF
#define TSC_MAX_ORDINAL 12
#define TPM_PROTECTED_COMMAND 0x00
#define TPM_CONNECTION_COMMAND 0x40

/*
 * Bug workaround - some TPM's don't flush the most
@@ -65,21 +66,6 @@ static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
 * values of the SHORT, MEDIUM, and LONG durations are retrieved
 * from the chip during initialization with a call to tpm_get_timeouts.
 */
static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
	TPM_UNDEFINED,		/* 0 */
	TPM_UNDEFINED,
	TPM_UNDEFINED,
	TPM_UNDEFINED,
	TPM_UNDEFINED,
	TPM_UNDEFINED,		/* 5 */
	TPM_UNDEFINED,
	TPM_UNDEFINED,
	TPM_UNDEFINED,
	TPM_UNDEFINED,
	TPM_SHORT,		/* 10 */
	TPM_SHORT,
};

static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
	TPM_UNDEFINED,		/* 0 */
	TPM_UNDEFINED,
@@ -351,14 +337,11 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
{
	int duration_idx = TPM_UNDEFINED;
	int duration = 0;
	u8 category = (ordinal >> 24) & 0xFF;

	if (ordinal < TPM_MAX_ORDINAL)
	if ((category == TPM_PROTECTED_COMMAND && ordinal < TPM_MAX_ORDINAL) ||
	    (category == TPM_CONNECTION_COMMAND && ordinal < TSC_MAX_ORDINAL))
		duration_idx = tpm_ordinal_duration[ordinal];
	else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
		 TPM_MAX_PROTECTED_ORDINAL)
		duration_idx =
		    tpm_protected_ordinal_duration[ordinal &
						   TPM_PROTECTED_ORDINAL_MASK];

	if (duration_idx != TPM_UNDEFINED)
		duration = chip->vendor.duration[duration_idx];
@@ -410,7 +393,7 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
		    chip->vendor.req_complete_val)
			goto out_recv;

		if ((status == chip->vendor.req_canceled)) {
		if (chip->vendor.req_canceled(chip, status)) {
			dev_err(chip->dev, "Operation Canceled\n");
			rc = -ECANCELED;
			goto out;
@@ -468,7 +451,7 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
		return -EFAULT;

	err = be32_to_cpu(cmd->header.out.return_code);
	if (err != 0)
	if (err != 0 && desc)
		dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);

	return err;
@@ -528,6 +511,25 @@ void tpm_gen_interrupt(struct tpm_chip *chip)
}
EXPORT_SYMBOL_GPL(tpm_gen_interrupt);

#define TPM_ORD_STARTUP cpu_to_be32(153)
#define TPM_ST_CLEAR cpu_to_be16(1)
#define TPM_ST_STATE cpu_to_be16(2)
#define TPM_ST_DEACTIVATED cpu_to_be16(3)
static const struct tpm_input_header tpm_startup_header = {
	.tag = TPM_TAG_RQU_COMMAND,
	.length = cpu_to_be32(12),
	.ordinal = TPM_ORD_STARTUP
};

static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
{
	struct tpm_cmd_t start_cmd;
	start_cmd.header.in = tpm_startup_header;
	start_cmd.params.startup_in.startup_type = startup_type;
	return transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE,
			    "attempting to start the TPM");
}

int tpm_get_timeouts(struct tpm_chip *chip)
{
	struct tpm_cmd_t tpm_cmd;
@@ -541,11 +543,28 @@ int tpm_get_timeouts(struct tpm_chip *chip)
	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, NULL);

	if (rc == TPM_ERR_INVALID_POSTINIT) {
		/* The TPM is not started, we are the first to talk to it.
		   Execute a startup command. */
		dev_info(chip->dev, "Issuing TPM_STARTUP");
		if (tpm_startup(chip, TPM_ST_CLEAR))
			return rc;

		tpm_cmd.header.in = tpm_getcap_header;
		tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
		tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
		rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
			"attempting to determine the timeouts");
	if (rc)
				  NULL);
	}
	if (rc) {
		dev_err(chip->dev,
			"A TPM error (%zd) occurred attempting to determine the timeouts\n",
			rc);
		goto duration;
	}

	if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
	    be32_to_cpu(tpm_cmd.header.out.length)
@@ -824,7 +843,7 @@ int tpm_do_selftest(struct tpm_chip *chip)
{
	int rc;
	unsigned int loops;
	unsigned int delay_msec = 1000;
	unsigned int delay_msec = 100;
	unsigned long duration;
	struct tpm_cmd_t cmd;

@@ -845,6 +864,14 @@ int tpm_do_selftest(struct tpm_chip *chip)
		cmd.header.in = pcrread_header;
		cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0);
		rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE);
		/* Some buggy TPMs will not respond to tpm_tis_ready() for
		 * around 300ms while the self test is ongoing, keep trying
		 * until the self test duration expires. */
		if (rc == -ETIME) {
			dev_info(chip->dev, HW_ERR "TPM command timed out during continue self test");
			msleep(delay_msec);
			continue;
		}

		if (rc < TPM_HEADER_SIZE)
			return -EFAULT;
@@ -1075,12 +1102,28 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
}
EXPORT_SYMBOL_GPL(tpm_store_cancel);

static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, bool check_cancel,
				   bool *canceled)
{
	u8 status = chip->vendor.status(chip);

	*canceled = false;
	if ((status & mask) == mask)
		return true;
	if (check_cancel && chip->vendor.req_canceled(chip, status)) {
		*canceled = true;
		return true;
	}
	return false;
}

int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
			 wait_queue_head_t *queue)
		      wait_queue_head_t *queue, bool check_cancel)
{
	unsigned long stop;
	long rc;
	u8 status;
	bool canceled = false;

	/* check current status */
	status = chip->vendor.status(chip);
@@ -1095,11 +1138,14 @@ int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
		if ((long)timeout <= 0)
			return -ETIME;
		rc = wait_event_interruptible_timeout(*queue,
						      ((chip->vendor.status(chip)
						      & mask) == mask),
			wait_for_tpm_stat_cond(chip, mask, check_cancel,
					       &canceled),
			timeout);
		if (rc > 0)
		if (rc > 0) {
			if (canceled)
				return -ECANCELED;
			return 0;
		}
		if (rc == -ERESTARTSYS && freezing(current)) {
			clear_thread_flag(TIF_SIGPENDING);
			goto again;
Loading