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