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
  23struct tpm_readpubek_out {
  24        u8 algorithm[4];
  25        u8 encscheme[2];
  26        u8 sigscheme[2];
  27        __be32 paramsize;
  28        u8 parameters[12];
  29        __be32 keysize;
  30        u8 modulus[256];
  31        u8 checksum[20];
  32} __packed;
  33
  34#define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256)
  35#define TPM_ORD_READPUBEK 124
  36
  37static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
  38                          char *buf)
  39{
  40        struct tpm_buf tpm_buf;
  41        struct tpm_readpubek_out *out;
  42        int i;
  43        char *str = buf;
  44        struct tpm_chip *chip = to_tpm_chip(dev);
  45        char anti_replay[20];
  46
  47        memset(&anti_replay, 0, sizeof(anti_replay));
  48
  49        if (tpm_try_get_ops(chip))
  50                return 0;
  51
  52        if (tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK))
  53                goto out_ops;
  54
  55        tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay));
  56
  57        if (tpm_transmit_cmd(chip, &tpm_buf, READ_PUBEK_RESULT_MIN_BODY_SIZE,
  58                             "attempting to read the PUBEK"))
  59                goto out_buf;
  60
  61        out = (struct tpm_readpubek_out *)&tpm_buf.data[10];
  62        str +=
  63            sprintf(str,
  64                    "Algorithm: %02X %02X %02X %02X\n"
  65                    "Encscheme: %02X %02X\n"
  66                    "Sigscheme: %02X %02X\n"
  67                    "Parameters: %02X %02X %02X %02X "
  68                    "%02X %02X %02X %02X "
  69                    "%02X %02X %02X %02X\n"
  70                    "Modulus length: %d\n"
  71                    "Modulus:\n",
  72                    out->algorithm[0], out->algorithm[1], out->algorithm[2],
  73                    out->algorithm[3],
  74                    out->encscheme[0], out->encscheme[1],
  75                    out->sigscheme[0], out->sigscheme[1],
  76                    out->parameters[0], out->parameters[1],
  77                    out->parameters[2], out->parameters[3],
  78                    out->parameters[4], out->parameters[5],
  79                    out->parameters[6], out->parameters[7],
  80                    out->parameters[8], out->parameters[9],
  81                    out->parameters[10], out->parameters[11],
  82                    be32_to_cpu(out->keysize));
  83
  84        for (i = 0; i < 256; i++) {
  85                str += sprintf(str, "%02X ", out->modulus[i]);
  86                if ((i + 1) % 16 == 0)
  87                        str += sprintf(str, "\n");
  88        }
  89
  90out_buf:
  91        tpm_buf_destroy(&tpm_buf);
  92out_ops:
  93        tpm_put_ops(chip);
  94        return str - buf;
  95}
  96static DEVICE_ATTR_RO(pubek);
  97
  98static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,
  99                         char *buf)
 100{
 101        cap_t cap;
 102        u8 digest[TPM_DIGEST_SIZE];
 103        u32 i, j, num_pcrs;
 104        char *str = buf;
 105        struct tpm_chip *chip = to_tpm_chip(dev);
 106
 107        if (tpm_try_get_ops(chip))
 108                return 0;
 109
 110        if (tpm1_getcap(chip, TPM_CAP_PROP_PCR, &cap,
 111                        "attempting to determine the number of PCRS",
 112                        sizeof(cap.num_pcrs))) {
 113                tpm_put_ops(chip);
 114                return 0;
 115        }
 116
 117        num_pcrs = be32_to_cpu(cap.num_pcrs);
 118        for (i = 0; i < num_pcrs; i++) {
 119                if (tpm1_pcr_read(chip, i, digest)) {
 120                        str = buf;
 121                        break;
 122                }
 123                str += sprintf(str, "PCR-%02d: ", i);
 124                for (j = 0; j < TPM_DIGEST_SIZE; j++)
 125                        str += sprintf(str, "%02X ", digest[j]);
 126                str += sprintf(str, "\n");
 127        }
 128        tpm_put_ops(chip);
 129        return str - buf;
 130}
 131static DEVICE_ATTR_RO(pcrs);
 132
 133static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
 134                     char *buf)
 135{
 136        struct tpm_chip *chip = to_tpm_chip(dev);
 137        ssize_t rc = 0;
 138        cap_t cap;
 139
 140        if (tpm_try_get_ops(chip))
 141                return 0;
 142
 143        if (tpm1_getcap(chip, TPM_CAP_FLAG_PERM, &cap,
 144                        "attempting to determine the permanent enabled state",
 145                        sizeof(cap.perm_flags)))
 146                goto out_ops;
 147
 148        rc = sprintf(buf, "%d\n", !cap.perm_flags.disable);
 149out_ops:
 150        tpm_put_ops(chip);
 151        return rc;
 152}
 153static DEVICE_ATTR_RO(enabled);
 154
 155static ssize_t active_show(struct device *dev, struct device_attribute *attr,
 156                    char *buf)
 157{
 158        struct tpm_chip *chip = to_tpm_chip(dev);
 159        ssize_t rc = 0;
 160        cap_t cap;
 161
 162        if (tpm_try_get_ops(chip))
 163                return 0;
 164
 165        if (tpm1_getcap(chip, TPM_CAP_FLAG_PERM, &cap,
 166                        "attempting to determine the permanent active state",
 167                        sizeof(cap.perm_flags)))
 168                goto out_ops;
 169
 170        rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated);
 171out_ops:
 172        tpm_put_ops(chip);
 173        return rc;
 174}
 175static DEVICE_ATTR_RO(active);
 176
 177static ssize_t owned_show(struct device *dev, struct device_attribute *attr,
 178                          char *buf)
 179{
 180        struct tpm_chip *chip = to_tpm_chip(dev);
 181        ssize_t rc = 0;
 182        cap_t cap;
 183
 184        if (tpm_try_get_ops(chip))
 185                return 0;
 186
 187        if (tpm1_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap,
 188                        "attempting to determine the owner state",
 189                        sizeof(cap.owned)))
 190                goto out_ops;
 191
 192        rc = sprintf(buf, "%d\n", cap.owned);
 193out_ops:
 194        tpm_put_ops(chip);
 195        return rc;
 196}
 197static DEVICE_ATTR_RO(owned);
 198
 199static ssize_t temp_deactivated_show(struct device *dev,
 200                                     struct device_attribute *attr, char *buf)
 201{
 202        struct tpm_chip *chip = to_tpm_chip(dev);
 203        ssize_t rc = 0;
 204        cap_t cap;
 205
 206        if (tpm_try_get_ops(chip))
 207                return 0;
 208
 209        if (tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap,
 210                        "attempting to determine the temporary state",
 211                        sizeof(cap.stclear_flags)))
 212                goto out_ops;
 213
 214        rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated);
 215out_ops:
 216        tpm_put_ops(chip);
 217        return rc;
 218}
 219static DEVICE_ATTR_RO(temp_deactivated);
 220
 221static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
 222                         char *buf)
 223{
 224        struct tpm_chip *chip = to_tpm_chip(dev);
 225        ssize_t rc = 0;
 226        char *str = buf;
 227        cap_t cap;
 228
 229        if (tpm_try_get_ops(chip))
 230                return 0;
 231
 232        if (tpm1_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap,
 233                        "attempting to determine the manufacturer",
 234                        sizeof(cap.manufacturer_id)))
 235                goto out_ops;
 236
 237        str += sprintf(str, "Manufacturer: 0x%x\n",
 238                       be32_to_cpu(cap.manufacturer_id));
 239
 240        /* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */
 241        rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_2, &cap,
 242                         "attempting to determine the 1.2 version",
 243                         sizeof(cap.tpm_version_1_2));
 244        if (!rc) {
 245                str += sprintf(str,
 246                               "TCG version: %d.%d\nFirmware version: %d.%d\n",
 247                               cap.tpm_version_1_2.Major,
 248                               cap.tpm_version_1_2.Minor,
 249                               cap.tpm_version_1_2.revMajor,
 250                               cap.tpm_version_1_2.revMinor);
 251        } else {
 252                /* Otherwise just use TPM_STRUCT_VER */
 253                if (tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap,
 254                                "attempting to determine the 1.1 version",
 255                                sizeof(cap.tpm_version)))
 256                        goto out_ops;
 257                str += sprintf(str,
 258                               "TCG version: %d.%d\nFirmware version: %d.%d\n",
 259                               cap.tpm_version.Major,
 260                               cap.tpm_version.Minor,
 261                               cap.tpm_version.revMajor,
 262                               cap.tpm_version.revMinor);
 263        }
 264        rc = str - buf;
 265out_ops:
 266        tpm_put_ops(chip);
 267        return rc;
 268}
 269static DEVICE_ATTR_RO(caps);
 270
 271static ssize_t cancel_store(struct device *dev, struct device_attribute *attr,
 272                            const char *buf, size_t count)
 273{
 274        struct tpm_chip *chip = to_tpm_chip(dev);
 275
 276        if (tpm_try_get_ops(chip))
 277                return 0;
 278
 279        chip->ops->cancel(chip);
 280        tpm_put_ops(chip);
 281        return count;
 282}
 283static DEVICE_ATTR_WO(cancel);
 284
 285static ssize_t durations_show(struct device *dev, struct device_attribute *attr,
 286                              char *buf)
 287{
 288        struct tpm_chip *chip = to_tpm_chip(dev);
 289
 290        if (chip->duration[TPM_LONG] == 0)
 291                return 0;
 292
 293        return sprintf(buf, "%d %d %d [%s]\n",
 294                       jiffies_to_usecs(chip->duration[TPM_SHORT]),
 295                       jiffies_to_usecs(chip->duration[TPM_MEDIUM]),
 296                       jiffies_to_usecs(chip->duration[TPM_LONG]),
 297                       chip->duration_adjusted
 298                       ? "adjusted" : "original");
 299}
 300static DEVICE_ATTR_RO(durations);
 301
 302static ssize_t timeouts_show(struct device *dev, struct device_attribute *attr,
 303                             char *buf)
 304{
 305        struct tpm_chip *chip = to_tpm_chip(dev);
 306
 307        return sprintf(buf, "%d %d %d %d [%s]\n",
 308                       jiffies_to_usecs(chip->timeout_a),
 309                       jiffies_to_usecs(chip->timeout_b),
 310                       jiffies_to_usecs(chip->timeout_c),
 311                       jiffies_to_usecs(chip->timeout_d),
 312                       chip->timeout_adjusted
 313                       ? "adjusted" : "original");
 314}
 315static DEVICE_ATTR_RO(timeouts);
 316
 317static struct attribute *tpm_dev_attrs[] = {
 318        &dev_attr_pubek.attr,
 319        &dev_attr_pcrs.attr,
 320        &dev_attr_enabled.attr,
 321        &dev_attr_active.attr,
 322        &dev_attr_owned.attr,
 323        &dev_attr_temp_deactivated.attr,
 324        &dev_attr_caps.attr,
 325        &dev_attr_cancel.attr,
 326        &dev_attr_durations.attr,
 327        &dev_attr_timeouts.attr,
 328        NULL,
 329};
 330
 331static const struct attribute_group tpm_dev_group = {
 332        .attrs = tpm_dev_attrs,
 333};
 334
 335void tpm_sysfs_add_device(struct tpm_chip *chip)
 336{
 337        /* XXX: If you wish to remove this restriction, you must first update
 338         * tpm_sysfs to explicitly lock chip->ops.
 339         */
 340        if (chip->flags & TPM_CHIP_FLAG_TPM2)
 341                return;
 342
 343        /* The sysfs routines rely on an implicit tpm_try_get_ops, device_del
 344         * is called before ops is null'd and the sysfs core synchronizes this
 345         * removal so that no callbacks are running or can run again
 346         */
 347        WARN_ON(chip->groups_cnt != 0);
 348        chip->groups[chip->groups_cnt++] = &tpm_dev_group;
 349}
 350