On Tue, Aug 09, 2016 at 03:34:55PM -0400, Nayna Jain wrote:
> Adds securityfs support for TPM2.0.
> This patch currently supports only binary_bios_measurements.
> 
> Changelog v2:
>         * Single tpm_of.c for reading both tpm and vtpm device tree values.
>         * Some of the issues are fixed in Patch 1 itself.
>         * Comments in tpm2.h give reference to the standard from where structs
>       are taken.
>       * Now, tpm_of.c has same code applied for both tpm and vtpm, so I think
>       that now it is needed to have generic types rather than endian specific 
> type.
> 
> There are few preexisting issues as being mentioned in feedback and are not 
> addressed in this patch. Reason being, I don't have much expertise of ACPI 
> side as of now, 
> and these changes will affect acpi,tpm,vtpm, all paths, so I would like to go 
> slow
> and fix them as different patch later after better understanding.
> Hope this sounds ok to have them as different patch.
> 
> Issues which are not addressed are as below:
>         * tpm_eventlog.h still has #ifdef defined, for tpm_bios_log_setup()
>         * tpm_bios_log_setup is still being called in tpm-chip register 
> function.

I do not understand your changelog entries. Please provide a nice one or
most two paragraph english language description and keep breakdowns and
changelogs in the cover letter.

Commit message does not equal to a discussion forum and I do not have
any idea what feedback you are talking about...

Not reviewing this further. This is just terrible.

/Jarkko

> Signed-off-by: Nayna Jain <na...@linux.vnet.ibm.com>
> ---
>  drivers/char/tpm/Makefile            |   8 +-
>  drivers/char/tpm/tpm-chip.c          |  20 +---
>  drivers/char/tpm/tpm2.h              |  85 +++++++++++++
>  drivers/char/tpm/tpm2_eventlog.c     | 224 
> +++++++++++++++++++++++++++++++++++
>  drivers/char/tpm/tpm_eventlog.h      |   2 +-
>  drivers/char/tpm/tpm_eventlog_init.c |  43 +++++--
>  drivers/char/tpm/tpm_of.c            |  17 ++-
>  7 files changed, 366 insertions(+), 33 deletions(-)
>  create mode 100644 drivers/char/tpm/tpm2.h
>  create mode 100644 drivers/char/tpm/tpm2_eventlog.c
> 
> diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
> index 9136762..509ace2 100644
> --- a/drivers/char/tpm/Makefile
> +++ b/drivers/char/tpm/Makefile
> @@ -6,10 +6,14 @@ tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o 
> tpm2-cmd.o
>  tpm-$(CONFIG_ACPI) += tpm_ppi.o
>  
>  ifdef CONFIG_ACPI
> -     tpm-y += tpm_eventlog_init.o tpm_eventlog.o tpm_acpi.o
> +     tpm-y += tpm_eventlog_init.o tpm2_eventlog.o tpm_eventlog.o tpm_acpi.o
>  else
>  ifdef CONFIG_TCG_IBMVTPM
> -     tpm-y += tpm_eventlog_init.o tpm_eventlog.o tpm_of.o
> +     tpm-y += tpm_eventlog_init.o tpm2_eventlog.o tpm_eventlog.o tpm_of.o
> +else
> +ifdef CONFIG_PPC64
> +     tpm-y += tpm_eventlog_init.o tpm2_eventlog.o tpm_eventlog.o tpm_of.o
> +endif
>  endif
>  endif
>  obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> index 7f6cdab..3f1c489 100644
> --- a/drivers/char/tpm/tpm-chip.c
> +++ b/drivers/char/tpm/tpm-chip.c
> @@ -285,20 +285,9 @@ static int tpm1_chip_register(struct tpm_chip *chip)
>  
>       tpm_sysfs_add_device(chip);
>  
> -     tpm_bios_log_setup(chip);
> -
>       return 0;
>  }
>  
> -static void tpm1_chip_unregister(struct tpm_chip *chip)
> -{
> -     if (chip->flags & TPM_CHIP_FLAG_TPM2)
> -             return;
> -
> -     if (chip->bios_dir)
> -             tpm_bios_log_teardown(chip);
> -}
> -
>  static void tpm_del_legacy_sysfs(struct tpm_chip *chip)
>  {
>       struct attribute **i;
> @@ -372,10 +361,8 @@ int tpm_chip_register(struct tpm_chip *chip)
>       tpm_add_ppi(chip);
>  
>       rc = tpm_add_char_device(chip);
> -     if (rc) {
> -             tpm1_chip_unregister(chip);
> +     if (rc)
>               return rc;
> -     }
>  
>       chip->flags |= TPM_CHIP_FLAG_REGISTERED;
>  
> @@ -385,6 +372,8 @@ int tpm_chip_register(struct tpm_chip *chip)
>               return rc;
>       }
>  
> +     tpm_bios_log_setup(chip);
> +
>       return 0;
>  }
>  EXPORT_SYMBOL_GPL(tpm_chip_register);
> @@ -409,7 +398,8 @@ void tpm_chip_unregister(struct tpm_chip *chip)
>  
>       tpm_del_legacy_sysfs(chip);
>  
> -     tpm1_chip_unregister(chip);
> +     tpm_bios_log_teardown(chip);
> +
>       tpm_del_char_device(chip);
>  }
>  EXPORT_SYMBOL_GPL(tpm_chip_unregister);
> diff --git a/drivers/char/tpm/tpm2.h b/drivers/char/tpm/tpm2.h
> new file mode 100644
> index 0000000..38a8073
> --- /dev/null
> +++ b/drivers/char/tpm/tpm2.h
> @@ -0,0 +1,85 @@
> +#ifndef __TPM2_H__
> +#define __TPM2_H__
> +
> +#define TPM_ALG_SHA1_DIGEST_SIZE     20
> +#define TPM_ALG_SHA256_DIGEST_SIZE   32
> +#define TPM_ALG_SHA384_DIGEST_SIZE   48
> +
> +#define HASH_COUNT   3
> +#define MAX_TPM_LOG_MSG      128
> +
> +/**
> + * All the structures related to Event Log are taken from TCG EFI Protocol
> + * Specification, Family "2.0". Document is available on link
> + * http://www.trustedcomputinggroup.org/tcg-efi-protocol-specification/
> + * Information is also available on TCG PC Client Platform Firmware Profile
> + * Specification, Family "2.0"
> + * Detailed digest structures for TPM2.0 are defined in document
> + * Trusted Platform Module Library Part 2: Structures, Family "2.0".
> + */
> +
> +/* Event log header algorithm spec. */
> +struct tcg_efispecideventalgorithmsize {
> +     u16     algorithm_id;
> +     u16     digest_size;
> +} __packed;
> +
> +/* Event log header data. */
> +struct tcg_efispecideventstruct {
> +     u8                                      signature[16];
> +     u32                                     platform_class;
> +     u8                                      spec_version_minor;
> +     u8                                      spec_version_major;
> +     u8                                      spec_errata;
> +     u8                                      uintnsize;
> +     u32                                     num_algs;
> +     struct tcg_efispecideventalgorithmsize  digest_sizes[HASH_COUNT];
> +     u8                                      vendor_info_size;
> +     u8                                      vendor_info[0];
> +} __packed;
> +
> +/* Header entry for eventlog. */
> +struct tcg_pcr_event {
> +     u32     pcr_index;
> +     u32     event_type;
> +     u8      digest[20];
> +     u32     event_size;
> +     u8      event[MAX_TPM_LOG_MSG];
> +} __packed;
> +
> +/* Digest union for crypto agility. */
> +union tpmu_ha {
> +     u8       sha1[TPM_ALG_SHA1_DIGEST_SIZE];
> +     u8       sha256[TPM_ALG_SHA256_DIGEST_SIZE];
> +     u8       sha384[TPM_ALG_SHA384_DIGEST_SIZE];
> +} __packed;
> +
> +/* Crypto Agile algorithm and respective digest. */
> +struct tpmt_ha {
> +     u16             algorithm_id;
> +     union tpmu_ha   digest;
> +} __packed;
> +
> +/* Crypto agile digests list. */
> +struct tpml_digest_values {
> +     u32             count;
> +     struct tpmt_ha  digests[HASH_COUNT];
> +} __packed;
> +
> +/* Event field structure. */
> +struct tcg_event_field {
> +     u32     event_size;
> +     u8      event[MAX_TPM_LOG_MSG];
> +} __packed;
> +
> +/* Crypto agile log entry format for TPM 2.0. */
> +struct tcg_pcr_event2 {
> +     u32                             pcr_index;
> +     u32                             event_type;
> +     struct tpml_digest_values       digests;
> +     struct tcg_event_field          event;
> +} __packed;
> +
> +extern const struct seq_operations tpm2_binary_b_measurments_seqops;
> +
> +#endif
> diff --git a/drivers/char/tpm/tpm2_eventlog.c 
> b/drivers/char/tpm/tpm2_eventlog.c
> new file mode 100644
> index 0000000..f1e8c4a
> --- /dev/null
> +++ b/drivers/char/tpm/tpm2_eventlog.c
> @@ -0,0 +1,224 @@
> +/*
> + * Copyright (C) 2016 IBM Corporation
> + *
> + * Authors:
> + *      Nayna Jain <na...@linux.vnet.ibm.com>
> +
> + * Access to TPM2.0 event log as written by Firmware.
> + * It assumes that writer of event log has followed TCG Spec 2.0
> + * has written the event struct data in little endian. With that,
> + * it doesn't need any endian conversion for structure content.
> + *
> + * 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.
> + */
> +
> +#include <linux/seq_file.h>
> +#include <linux/fs.h>
> +#include <linux/security.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +
> +#include "tpm.h"
> +#include "tpm2.h"
> +#include "tpm_eventlog.h"
> +
> +
> +static int calc_tpm2_event_size(struct tcg_pcr_event2 *event,
> +             struct tcg_pcr_event *event_header)
> +{
> +     struct tcg_efispecideventstruct *efispecid;
> +     struct tcg_event_field *event_field;
> +     void *marker, *marker_start;
> +     int j;
> +     size_t size = 0;
> +
> +     /*
> +      * NOTE: TPM2.0 allows support for extend to multiple PCR Banks.
> +      * This implies that eventlog also has multiple digest values
> +      * one for each PCR Bank. This is called Crypto Agile Log Entry
> +      * Format. Current support implementation is for SHA1 and SHA256.
> +      * Number of digest values are identified by parsing first
> +      * structure stored in event log also called event header.
> +      * Further, the eventlog is written in packed form so to calculate
> +      * offset it is important to know the type of algorithm used.
> +      * Eg. 1:
> +      * digest_values.count = 1;
> +      * digest_values.digest[0].algorithm_id = sha1;
> +      * digest_values.digest[0].digest.sha1 = {20 bytes raw data};
> +      * Offset of eventsize is sizeof(count) + sizeof(algorithm_id) + 20
> +      *
> +      * Eg. 2:
> +      * digest_values.count = 1;
> +      * digest_values.digest[0].algorithm_id = sha256;
> +      * digest_values.digest[0].digest.sha1 = {32 bytes raw data};
> +      * Offset of eventsize is sizeof(count) + sizeof(algorithm_id) + 32
> +
> +      * Eg. 3:
> +      * digest_values.count = 2;
> +      * digest_values.digest[0].algorithm_id = sha1;
> +      * digest_values.digest[0].digest.sha1 = {20 bytes raw data};
> +      * digest_values.digest[1].algorithm_id = sha256;
> +      * digest_values.digest[1].digest.sha256 = {32 bytes raw data};
> +      * Offset of eventsize is sizeof(count) + sizeof(algorithm_id) + 20
> +      *                      + sizeof(algorithm_id) + 32;
> +      *
> +      * So, it implies that offset of event_size can vary based on digest
> +      * values as defined by vendor. And so we have to calculate the
> +      * offset by parsing through number and type of digests being used.
> +      * And this is the purpose of using *marker to traverse the structure
> +      * and calculate the offset of event_size. This function uses *marker
> +      * to parse and calculate the dynamic size of the whole event structure.
> +      */
> +
> +     marker = event;
> +     marker_start = marker;
> +     marker = marker + sizeof(event->pcr_index) + sizeof(event->event_type)
> +             + sizeof(event->digests.count);
> +
> +     efispecid = (struct tcg_efispecideventstruct *) event_header->event;
> +
> +     for (j = 0; (j < efispecid->num_algs) && (j < HASH_COUNT); j++) {
> +             marker = marker
> +                     + sizeof(efispecid->digest_sizes[j].algorithm_id);
> +             marker = marker + efispecid->digest_sizes[j].digest_size;
> +     }
> +
> +     event_field = (struct tcg_event_field *) marker;
> +     marker = marker + sizeof(event_field->event_size)
> +             + event_field->event_size;
> +     size = marker - marker_start;
> +
> +     if ((event->event_type == 0) && (event_field->event_size == 0))
> +             return 0;
> +
> +     return size;
> +}
> +
> +static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
> +{
> +     struct tpm_bios_log *log = m->private;
> +     void *addr = log->bios_event_log;
> +     void *limit = log->bios_event_log_end;
> +     struct tcg_pcr_event *event_header;
> +     struct tcg_pcr_event2 *event;
> +     int i;
> +     size_t size = 0;
> +
> +     event_header = addr;
> +
> +     size = sizeof(struct tcg_pcr_event) - sizeof(event_header->event)
> +             + event_header->event_size;
> +
> +
> +     if (*pos == 0) {
> +             if (addr + size < limit) {
> +                     if ((event_header->event_type == 0) &&
> +                                     (event_header->event_size == 0))
> +                             return NULL;
> +                     return SEQ_START_TOKEN;
> +             }
> +     }
> +
> +     if (*pos > 0) {
> +             addr += size;
> +             event = addr;
> +             size = calc_tpm2_event_size(event, event_header);
> +             if ((addr + size >=  limit) || (size == 0))
> +                     return NULL;
> +     }
> +
> +     /* read over *pos measurements */
> +     for (i = 0; i < (*pos - 1); i++) {
> +             event = addr;
> +             size = calc_tpm2_event_size(event, event_header);
> +
> +             if ((addr + size >= limit) || (size == 0))
> +                     return NULL;
> +             addr += size;
> +     }
> +
> +     return addr;
> +}
> +
> +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 tpm_bios_log *log = m->private;
> +     void *limit = log->bios_event_log_end;
> +     void *marker;
> +     size_t event_size = 0;
> +
> +     event_header = log->bios_event_log;
> +
> +     if (v == SEQ_START_TOKEN) {
> +             event_size = sizeof(struct tcg_pcr_event)
> +                     - sizeof(event_header->event)
> +                     + event_header->event_size;
> +             marker = event_header;
> +     } else {
> +             event = v;
> +             event_size = calc_tpm2_event_size(event, event_header);
> +             if (event_size == 0)
> +                     return NULL;
> +             marker =  event;
> +     }
> +
> +     marker = marker + event_size;
> +     if (marker >= limit)
> +             return NULL;
> +     v = marker;
> +     event = v;
> +
> +     event_size = calc_tpm2_event_size(event, event_header);
> +     if (((v + event_size) >= limit) || (event_size == 0))
> +             return NULL;
> +
> +     (*pos)++;
> +     return v;
> +}
> +
> +static void tpm2_bios_measurements_stop(struct seq_file *m, void *v)
> +{
> +}
> +
> +static int tpm2_binary_bios_measurements_show(struct seq_file *m, void *v)
> +{
> +     struct tpm_bios_log *log = m->private;
> +     struct tcg_pcr_event *event_header = log->bios_event_log;
> +     struct tcg_pcr_event2 *event = v;
> +     void *temp_ptr;
> +     size_t size = 0;
> +
> +     if (v == SEQ_START_TOKEN) {
> +
> +             size = sizeof(struct tcg_pcr_event)
> +                     - sizeof(event_header->event)
> +                     + event_header->event_size;
> +
> +             temp_ptr = event_header;
> +
> +             if (size > 0)
> +                     seq_write(m, temp_ptr, size);
> +     } else {
> +
> +             size = calc_tpm2_event_size(event, event_header);
> +
> +             temp_ptr = event;
> +             if (size > 0)
> +                     seq_write(m, temp_ptr, size);
> +     }
> +
> +     return 0;
> +}
> +
> +const struct seq_operations tpm2_binary_b_measurments_seqops = {
> +     .start = tpm2_bios_measurements_start,
> +     .next = tpm2_bios_measurements_next,
> +     .stop = tpm2_bios_measurements_stop,
> +     .show = tpm2_binary_bios_measurements_show,
> +};
> diff --git a/drivers/char/tpm/tpm_eventlog.h b/drivers/char/tpm/tpm_eventlog.h
> index b888c77..3297fda 100644
> --- a/drivers/char/tpm/tpm_eventlog.h
> +++ b/drivers/char/tpm/tpm_eventlog.h
> @@ -78,7 +78,7 @@ enum tcpa_pc_event_ids {
>  int read_log(struct tpm_bios_log *log, struct tpm_chip *chip);
>  
>  #if defined(CONFIG_TCG_IBMVTPM) || defined(CONFIG_TCG_IBMVTPM_MODULE) || \
> -     defined(CONFIG_ACPI)
> +     defined(CONFIG_ACPI) || defined(CONFIG_PPC64)
>  extern void tpm_bios_log_setup(struct tpm_chip *chip);
>  extern void tpm_bios_log_teardown(struct tpm_chip *chip);
>  #else
> diff --git a/drivers/char/tpm/tpm_eventlog_init.c 
> b/drivers/char/tpm/tpm_eventlog_init.c
> index dd5dbc4..a3fb5bc 100644
> --- a/drivers/char/tpm/tpm_eventlog_init.c
> +++ b/drivers/char/tpm/tpm_eventlog_init.c
> @@ -28,6 +28,7 @@
>  #include <linux/slab.h>
>  
>  #include "tpm.h"
> +#include "tpm2.h"
>  #include "tpm_eventlog.h"
>  
>  
> @@ -103,36 +104,54 @@ void tpm_bios_log_setup(struct tpm_chip *chip)
>  {
>       struct dentry *tpm_dir, *bin_file, *ascii_file;
>       const char *name = dev_name(&chip->dev);
> +     void *seq_ops;
> +     int num_files = 0;
>       int i;
>  
>       for (i = 0; i < 3; i++)
>               chip->bios_dir[i] = NULL;
>  
> +     /*
> +      * NOTE: Currently, support is added only for binary_bios_measurements
> +      * for TPM2.0. And so it is required to check that if device is TPM2,
> +      * only 2 entries are allocated i.e. tpm0 dir and
> +      * binary_bios_measurements file.
> +      */
> +
> +     num_files = chip->flags & TPM_CHIP_FLAG_TPM2 ? 2 : 3;
> +
>       tpm_dir = securityfs_create_dir(name, NULL);
>       if (is_bad(tpm_dir))
>               goto out;
>  
>       tpm_dir->d_inode->i_private = chip;
>  
> +     if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +             seq_ops = (void *)&tpm2_binary_b_measurments_seqops;
> +     else
> +             seq_ops = (void *)&tpm_binary_b_measurments_seqops;
> +
>       bin_file =
>           securityfs_create_file("binary_bios_measurements",
>                                  S_IRUSR | S_IRGRP, tpm_dir,
> -                                (void *)&tpm_binary_b_measurments_seqops,
> +                                seq_ops,
>                                  &tpm_bios_measurements_ops);
>       if (is_bad(bin_file))
>               goto out_tpm;
>  
> -     ascii_file =
> -         securityfs_create_file("ascii_bios_measurements",
> -                                S_IRUSR | S_IRGRP, tpm_dir,
> -                                (void *)&tpm_ascii_b_measurments_seqops,
> -                                &tpm_bios_measurements_ops);
> -     if (is_bad(ascii_file))
> -             goto out_bin;
> -
> -     chip->bios_dir[0] = ascii_file;
> -     chip->bios_dir[1] = bin_file;
> -     chip->bios_dir[2] = tpm_dir;
> +     chip->bios_dir[num_files-1] = tpm_dir;
> +     chip->bios_dir[num_files-2] = bin_file;
> +
> +     if (num_files == 3) {
> +             ascii_file =
> +                     securityfs_create_file("ascii_bios_measurements",
> +                                     S_IRUSR | S_IRGRP, tpm_dir,
> +                                     (void *)&tpm_ascii_b_measurments_seqops,
> +                                     &tpm_bios_measurements_ops);
> +             if (is_bad(ascii_file))
> +                     goto out_bin;
> +             chip->bios_dir[num_files-3] = ascii_file;
> +     }
>  
>       return;
>  
> diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_of.c
> index 30a9905..d3c72ce 100644
> --- a/drivers/char/tpm/tpm_of.c
> +++ b/drivers/char/tpm/tpm_of.c
> @@ -26,6 +26,7 @@ int read_log(struct tpm_bios_log *log, struct tpm_chip 
> *chip)
>       struct device_node *np;
>       const u32 *sizep;
>       const u64 *basep;
> +     u32 log_size;
>  
>       if (log->bios_event_log != NULL) {
>               pr_err("%s: ERROR - Eventlog already initialized\n", __func__);
> @@ -52,6 +53,11 @@ int read_log(struct tpm_bios_log *log, struct tpm_chip 
> *chip)
>               goto cleanup_eio;
>       }
>  
> +     if (!strncmp(np->name, "tpm", 3))
> +             log_size = be32_to_cpup(sizep);
> +     else
> +             log_size = *sizep;
> +
>       basep = of_get_property(np, "linux,sml-base", NULL);
>       if (basep == NULL) {
>               dev_dbg(&chip->dev, "%s: ERROR - SML not found\n",
> @@ -59,15 +65,20 @@ int read_log(struct tpm_bios_log *log, struct tpm_chip 
> *chip)
>               goto cleanup_eio;
>       }
>  
> -     log->bios_event_log = kmalloc(*sizep, GFP_KERNEL);
> +     log->bios_event_log = kmalloc(log_size, GFP_KERNEL);
>       if (!log->bios_event_log) {
>               of_node_put(np);
>               return -ENOMEM;
>       }
>  
> -     log->bios_event_log_end = log->bios_event_log + *sizep;
> +     log->bios_event_log_end = log->bios_event_log + log_size;
> +
> +     if (!strncmp(np->name, "tpm", 3))
> +             memcpy(log->bios_event_log, __va(be64_to_cpup(basep)),
> +             log_size);
> +     else
> +             memcpy(log->bios_event_log, __va(*basep), log_size);
>  
> -     memcpy(log->bios_event_log, __va(*basep), *sizep);
>       of_node_put(np);
>  
>       return 0;
> -- 
> 2.5.0
> 
> 
> ------------------------------------------------------------------------------
> What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
> patterns at an interface-level. Reveals which users, apps, and protocols are 
> consuming the most bandwidth. Provides multi-vendor support for NetFlow, 
> J-Flow, sFlow and other flows. Make informed decisions using capacity 
> planning reports. http://sdm.link/zohodev2dev
> _______________________________________________
> tpmdd-devel mailing list
> tpmdd-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/tpmdd-devel

------------------------------------------------------------------------------
What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
patterns at an interface-level. Reveals which users, apps, and protocols are 
consuming the most bandwidth. Provides multi-vendor support for NetFlow, 
J-Flow, sFlow and other flows. Make informed decisions using capacity 
planning reports. http://sdm.link/zohodev2dev
_______________________________________________
tpmdd-devel mailing list
tpmdd-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tpmdd-devel

Reply via email to