Skip to content

Commit

Permalink
Merge branch 'next-tpm' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/jmorris/linux-security

Pull tpm updates from James Morris:

 - 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

* 'next-tpm' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (37 commits)
  tpm/ppi: Enable submission of optional command parameter for PPI 1.3
  tpm/ppi: Possibly show command parameter if TPM PPI 1.3 is used
  tpm/ppi: Display up to 101 operations as define for version 1.3
  tpm/ppi: rename TPM_PPI_REVISION_ID to TPM_PPI_REVISION_ID_1
  tpm/ppi: pass function revision ID to tpm_eval_dsm()
  tpm: pass an array of tpm_extend_digest structures to tpm_pcr_extend()
  KEYS: trusted: explicitly use tpm_chip structure from tpm_default_chip()
  tpm: move tpm_chip definition to include/linux/tpm.h
  tpm: retrieve digest size of unknown algorithms with PCR read
  tpm: rename and export tpm2_digest and tpm2_algorithms
  tpm: dynamically allocate the allocated_banks array
  tpm: remove @flags from tpm_transmit()
  tpm: take TPM chip power gating out of tpm_transmit()
  tpm: introduce tpm_chip_start() and tpm_chip_stop()
  tpm: remove TPM_TRANSMIT_UNLOCKED flag
  tpm: use tpm_try_get_ops() in tpm-sysfs.c.
  tpm: remove @space from tpm_transmit()
  tpm: move TPM space code out of tpm_transmit()
  tpm: move tpm_validate_commmand() to tpm2-space.c
  tpm: clean up tpm_try_transmit() error handling flow
  ...
  • Loading branch information
torvalds committed Mar 11, 2019
2 parents c3665a6 + 5da1072 commit 5af7f11
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 5af7f11

Please sign in to comment.