You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
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 ...
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
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.
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
|
||||
"attempting to determine the timeouts");
|
||||
if (rc)
|
||||
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,
|
||||
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 @@ again:
|
||||
if ((long)timeout <= 0)
|
||||
return -ETIME;
|
||||
rc = wait_event_interruptible_timeout(*queue,
|
||||
((chip->vendor.status(chip)
|
||||
& mask) == mask),
|
||||
timeout);
|
||||
if (rc > 0)
|
||||
wait_for_tpm_stat_cond(chip, mask, check_cancel,
|
||||
&canceled),
|
||||
timeout);
|
||||
if (rc > 0) {
|
||||
if (canceled)
|
||||
return -ECANCELED;
|
||||
return 0;
|
||||
}
|
||||
if (rc == -ERESTARTSYS && freezing(current)) {
|
||||
clear_thread_flag(TIF_SIGPENDING);
|
||||
goto again;
|
||||
|
||||
+32
-20
@@ -47,6 +47,7 @@ enum tpm_addr {
|
||||
#define TPM_WARN_DOING_SELFTEST 0x802
|
||||
#define TPM_ERR_DEACTIVATED 0x6
|
||||
#define TPM_ERR_DISABLED 0x7
|
||||
#define TPM_ERR_INVALID_POSTINIT 38
|
||||
|
||||
#define TPM_HEADER_SIZE 10
|
||||
extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
|
||||
@@ -77,7 +78,7 @@ struct tpm_chip;
|
||||
struct tpm_vendor_specific {
|
||||
const u8 req_complete_mask;
|
||||
const u8 req_complete_val;
|
||||
const u8 req_canceled;
|
||||
bool (*req_canceled)(struct tpm_chip *chip, u8 status);
|
||||
void __iomem *iobase; /* ioremapped address */
|
||||
unsigned long base; /* TPM base address */
|
||||
|
||||
@@ -100,13 +101,19 @@ struct tpm_vendor_specific {
|
||||
bool timeout_adjusted;
|
||||
unsigned long duration[3]; /* jiffies */
|
||||
bool duration_adjusted;
|
||||
void *data;
|
||||
void *priv;
|
||||
|
||||
wait_queue_head_t read_queue;
|
||||
wait_queue_head_t int_queue;
|
||||
|
||||
u16 manufacturer_id;
|
||||
};
|
||||
|
||||
#define TPM_VPRIV(c) (c)->vendor.priv
|
||||
|
||||
#define TPM_VID_INTEL 0x8086
|
||||
#define TPM_VID_WINBOND 0x1050
|
||||
#define TPM_VID_STM 0x104A
|
||||
|
||||
struct tpm_chip {
|
||||
struct device *dev; /* Device stuff */
|
||||
@@ -154,13 +161,13 @@ struct tpm_input_header {
|
||||
__be16 tag;
|
||||
__be32 length;
|
||||
__be32 ordinal;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct tpm_output_header {
|
||||
__be16 tag;
|
||||
__be32 length;
|
||||
__be32 return_code;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct stclear_flags_t {
|
||||
__be16 tag;
|
||||
@@ -169,14 +176,14 @@ struct stclear_flags_t {
|
||||
u8 physicalPresence;
|
||||
u8 physicalPresenceLock;
|
||||
u8 bGlobalLock;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct tpm_version_t {
|
||||
u8 Major;
|
||||
u8 Minor;
|
||||
u8 revMajor;
|
||||
u8 revMinor;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct tpm_version_1_2_t {
|
||||
__be16 tag;
|
||||
@@ -184,20 +191,20 @@ struct tpm_version_1_2_t {
|
||||
u8 Minor;
|
||||
u8 revMajor;
|
||||
u8 revMinor;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct timeout_t {
|
||||
__be32 a;
|
||||
__be32 b;
|
||||
__be32 c;
|
||||
__be32 d;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct duration_t {
|
||||
__be32 tpm_short;
|
||||
__be32 tpm_medium;
|
||||
__be32 tpm_long;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct permanent_flags_t {
|
||||
__be16 tag;
|
||||
@@ -221,7 +228,7 @@ struct permanent_flags_t {
|
||||
u8 tpmEstablished;
|
||||
u8 maintenanceDone;
|
||||
u8 disableFullDALogicInfo;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
typedef union {
|
||||
struct permanent_flags_t perm_flags;
|
||||
@@ -239,12 +246,12 @@ struct tpm_getcap_params_in {
|
||||
__be32 cap;
|
||||
__be32 subcap_size;
|
||||
__be32 subcap;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct tpm_getcap_params_out {
|
||||
__be32 cap_size;
|
||||
cap_t cap;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct tpm_readpubek_params_out {
|
||||
u8 algorithm[4];
|
||||
@@ -255,7 +262,7 @@ struct tpm_readpubek_params_out {
|
||||
__be32 keysize;
|
||||
u8 modulus[256];
|
||||
u8 checksum[20];
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
typedef union {
|
||||
struct tpm_input_header in;
|
||||
@@ -265,16 +272,16 @@ typedef union {
|
||||
#define TPM_DIGEST_SIZE 20
|
||||
struct tpm_pcrread_out {
|
||||
u8 pcr_result[TPM_DIGEST_SIZE];
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct tpm_pcrread_in {
|
||||
__be32 pcr_idx;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct tpm_pcrextend_in {
|
||||
__be32 pcr_idx;
|
||||
u8 hash[TPM_DIGEST_SIZE];
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
|
||||
* bytes, but 128 is still a relatively large number of random bytes and
|
||||
@@ -285,11 +292,15 @@ struct tpm_pcrextend_in {
|
||||
struct tpm_getrandom_out {
|
||||
__be32 rng_data_len;
|
||||
u8 rng_data[TPM_MAX_RNG_DATA];
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct tpm_getrandom_in {
|
||||
__be32 num_bytes;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct tpm_startup_in {
|
||||
__be16 startup_type;
|
||||
} __packed;
|
||||
|
||||
typedef union {
|
||||
struct tpm_getcap_params_out getcap_out;
|
||||
@@ -301,12 +312,13 @@ typedef union {
|
||||
struct tpm_pcrextend_in pcrextend_in;
|
||||
struct tpm_getrandom_in getrandom_in;
|
||||
struct tpm_getrandom_out getrandom_out;
|
||||
struct tpm_startup_in startup_in;
|
||||
} tpm_cmd_params;
|
||||
|
||||
struct tpm_cmd_t {
|
||||
tpm_cmd_header header;
|
||||
tpm_cmd_params params;
|
||||
}__attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *);
|
||||
|
||||
@@ -326,7 +338,7 @@ extern void tpm_remove_hardware(struct device *);
|
||||
extern int tpm_pm_suspend(struct device *);
|
||||
extern int tpm_pm_resume(struct device *);
|
||||
extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
|
||||
wait_queue_head_t *);
|
||||
wait_queue_head_t *, bool);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
extern int tpm_add_ppi(struct kobject *);
|
||||
|
||||
@@ -33,13 +33,13 @@ struct acpi_tcpa {
|
||||
u16 platform_class;
|
||||
union {
|
||||
struct client_hdr {
|
||||
u32 log_max_len __attribute__ ((packed));
|
||||
u64 log_start_addr __attribute__ ((packed));
|
||||
u32 log_max_len __packed;
|
||||
u64 log_start_addr __packed;
|
||||
} client;
|
||||
struct server_hdr {
|
||||
u16 reserved;
|
||||
u64 log_max_len __attribute__ ((packed));
|
||||
u64 log_start_addr __attribute__ ((packed));
|
||||
u64 log_max_len __packed;
|
||||
u64 log_start_addr __packed;
|
||||
} server;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -116,6 +116,11 @@ static u8 tpm_atml_status(struct tpm_chip *chip)
|
||||
return ioread8(chip->vendor.iobase + 1);
|
||||
}
|
||||
|
||||
static bool tpm_atml_req_canceled(struct tpm_chip *chip, u8 status)
|
||||
{
|
||||
return (status == ATML_STATUS_READY);
|
||||
}
|
||||
|
||||
static const struct file_operations atmel_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
@@ -147,7 +152,7 @@ static const struct tpm_vendor_specific tpm_atmel = {
|
||||
.status = tpm_atml_status,
|
||||
.req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
|
||||
.req_complete_val = ATML_STATUS_DATA_AVAIL,
|
||||
.req_canceled = ATML_STATUS_READY,
|
||||
.req_canceled = tpm_atml_req_canceled,
|
||||
.attr_group = &atmel_attr_grp,
|
||||
.miscdev = { .fops = &atmel_ops, },
|
||||
};
|
||||
|
||||
@@ -505,6 +505,11 @@ out_err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool tpm_tis_i2c_req_canceled(struct tpm_chip *chip, u8 status)
|
||||
{
|
||||
return (status == TPM_STS_COMMAND_READY);
|
||||
}
|
||||
|
||||
static const struct file_operations tis_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
@@ -550,7 +555,7 @@ static struct tpm_vendor_specific tpm_tis_i2c = {
|
||||
.cancel = tpm_tis_i2c_ready,
|
||||
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
.req_canceled = TPM_STS_COMMAND_READY,
|
||||
.req_canceled = tpm_tis_i2c_req_canceled,
|
||||
.attr_group = &tis_attr_grp,
|
||||
.miscdev.fops = &tis_ops,
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
|
||||
* Copyright (C) 2009, 2010 STMicroelectronics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* STMicroelectronics version 1.2.0, Copyright (C) 2010
|
||||
* STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
|
||||
* This is free software, and you are welcome to redistribute it
|
||||
* under certain conditions.
|
||||
*
|
||||
* @Author: Christophe RICARD tpmsupport@st.com
|
||||
*
|
||||
* @File: stm_st33_tpm_i2c.h
|
||||
*
|
||||
* @Date: 09/15/2010
|
||||
*/
|
||||
#ifndef __STM_ST33_TPM_I2C_MAIN_H__
|
||||
#define __STM_ST33_TPM_I2C_MAIN_H__
|
||||
|
||||
#define TPM_ACCESS (0x0)
|
||||
#define TPM_STS (0x18)
|
||||
#define TPM_HASH_END (0x20)
|
||||
#define TPM_DATA_FIFO (0x24)
|
||||
#define TPM_HASH_DATA (0x24)
|
||||
#define TPM_HASH_START (0x28)
|
||||
#define TPM_INTF_CAPABILITY (0x14)
|
||||
#define TPM_INT_STATUS (0x10)
|
||||
#define TPM_INT_ENABLE (0x08)
|
||||
|
||||
#define TPM_DUMMY_BYTE 0xAA
|
||||
#define TPM_WRITE_DIRECTION 0x80
|
||||
#define TPM_HEADER_SIZE 10
|
||||
#define TPM_BUFSIZE 2048
|
||||
|
||||
#define LOCALITY0 0
|
||||
|
||||
#define TPM_ST33_I2C "st33zp24_i2c"
|
||||
|
||||
struct st33zp24_platform_data {
|
||||
int io_serirq;
|
||||
int io_lpcpd;
|
||||
struct i2c_client *client;
|
||||
u8 *tpm_i2c_buffer[2]; /* 0 Request 1 Response */
|
||||
struct completion irq_detection;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
#endif /* __STM_ST33_TPM_I2C_MAIN_H__ */
|
||||
@@ -64,7 +64,7 @@ static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev)
|
||||
{
|
||||
struct tpm_chip *chip = dev_get_drvdata(dev);
|
||||
if (chip)
|
||||
return (struct ibmvtpm_dev *)chip->vendor.data;
|
||||
return (struct ibmvtpm_dev *)TPM_VPRIV(chip);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
u16 len;
|
||||
int sig;
|
||||
|
||||
ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data;
|
||||
ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
|
||||
|
||||
if (!ibmvtpm->rtce_buf) {
|
||||
dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
|
||||
@@ -127,7 +127,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
u64 *word = (u64 *) &crq;
|
||||
int rc;
|
||||
|
||||
ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data;
|
||||
ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
|
||||
|
||||
if (!ibmvtpm->rtce_buf) {
|
||||
dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
|
||||
@@ -398,6 +398,11 @@ static int tpm_ibmvtpm_resume(struct device *dev)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool tpm_ibmvtpm_req_canceled(struct tpm_chip *chip, u8 status)
|
||||
{
|
||||
return (status == 0);
|
||||
}
|
||||
|
||||
static const struct file_operations ibmvtpm_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
@@ -441,7 +446,7 @@ static const struct tpm_vendor_specific tpm_ibmvtpm = {
|
||||
.status = tpm_ibmvtpm_status,
|
||||
.req_complete_mask = 0,
|
||||
.req_complete_val = 0,
|
||||
.req_canceled = 0,
|
||||
.req_canceled = tpm_ibmvtpm_req_canceled,
|
||||
.attr_group = &ibmvtpm_attr_grp,
|
||||
.miscdev = { .fops = &ibmvtpm_ops, },
|
||||
};
|
||||
@@ -647,7 +652,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
|
||||
|
||||
ibmvtpm->dev = dev;
|
||||
ibmvtpm->vdev = vio_dev;
|
||||
chip->vendor.data = (void *)ibmvtpm;
|
||||
TPM_VPRIV(chip) = (void *)ibmvtpm;
|
||||
|
||||
spin_lock_init(&ibmvtpm->rtce_lock);
|
||||
|
||||
|
||||
@@ -227,6 +227,11 @@ static u8 tpm_nsc_status(struct tpm_chip *chip)
|
||||
return inb(chip->vendor.base + NSC_STATUS);
|
||||
}
|
||||
|
||||
static bool tpm_nsc_req_canceled(struct tpm_chip *chip, u8 status)
|
||||
{
|
||||
return (status == NSC_STATUS_RDY);
|
||||
}
|
||||
|
||||
static const struct file_operations nsc_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
@@ -258,7 +263,7 @@ static const struct tpm_vendor_specific tpm_nsc = {
|
||||
.status = tpm_nsc_status,
|
||||
.req_complete_mask = NSC_STATUS_OBF,
|
||||
.req_complete_val = NSC_STATUS_OBF,
|
||||
.req_canceled = NSC_STATUS_RDY,
|
||||
.req_canceled = tpm_nsc_req_canceled,
|
||||
.attr_group = &nsc_attr_grp,
|
||||
.miscdev = { .fops = &nsc_ops, },
|
||||
};
|
||||
|
||||
+51
-13
@@ -84,6 +84,9 @@ static int is_itpm(struct pnp_dev *dev)
|
||||
struct acpi_device *acpi = pnp_acpi_device(dev);
|
||||
struct acpi_hardware_id *id;
|
||||
|
||||
if (!acpi)
|
||||
return 0;
|
||||
|
||||
list_for_each_entry(id, &acpi->pnp.ids, list) {
|
||||
if (!strcmp("INTC0102", id->id))
|
||||
return 1;
|
||||
@@ -98,6 +101,22 @@ static inline int is_itpm(struct pnp_dev *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Before we attempt to access the TPM we must see that the valid bit is set.
|
||||
* The specification says that this bit is 0 at reset and remains 0 until the
|
||||
* 'TPM has gone through its self test and initialization and has established
|
||||
* correct values in the other bits.' */
|
||||
static int wait_startup(struct tpm_chip *chip, int l)
|
||||
{
|
||||
unsigned long stop = jiffies + chip->vendor.timeout_a;
|
||||
do {
|
||||
if (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
|
||||
TPM_ACCESS_VALID)
|
||||
return 0;
|
||||
msleep(TPM_TIMEOUT);
|
||||
} while (time_before(jiffies, stop));
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int check_locality(struct tpm_chip *chip, int l)
|
||||
{
|
||||
if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
|
||||
@@ -198,7 +217,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
wait_for_tpm_stat(chip,
|
||||
TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
chip->vendor.timeout_c,
|
||||
&chip->vendor.read_queue)
|
||||
&chip->vendor.read_queue, true)
|
||||
== 0) {
|
||||
burstcnt = get_burstcount(chip);
|
||||
for (; burstcnt > 0 && size < count; burstcnt--)
|
||||
@@ -241,7 +260,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
}
|
||||
|
||||
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
|
||||
&chip->vendor.int_queue);
|
||||
&chip->vendor.int_queue, false);
|
||||
status = tpm_tis_status(chip);
|
||||
if (status & TPM_STS_DATA_AVAIL) { /* retry? */
|
||||
dev_err(chip->dev, "Error left over data\n");
|
||||
@@ -277,7 +296,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
|
||||
tpm_tis_ready(chip);
|
||||
if (wait_for_tpm_stat
|
||||
(chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
|
||||
&chip->vendor.int_queue) < 0) {
|
||||
&chip->vendor.int_queue, false) < 0) {
|
||||
rc = -ETIME;
|
||||
goto out_err;
|
||||
}
|
||||
@@ -292,7 +311,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
|
||||
}
|
||||
|
||||
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
|
||||
&chip->vendor.int_queue);
|
||||
&chip->vendor.int_queue, false);
|
||||
status = tpm_tis_status(chip);
|
||||
if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
|
||||
rc = -EIO;
|
||||
@@ -304,7 +323,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
|
||||
iowrite8(buf[count],
|
||||
chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
|
||||
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
|
||||
&chip->vendor.int_queue);
|
||||
&chip->vendor.int_queue, false);
|
||||
status = tpm_tis_status(chip);
|
||||
if ((status & TPM_STS_DATA_EXPECT) != 0) {
|
||||
rc = -EIO;
|
||||
@@ -342,7 +361,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
|
||||
if (wait_for_tpm_stat
|
||||
(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
tpm_calc_ordinal_duration(chip, ordinal),
|
||||
&chip->vendor.read_queue) < 0) {
|
||||
&chip->vendor.read_queue, false) < 0) {
|
||||
rc = -ETIME;
|
||||
goto out_err;
|
||||
}
|
||||
@@ -374,7 +393,7 @@ static int probe_itpm(struct tpm_chip *chip)
|
||||
if (vendor != TPM_VID_INTEL)
|
||||
return 0;
|
||||
|
||||
itpm = 0;
|
||||
itpm = false;
|
||||
|
||||
rc = tpm_tis_send_data(chip, cmd_getticks, len);
|
||||
if (rc == 0)
|
||||
@@ -383,7 +402,7 @@ static int probe_itpm(struct tpm_chip *chip)
|
||||
tpm_tis_ready(chip);
|
||||
release_locality(chip, chip->vendor.locality, 0);
|
||||
|
||||
itpm = 1;
|
||||
itpm = true;
|
||||
|
||||
rc = tpm_tis_send_data(chip, cmd_getticks, len);
|
||||
if (rc == 0) {
|
||||
@@ -400,6 +419,19 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
|
||||
{
|
||||
switch (chip->vendor.manufacturer_id) {
|
||||
case TPM_VID_WINBOND:
|
||||
return ((status == TPM_STS_VALID) ||
|
||||
(status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)));
|
||||
case TPM_VID_STM:
|
||||
return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY));
|
||||
default:
|
||||
return (status == TPM_STS_COMMAND_READY);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct file_operations tis_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
@@ -445,7 +477,7 @@ static struct tpm_vendor_specific tpm_tis = {
|
||||
.cancel = tpm_tis_ready,
|
||||
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
.req_canceled = TPM_STS_COMMAND_READY,
|
||||
.req_canceled = tpm_tis_req_canceled,
|
||||
.attr_group = &tis_attr_grp,
|
||||
.miscdev = {
|
||||
.fops = &tis_ops,},
|
||||
@@ -502,7 +534,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static bool interrupts = 1;
|
||||
static bool interrupts = true;
|
||||
module_param(interrupts, bool, 0444);
|
||||
MODULE_PARM_DESC(interrupts, "Enable interrupts");
|
||||
|
||||
@@ -528,12 +560,18 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
|
||||
chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
|
||||
chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
|
||||
|
||||
if (wait_startup(chip, 0) != 0) {
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (request_locality(chip, 0) != 0) {
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
|
||||
chip->vendor.manufacturer_id = vendor;
|
||||
|
||||
dev_info(dev,
|
||||
"1.2 TPM (device-id 0x%X, rev-id %d)\n",
|
||||
@@ -545,7 +583,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
}
|
||||
itpm = (probe == 0) ? 0 : 1;
|
||||
itpm = !!probe;
|
||||
}
|
||||
|
||||
if (itpm)
|
||||
@@ -741,10 +779,10 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
|
||||
if (pnp_irq_valid(pnp_dev, 0))
|
||||
irq = pnp_irq(pnp_dev, 0);
|
||||
else
|
||||
interrupts = 0;
|
||||
interrupts = false;
|
||||
|
||||
if (is_itpm(pnp_dev))
|
||||
itpm = 1;
|
||||
itpm = true;
|
||||
|
||||
return tpm_tis_init(&pnp_dev->dev, start, len, irq);
|
||||
}
|
||||
|
||||
+14
-27
@@ -30,11 +30,10 @@
|
||||
|
||||
static struct crypto_shash *shash;
|
||||
|
||||
static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
|
||||
unsigned long msglen,
|
||||
unsigned long modulus_bitlen,
|
||||
unsigned char *out,
|
||||
unsigned long *outlen)
|
||||
static const char *pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
|
||||
unsigned long msglen,
|
||||
unsigned long modulus_bitlen,
|
||||
unsigned long *outlen)
|
||||
{
|
||||
unsigned long modulus_len, ps_len, i;
|
||||
|
||||
@@ -42,11 +41,11 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
|
||||
|
||||
/* test message size */
|
||||
if ((msglen > modulus_len) || (modulus_len < 11))
|
||||
return -EINVAL;
|
||||
return NULL;
|
||||
|
||||
/* separate encoded message */
|
||||
if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1))
|
||||
return -EINVAL;
|
||||
if (msg[0] != 0x00 || msg[1] != 0x01)
|
||||
return NULL;
|
||||
|
||||
for (i = 2; i < modulus_len - 1; i++)
|
||||
if (msg[i] != 0xFF)
|
||||
@@ -56,19 +55,13 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
|
||||
if (msg[i] != 0)
|
||||
/* There was no octet with hexadecimal value 0x00
|
||||
to separate ps from m. */
|
||||
return -EINVAL;
|
||||
return NULL;
|
||||
|
||||
ps_len = i - 2;
|
||||
|
||||
if (*outlen < (msglen - (2 + ps_len + 1))) {
|
||||
*outlen = msglen - (2 + ps_len + 1);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
*outlen = (msglen - (2 + ps_len + 1));
|
||||
memcpy(out, &msg[2 + ps_len + 1], *outlen);
|
||||
|
||||
return 0;
|
||||
return msg + 2 + ps_len + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -83,7 +76,8 @@ static int digsig_verify_rsa(struct key *key,
|
||||
unsigned long mlen, mblen;
|
||||
unsigned nret, l;
|
||||
int head, i;
|
||||
unsigned char *out1 = NULL, *out2 = NULL;
|
||||
unsigned char *out1 = NULL;
|
||||
const char *m;
|
||||
MPI in = NULL, res = NULL, pkey[2];
|
||||
uint8_t *p, *datap, *endp;
|
||||
struct user_key_payload *ukp;
|
||||
@@ -120,7 +114,7 @@ static int digsig_verify_rsa(struct key *key,
|
||||
}
|
||||
|
||||
mblen = mpi_get_nbits(pkey[0]);
|
||||
mlen = (mblen + 7)/8;
|
||||
mlen = DIV_ROUND_UP(mblen, 8);
|
||||
|
||||
if (mlen == 0)
|
||||
goto err;
|
||||
@@ -129,10 +123,6 @@ static int digsig_verify_rsa(struct key *key,
|
||||
if (!out1)
|
||||
goto err;
|
||||
|
||||
out2 = kzalloc(mlen, GFP_KERNEL);
|
||||
if (!out2)
|
||||
goto err;
|
||||
|
||||
nret = siglen;
|
||||
in = mpi_read_from_buffer(sig, &nret);
|
||||
if (!in)
|
||||
@@ -164,18 +154,15 @@ static int digsig_verify_rsa(struct key *key,
|
||||
|
||||
kfree(p);
|
||||
|
||||
err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
|
||||
if (err)
|
||||
goto err;
|
||||
m = pkcs_1_v1_5_decode_emsa(out1, len, mblen, &len);
|
||||
|
||||
if (len != hlen || memcmp(out2, h, hlen))
|
||||
if (!m || len != hlen || memcmp(m, h, hlen))
|
||||
err = -EINVAL;
|
||||
|
||||
err:
|
||||
mpi_free(in);
|
||||
mpi_free(res);
|
||||
kfree(out1);
|
||||
kfree(out2);
|
||||
while (--i >= 0)
|
||||
mpi_free(pkey[i]);
|
||||
err1:
|
||||
|
||||
@@ -65,10 +65,6 @@
|
||||
typedef mpi_limb_t *mpi_ptr_t; /* pointer to a limb */
|
||||
typedef int mpi_size_t; /* (must be a signed type) */
|
||||
|
||||
#define ABS(x) (x >= 0 ? x : -x)
|
||||
#define MIN(l, o) ((l) < (o) ? (l) : (o))
|
||||
#define MAX(h, i) ((h) > (i) ? (h) : (i))
|
||||
|
||||
static inline int RESIZE_IF_NEEDED(MPI a, unsigned b)
|
||||
{
|
||||
if (a->alloced < b)
|
||||
|
||||
+4
-4
@@ -52,7 +52,7 @@ MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes)
|
||||
else
|
||||
nbits = 0;
|
||||
|
||||
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
|
||||
nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
|
||||
val = mpi_alloc(nlimbs);
|
||||
if (!val)
|
||||
return NULL;
|
||||
@@ -96,8 +96,8 @@ MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
|
||||
buffer += 2;
|
||||
nread = 2;
|
||||
|
||||
nbytes = (nbits + 7) / 8;
|
||||
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
|
||||
nbytes = DIV_ROUND_UP(nbits, 8);
|
||||
nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
|
||||
val = mpi_alloc(nlimbs);
|
||||
if (!val)
|
||||
return NULL;
|
||||
@@ -193,7 +193,7 @@ int mpi_set_buffer(MPI a, const void *xbuffer, unsigned nbytes, int sign)
|
||||
int nlimbs;
|
||||
int i;
|
||||
|
||||
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
|
||||
nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
|
||||
if (RESIZE_IF_NEEDED(a, nlimbs) < 0)
|
||||
return -ENOMEM;
|
||||
a->sign = sign;
|
||||
|
||||
@@ -17,5 +17,17 @@ config INTEGRITY_SIGNATURE
|
||||
This is useful for evm and module keyrings, when keys are
|
||||
usually only added from initramfs.
|
||||
|
||||
config INTEGRITY_ASYMMETRIC_KEYS
|
||||
boolean "Enable asymmetric keys support"
|
||||
depends on INTEGRITY_SIGNATURE
|
||||
default n
|
||||
select ASYMMETRIC_KEY_TYPE
|
||||
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
||||
select PUBLIC_KEY_ALGO_RSA
|
||||
select X509_CERTIFICATE_PARSER
|
||||
help
|
||||
This option enables digital signature verification using
|
||||
asymmetric keys.
|
||||
|
||||
source security/integrity/ima/Kconfig
|
||||
source security/integrity/evm/Kconfig
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
obj-$(CONFIG_INTEGRITY) += integrity.o
|
||||
obj-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
|
||||
obj-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
|
||||
|
||||
integrity-y := iint.o
|
||||
|
||||
|
||||
@@ -44,5 +44,14 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
|
||||
}
|
||||
}
|
||||
|
||||
return digsig_verify(keyring[id], sig, siglen, digest, digestlen);
|
||||
switch (sig[0]) {
|
||||
case 1:
|
||||
return digsig_verify(keyring[id], sig, siglen,
|
||||
digest, digestlen);
|
||||
case 2:
|
||||
return asymmetric_verify(keyring[id], sig, siglen,
|
||||
digest, digestlen);
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user