linux/drivers/char/tpm/tpm-sysfs.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2004 IBM Corporation
   3 * Authors:
   4 * Leendert van Doorn <leendert@watson.ibm.com>
   5 * Dave Safford <safford@watson.ibm.com>
   6 * Reiner Sailer <sailer@watson.ibm.com>
   7 * Kylene Hall <kjhall@us.ibm.com>
   8 *
   9 * Copyright (C) 2013 Obsidian Research Corp
  10 * Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
  11 *
  12 * sysfs filesystem inspection interface to the TPM
  13 *
  14 * This program is free software; you can redistribute it and/or
  15 * modify it under the terms of the GNU General Public License as
  16 * published by the Free Software Foundation, version 2 of the
  17 * License.
  18 *
  19 */
  20#include <linux/device.h>
  21#include "tpm.h"
  22
  23#define READ_PUBEK_RESULT_SIZE 314
  24#define TPM_ORD_READPUBEK cpu_to_be32(124)
  25static struct tpm_input_header tpm_readpubek_header = {
  26        .tag = TPM_TAG_RQU_COMMAND,
  27        .length = cpu_to_be32(30),
  28        .ordinal = TPM_ORD_READPUBEK
  29};
  30static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
  31                          char *buf)
  32{
  33        u8 *data;
  34        struct tpm_cmd_t tpm_cmd;
  35        ssize_t err;
  36        int i, rc;
  37        char *str = buf;
  38
  39        struct tpm_chip *chip = dev_get_drvdata(dev);
  40
  41        tpm_cmd.header.in = tpm_readpubek_header;
  42        err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
  43                               "attempting to read the PUBEK");
  44        if (err)
  45                goto out;
  46
  47        /*
  48           ignore header 10 bytes
  49           algorithm 32 bits (1 == RSA )
  50           encscheme 16 bits
  51           sigscheme 16 bits
  52           parameters (RSA 12->bytes: keybit, #primes, expbit)
  53           keylenbytes 32 bits
  54           256 byte modulus
  55           ignore checksum 20 bytes
  56         */
  57        data = tpm_cmd.params.readpubek_out_buffer;
  58        str +=
  59            sprintf(str,
  60                    "Algorithm: %02X %02X %02X %02X\n"
  61                    "Encscheme: %02X %02X\n"
  62                    "Sigscheme: %02X %02X\n"
  63                    "Parameters: %02X %02X %02X %02X "
  64                    "%02X %02X %02X %02X "
  65                    "%02X %02X %02X %02X\n"
  66                    "Modulus length: %d\n"
  67                    "Modulus:\n",
  68                    data[0], data[1], data[2], data[3],
  69                    data[4], data[5],
  70                    data[6], data[7],
  71                    data[12], data[13], data[14], data[15],
  72                    data[16], data[17], data[18], data[19],
  73                    data[20], data[21], data[22], data[23],
  74                    be32_to_cpu(*((__be32 *) (data + 24))));
  75
  76        for (i = 0; i < 256; i++) {
  77                str += sprintf(str, "%02X ", data[i + 28]);
  78                if ((i + 1) % 16 == 0)
  79                        str += sprintf(str, "\n");
  80        }
  81out:
  82        rc = str - buf;
  83        return rc;
  84}
  85static DEVICE_ATTR_RO(pubek);
  86
  87static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,
  88                         char *buf)
  89{
  90        cap_t cap;
  91        u8 digest[TPM_DIGEST_SIZE];
  92        ssize_t rc;
  93        int i, j, num_pcrs;
  94        char *str = buf;
  95        struct tpm_chip *chip = dev_get_drvdata(dev);
  96
  97        rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap,
  98                        "attempting to determine the number of PCRS");
  99        if (rc)
 100                return 0;
 101
 102        num_pcrs = be32_to_cpu(cap.num_pcrs);
 103        for (i = 0; i < num_pcrs; i++) {
 104                rc = tpm_pcr_read_dev(chip, i, digest);
 105                if (rc)
 106                        break;
 107                str += sprintf(str, "PCR-%02d: ", i);
 108                for (j = 0; j < TPM_DIGEST_SIZE; j++)
 109                        str += sprintf(str, "%02X ", digest[j]);
 110                str += sprintf(str, "\n");
 111        }
 112        return str - buf;
 113}
 114static DEVICE_ATTR_RO(pcrs);
 115
 116static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
 117                     char *buf)
 118{
 119        cap_t cap;
 120        ssize_t rc;
 121
 122        rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap,
 123                         "attempting to determine the permanent enabled state");
 124        if (rc)
 125                return 0;
 126
 127        rc = sprintf(buf, "%d\n", !cap.perm_flags.disable);
 128        return rc;
 129}
 130static DEVICE_ATTR_RO(enabled);
 131
 132static ssize_t active_show(struct device *dev, struct device_attribute *attr,
 133                    char *buf)
 134{
 135        cap_t cap;
 136        ssize_t rc;
 137
 138        rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap,
 139                         "attempting to determine the permanent active state");
 140        if (rc)
 141                return 0;
 142
 143        rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated);
 144        return rc;
 145}
 146static DEVICE_ATTR_RO(active);
 147
 148static ssize_t owned_show(struct device *dev, struct device_attribute *attr,
 149                          char *buf)
 150{
 151        cap_t cap;
 152        ssize_t rc;
 153
 154        rc = tpm_getcap(dev, TPM_CAP_PROP_OWNER, &cap,
 155                         "attempting to determine the owner state");
 156        if (rc)
 157                return 0;
 158
 159        rc = sprintf(buf, "%d\n", cap.owned);
 160        return rc;
 161}
 162static DEVICE_ATTR_RO(owned);
 163
 164static ssize_t temp_deactivated_show(struct device *dev,
 165                                     struct device_attribute *attr, char *buf)
 166{
 167        cap_t cap;
 168        ssize_t rc;
 169
 170        rc = tpm_getcap(dev, TPM_CAP_FLAG_VOL, &cap,
 171                         "attempting to determine the temporary state");
 172        if (rc)
 173                return 0;
 174
 175        rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated);
 176        return rc;
 177}
 178static DEVICE_ATTR_RO(temp_deactivated);
 179
 180static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
 181                         char *buf)
 182{
 183        cap_t cap;
 184        ssize_t rc;
 185        char *str = buf;
 186
 187        rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap,
 188                        "attempting to determine the manufacturer");
 189        if (rc)
 190                return 0;
 191        str += sprintf(str, "Manufacturer: 0x%x\n",
 192                       be32_to_cpu(cap.manufacturer_id));
 193
 194        /* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */
 195        rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap,
 196                         "attempting to determine the 1.2 version");
 197        if (!rc) {
 198                str += sprintf(str,
 199                               "TCG version: %d.%d\nFirmware version: %d.%d\n",
 200                               cap.tpm_version_1_2.Major,
 201                               cap.tpm_version_1_2.Minor,
 202                               cap.tpm_version_1_2.revMajor,
 203                               cap.tpm_version_1_2.revMinor);
 204        } else {
 205                /* Otherwise just use TPM_STRUCT_VER */
 206                rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap,
 207                                "attempting to determine the 1.1 version");
 208                if (rc)
 209                        return 0;
 210                str += sprintf(str,
 211                               "TCG version: %d.%d\nFirmware version: %d.%d\n",
 212                               cap.tpm_version.Major,
 213                               cap.tpm_version.Minor,
 214                               cap.tpm_version.revMajor,
 215                               cap.tpm_version.revMinor);
 216        }
 217
 218        return str - buf;
 219}
 220static DEVICE_ATTR_RO(caps);
 221
 222static ssize_t cancel_store(struct device *dev, struct device_attribute *attr,
 223                            const char *buf, size_t count)
 224{
 225        struct tpm_chip *chip = dev_get_drvdata(dev);
 226        if (chip == NULL)
 227                return 0;
 228
 229        chip->ops->cancel(chip);
 230        return count;
 231}
 232static DEVICE_ATTR_WO(cancel);
 233
 234static ssize_t durations_show(struct device *dev, struct device_attribute *attr,
 235                              char *buf)
 236{
 237        struct tpm_chip *chip = dev_get_drvdata(dev);
 238
 239        if (chip->vendor.duration[TPM_LONG] == 0)
 240                return 0;
 241
 242        return sprintf(buf, "%d %d %d [%s]\n",
 243                       jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
 244                       jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
 245                       jiffies_to_usecs(chip->vendor.duration[TPM_LONG]),
 246                       chip->vendor.duration_adjusted
 247                       ? "adjusted" : "original");
 248}
 249static DEVICE_ATTR_RO(durations);
 250
 251static ssize_t timeouts_show(struct device *dev, struct device_attribute *attr,
 252                             char *buf)
 253{
 254        struct tpm_chip *chip = dev_get_drvdata(dev);
 255
 256        return sprintf(buf, "%d %d %d %d [%s]\n",
 257                       jiffies_to_usecs(chip->vendor.timeout_a),
 258                       jiffies_to_usecs(chip->vendor.timeout_b),
 259                       jiffies_to_usecs(chip->vendor.timeout_c),
 260                       jiffies_to_usecs(chip->vendor.timeout_d),
 261                       chip->vendor.timeout_adjusted
 262                       ? "adjusted" : "original");
 263}
 264static DEVICE_ATTR_RO(timeouts);
 265
 266static struct attribute *tpm_dev_attrs[] = {
 267        &dev_attr_pubek.attr,
 268        &dev_attr_pcrs.attr,
 269        &dev_attr_enabled.attr,
 270        &dev_attr_active.attr,
 271        &dev_attr_owned.attr,
 272        &dev_attr_temp_deactivated.attr,
 273        &dev_attr_caps.attr,
 274        &dev_attr_cancel.attr,
 275        &dev_attr_durations.attr,
 276        &dev_attr_timeouts.attr,
 277        NULL,
 278};
 279
 280static const struct attribute_group tpm_dev_group = {
 281        .attrs = tpm_dev_attrs,
 282};
 283
 284int tpm_sysfs_add_device(struct tpm_chip *chip)
 285{
 286        int err;
 287        err = sysfs_create_group(&chip->pdev->kobj,
 288                                 &tpm_dev_group);
 289
 290        if (err)
 291                dev_err(chip->pdev,
 292                        "failed to create sysfs attributes, %d\n", err);
 293        return err;
 294}
 295
 296void tpm_sysfs_del_device(struct tpm_chip *chip)
 297{
 298        sysfs_remove_group(&chip->pdev->kobj, &tpm_dev_group);
 299}
 300