Skip to content

Commit

Permalink
Merge tag 'tpmdd-next-20190213' of git://git.infradead.org/users/jjs/…
Browse files Browse the repository at this point in the history
…linux-tpmdd into next-tpm

tpmdd updates for Linux v5.1

From: Jarkko Sakkinen <[email protected]>

Clean up the transmission flow
==============================

Cleaned up the whole transmission flow. Locking of the chip is now done in
the level of tpm_try_get_ops() and tpm_put_ops() instead taking the chip
lock inside tpm_transmit(). The nested calls inside tpm_transmit(), used
with the resource manager, have been refactored out.

Should make easier to perform more complex transactions with the TPM
without making the subsystem a bigger mess (e.g. encrypted channel patches
by James Bottomley).

PPI 1.3 support
===============

TPM PPI 1.3 introduces an additional optional command parameter that may be
needed for some commands. Display the parameter if the command requires
such a parameter. Only command 23 (SetPCRBanks) needs one.

The PPI request file will show output like this then:

   # echo "23 16" > request
   # cat request
   23 16

   # echo "5" > request
   # cat request
   5

Extend all PCR banks in IMA
===========================

Instead of static PCR banks array, the array of available PCR banks is now
allocated dynamically. The digests sizes are determined dynamically using a
probe PCR read without relying crypto's static list of hash algorithms.

This should finally make sealing of measurements in IMA safe and secure.

TPM 2.0 selftests
=================

Added a test suite to tools/testing/selftests/tpm2 previously outside of
the kernel tree: https://github.com/jsakkine-intel/tpm2-scripts.
  • Loading branch information
James Morris committed Feb 13, 2019
2 parents e7a44cf + 50a81b6 commit 5da1072
Show file tree
Hide file tree
Showing 39 changed files with 1,876 additions and 744 deletions.
41 changes: 16 additions & 25 deletions drivers/char/tpm/eventlog/tpm1.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ static const char* tcpa_pc_event_id_strings[] = {
/* returns pointer to start of pos. entry of tcg log */
static void *tpm1_bios_measurements_start(struct seq_file *m, loff_t *pos)
{
loff_t i;
loff_t i = 0;
struct tpm_chip *chip = m->private;
struct tpm_bios_log *log = &chip->log;
void *addr = log->bios_event_log;
Expand All @@ -83,38 +83,29 @@ static void *tpm1_bios_measurements_start(struct seq_file *m, loff_t *pos)
u32 converted_event_size;
u32 converted_event_type;


/* read over *pos measurements */
for (i = 0; i < *pos; i++) {
do {
event = addr;

/* check if current entry is valid */
if (addr + sizeof(struct tcpa_event) > limit)
return NULL;

converted_event_size =
do_endian_conversion(event->event_size);
converted_event_type =
do_endian_conversion(event->event_type);

if ((addr + sizeof(struct tcpa_event)) < limit) {
if ((converted_event_type == 0) &&
(converted_event_size == 0))
return NULL;
addr += (sizeof(struct tcpa_event) +
converted_event_size);
}
}

/* now check if current entry is valid */
if ((addr + sizeof(struct tcpa_event)) >= limit)
return NULL;

event = addr;
if (((converted_event_type == 0) && (converted_event_size == 0))
|| ((addr + sizeof(struct tcpa_event) + converted_event_size)
> limit))
return NULL;

converted_event_size = do_endian_conversion(event->event_size);
converted_event_type = do_endian_conversion(event->event_type);
if (i++ == *pos)
break;

if (((converted_event_type == 0) && (converted_event_size == 0))
|| ((addr + sizeof(struct tcpa_event) + converted_event_size)
>= limit))
return NULL;
addr += (sizeof(struct tcpa_event) + converted_event_size);
} while (1);

return addr;
}
Expand All @@ -134,7 +125,7 @@ static void *tpm1_bios_measurements_next(struct seq_file *m, void *v,
v += sizeof(struct tcpa_event) + converted_event_size;

/* now check if current entry is valid */
if ((v + sizeof(struct tcpa_event)) >= limit)
if ((v + sizeof(struct tcpa_event)) > limit)
return NULL;

event = v;
Expand All @@ -143,7 +134,7 @@ static void *tpm1_bios_measurements_next(struct seq_file *m, void *v,
converted_event_type = do_endian_conversion(event->event_type);

if (((converted_event_type == 0) && (converted_event_size == 0)) ||
((v + sizeof(struct tcpa_event) + converted_event_size) >= limit))
((v + sizeof(struct tcpa_event) + converted_event_size) > limit))
return NULL;

(*pos)++;
Expand Down
12 changes: 6 additions & 6 deletions drivers/char/tpm/eventlog/tpm2.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
*
* Returns size of the event. If it is an invalid event, returns 0.
*/
static int calc_tpm2_event_size(struct tcg_pcr_event2 *event,
static int calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
struct tcg_pcr_event *event_header)
{
struct tcg_efi_specid_event *efispecid;
struct tcg_efi_specid_event_head *efispecid;
struct tcg_event_field *event_field;
void *marker;
void *marker_start;
Expand All @@ -55,7 +55,7 @@ static int calc_tpm2_event_size(struct tcg_pcr_event2 *event,
marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
+ sizeof(event->count);

efispecid = (struct tcg_efi_specid_event *)event_header->event;
efispecid = (struct tcg_efi_specid_event_head *)event_header->event;

/* Check if event is malformed. */
if (event->count > efispecid->num_algs)
Expand Down Expand Up @@ -95,7 +95,7 @@ static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
void *addr = log->bios_event_log;
void *limit = log->bios_event_log_end;
struct tcg_pcr_event *event_header;
struct tcg_pcr_event2 *event;
struct tcg_pcr_event2_head *event;
size_t size;
int i;

Expand Down Expand Up @@ -136,7 +136,7 @@ static void *tpm2_bios_measurements_next(struct seq_file *m, void *v,
loff_t *pos)
{
struct tcg_pcr_event *event_header;
struct tcg_pcr_event2 *event;
struct tcg_pcr_event2_head *event;
struct tpm_chip *chip = m->private;
struct tpm_bios_log *log = &chip->log;
void *limit = log->bios_event_log_end;
Expand Down Expand Up @@ -180,7 +180,7 @@ static int tpm2_binary_bios_measurements_show(struct seq_file *m, void *v)
struct tpm_chip *chip = m->private;
struct tpm_bios_log *log = &chip->log;
struct tcg_pcr_event *event_header = log->bios_event_log;
struct tcg_pcr_event2 *event = v;
struct tcg_pcr_event2_head *event = v;
void *temp_ptr;
size_t size;

Expand Down
2 changes: 1 addition & 1 deletion drivers/char/tpm/st33zp24/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

struct st33zp24_i2c_phy {
struct i2c_client *client;
u8 buf[TPM_BUFSIZE + 1];
u8 buf[ST33ZP24_BUFSIZE + 1];
int io_lpcpd;
};

Expand Down
2 changes: 1 addition & 1 deletion drivers/char/tpm/st33zp24/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
* some latency byte before the answer is available (max 15).
* We have 2048 + 1024 + 15.
*/
#define ST33ZP24_SPI_BUFFER_SIZE (TPM_BUFSIZE + (TPM_BUFSIZE / 2) +\
#define ST33ZP24_SPI_BUFFER_SIZE (ST33ZP24_BUFSIZE + (ST33ZP24_BUFSIZE / 2) +\
MAX_SPI_LATENCY)


Expand Down
2 changes: 1 addition & 1 deletion drivers/char/tpm/st33zp24/st33zp24.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
goto out_err;
}

return len;
return 0;
out_err:
st33zp24_cancel(chip);
release_locality(chip);
Expand Down
4 changes: 2 additions & 2 deletions drivers/char/tpm/st33zp24/st33zp24.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
#ifndef __LOCAL_ST33ZP24_H__
#define __LOCAL_ST33ZP24_H__

#define TPM_WRITE_DIRECTION 0x80
#define TPM_BUFSIZE 2048
#define TPM_WRITE_DIRECTION 0x80
#define ST33ZP24_BUFSIZE 2048

struct st33zp24_dev {
struct tpm_chip *chip;
Expand Down
124 changes: 121 additions & 3 deletions drivers/char/tpm/tpm-chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,103 @@ struct class *tpm_class;
struct class *tpmrm_class;
dev_t tpm_devt;

static int tpm_request_locality(struct tpm_chip *chip)
{
int rc;

if (!chip->ops->request_locality)
return 0;

rc = chip->ops->request_locality(chip, 0);
if (rc < 0)
return rc;

chip->locality = rc;
return 0;
}

static void tpm_relinquish_locality(struct tpm_chip *chip)
{
int rc;

if (!chip->ops->relinquish_locality)
return;

rc = chip->ops->relinquish_locality(chip, chip->locality);
if (rc)
dev_err(&chip->dev, "%s: : error %d\n", __func__, rc);

chip->locality = -1;
}

static int tpm_cmd_ready(struct tpm_chip *chip)
{
if (!chip->ops->cmd_ready)
return 0;

return chip->ops->cmd_ready(chip);
}

static int tpm_go_idle(struct tpm_chip *chip)
{
if (!chip->ops->go_idle)
return 0;

return chip->ops->go_idle(chip);
}

/**
* tpm_chip_start() - power on the TPM
* @chip: a TPM chip to use
*
* Return:
* * The response length - OK
* * -errno - A system error
*/
int tpm_chip_start(struct tpm_chip *chip)
{
int ret;

if (chip->ops->clk_enable)
chip->ops->clk_enable(chip, true);

if (chip->locality == -1) {
ret = tpm_request_locality(chip);
if (ret) {
chip->ops->clk_enable(chip, false);
return ret;
}
}

ret = tpm_cmd_ready(chip);
if (ret) {
tpm_relinquish_locality(chip);
if (chip->ops->clk_enable)
chip->ops->clk_enable(chip, false);
return ret;
}

return 0;
}
EXPORT_SYMBOL_GPL(tpm_chip_start);

/**
* tpm_chip_stop() - power off the TPM
* @chip: a TPM chip to use
*
* Return:
* * The response length - OK
* * -errno - A system error
*/
void tpm_chip_stop(struct tpm_chip *chip)
{
tpm_go_idle(chip);
tpm_relinquish_locality(chip);
if (chip->ops->clk_enable)
chip->ops->clk_enable(chip, false);
}
EXPORT_SYMBOL_GPL(tpm_chip_stop);

/**
* tpm_try_get_ops() - Get a ref to the tpm_chip
* @chip: Chip to ref
Expand All @@ -56,10 +153,17 @@ int tpm_try_get_ops(struct tpm_chip *chip)

down_read(&chip->ops_sem);
if (!chip->ops)
goto out_ops;

mutex_lock(&chip->tpm_mutex);
rc = tpm_chip_start(chip);
if (rc)
goto out_lock;

return 0;
out_lock:
mutex_unlock(&chip->tpm_mutex);
out_ops:
up_read(&chip->ops_sem);
put_device(&chip->dev);
return rc;
Expand All @@ -75,6 +179,8 @@ EXPORT_SYMBOL_GPL(tpm_try_get_ops);
*/
void tpm_put_ops(struct tpm_chip *chip)
{
tpm_chip_stop(chip);
mutex_unlock(&chip->tpm_mutex);
up_read(&chip->ops_sem);
put_device(&chip->dev);
}
Expand Down Expand Up @@ -160,6 +266,7 @@ static void tpm_dev_release(struct device *dev)
kfree(chip->log.bios_event_log);
kfree(chip->work_space.context_buf);
kfree(chip->work_space.session_buf);
kfree(chip->allocated_banks);
kfree(chip);
}

Expand Down Expand Up @@ -189,7 +296,10 @@ static int tpm_class_shutdown(struct device *dev)

if (chip->flags & TPM_CHIP_FLAG_TPM2) {
down_write(&chip->ops_sem);
tpm2_shutdown(chip, TPM2_SU_CLEAR);
if (!tpm_chip_start(chip)) {
tpm2_shutdown(chip, TPM2_SU_CLEAR);
tpm_chip_stop(chip);
}
chip->ops = NULL;
up_write(&chip->ops_sem);
}
Expand Down Expand Up @@ -368,8 +478,12 @@ static void tpm_del_char_device(struct tpm_chip *chip)

/* Make the driver uncallable. */
down_write(&chip->ops_sem);
if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_shutdown(chip, TPM2_SU_CLEAR);
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
if (!tpm_chip_start(chip)) {
tpm2_shutdown(chip, TPM2_SU_CLEAR);
tpm_chip_stop(chip);
}
}
chip->ops = NULL;
up_write(&chip->ops_sem);
}
Expand Down Expand Up @@ -451,7 +565,11 @@ int tpm_chip_register(struct tpm_chip *chip)
{
int rc;

rc = tpm_chip_start(chip);
if (rc)
return rc;
rc = tpm_auto_startup(chip);
tpm_chip_stop(chip);
if (rc)
return rc;

Expand Down
Loading

0 comments on commit 5da1072

Please sign in to comment.