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