2 * Copyright (C) 2004 IBM Corporation
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>
9 * Copyright (C) 2013 Obsidian Research Corp
10 * Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
12 * sysfs filesystem inspection interface to the TPM
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
20 #include <linux/device.h>
23 struct tpm_readpubek_out
{
34 #define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256)
35 #define TPM_ORD_READPUBEK 124
37 static ssize_t
pubek_show(struct device
*dev
, struct device_attribute
*attr
,
40 struct tpm_buf tpm_buf
;
41 struct tpm_readpubek_out
*out
;
44 struct tpm_chip
*chip
= to_tpm_chip(dev
);
47 memset(&anti_replay
, 0, sizeof(anti_replay
));
49 if (tpm_try_get_ops(chip
))
52 if (tpm_buf_init(&tpm_buf
, TPM_TAG_RQU_COMMAND
, TPM_ORD_READPUBEK
))
55 tpm_buf_append(&tpm_buf
, anti_replay
, sizeof(anti_replay
));
57 if (tpm_transmit_cmd(chip
, NULL
, tpm_buf
.data
, PAGE_SIZE
,
58 READ_PUBEK_RESULT_MIN_BODY_SIZE
, 0,
59 "attempting to read the PUBEK"))
62 out
= (struct tpm_readpubek_out
*)&tpm_buf
.data
[10];
65 "Algorithm: %02X %02X %02X %02X\n"
66 "Encscheme: %02X %02X\n"
67 "Sigscheme: %02X %02X\n"
68 "Parameters: %02X %02X %02X %02X "
69 "%02X %02X %02X %02X "
70 "%02X %02X %02X %02X\n"
71 "Modulus length: %d\n"
73 out
->algorithm
[0], out
->algorithm
[1], out
->algorithm
[2],
75 out
->encscheme
[0], out
->encscheme
[1],
76 out
->sigscheme
[0], out
->sigscheme
[1],
77 out
->parameters
[0], out
->parameters
[1],
78 out
->parameters
[2], out
->parameters
[3],
79 out
->parameters
[4], out
->parameters
[5],
80 out
->parameters
[6], out
->parameters
[7],
81 out
->parameters
[8], out
->parameters
[9],
82 out
->parameters
[10], out
->parameters
[11],
83 be32_to_cpu(out
->keysize
));
85 for (i
= 0; i
< 256; i
++) {
86 str
+= sprintf(str
, "%02X ", out
->modulus
[i
]);
87 if ((i
+ 1) % 16 == 0)
88 str
+= sprintf(str
, "\n");
92 tpm_buf_destroy(&tpm_buf
);
97 static DEVICE_ATTR_RO(pubek
);
99 static ssize_t
pcrs_show(struct device
*dev
, struct device_attribute
*attr
,
103 u8 digest
[TPM_DIGEST_SIZE
];
107 struct tpm_chip
*chip
= to_tpm_chip(dev
);
109 if (tpm_try_get_ops(chip
))
112 if (tpm_getcap(chip
, TPM_CAP_PROP_PCR
, &cap
,
113 "attempting to determine the number of PCRS",
114 sizeof(cap
.num_pcrs
))) {
119 num_pcrs
= be32_to_cpu(cap
.num_pcrs
);
120 for (i
= 0; i
< num_pcrs
; i
++) {
121 rc
= tpm_pcr_read_dev(chip
, i
, digest
);
124 str
+= sprintf(str
, "PCR-%02d: ", i
);
125 for (j
= 0; j
< TPM_DIGEST_SIZE
; j
++)
126 str
+= sprintf(str
, "%02X ", digest
[j
]);
127 str
+= sprintf(str
, "\n");
132 static DEVICE_ATTR_RO(pcrs
);
134 static ssize_t
enabled_show(struct device
*dev
, struct device_attribute
*attr
,
137 struct tpm_chip
*chip
= to_tpm_chip(dev
);
141 if (tpm_try_get_ops(chip
))
144 if (tpm_getcap(chip
, TPM_CAP_FLAG_PERM
, &cap
,
145 "attempting to determine the permanent enabled state",
146 sizeof(cap
.perm_flags
)))
149 rc
= sprintf(buf
, "%d\n", !cap
.perm_flags
.disable
);
154 static DEVICE_ATTR_RO(enabled
);
156 static ssize_t
active_show(struct device
*dev
, struct device_attribute
*attr
,
159 struct tpm_chip
*chip
= to_tpm_chip(dev
);
163 if (tpm_try_get_ops(chip
))
166 if (tpm_getcap(chip
, TPM_CAP_FLAG_PERM
, &cap
,
167 "attempting to determine the permanent active state",
168 sizeof(cap
.perm_flags
)))
171 rc
= sprintf(buf
, "%d\n", !cap
.perm_flags
.deactivated
);
176 static DEVICE_ATTR_RO(active
);
178 static ssize_t
owned_show(struct device
*dev
, struct device_attribute
*attr
,
181 struct tpm_chip
*chip
= to_tpm_chip(dev
);
185 if (tpm_try_get_ops(chip
))
188 if (tpm_getcap(to_tpm_chip(dev
), TPM_CAP_PROP_OWNER
, &cap
,
189 "attempting to determine the owner state",
193 rc
= sprintf(buf
, "%d\n", cap
.owned
);
198 static DEVICE_ATTR_RO(owned
);
200 static ssize_t
temp_deactivated_show(struct device
*dev
,
201 struct device_attribute
*attr
, char *buf
)
203 struct tpm_chip
*chip
= to_tpm_chip(dev
);
207 if (tpm_try_get_ops(chip
))
210 if (tpm_getcap(to_tpm_chip(dev
), TPM_CAP_FLAG_VOL
, &cap
,
211 "attempting to determine the temporary state",
212 sizeof(cap
.stclear_flags
)))
215 rc
= sprintf(buf
, "%d\n", cap
.stclear_flags
.deactivated
);
220 static DEVICE_ATTR_RO(temp_deactivated
);
222 static ssize_t
caps_show(struct device
*dev
, struct device_attribute
*attr
,
225 struct tpm_chip
*chip
= to_tpm_chip(dev
);
230 if (tpm_try_get_ops(chip
))
233 if (tpm_getcap(chip
, TPM_CAP_PROP_MANUFACTURER
, &cap
,
234 "attempting to determine the manufacturer",
235 sizeof(cap
.manufacturer_id
)))
238 str
+= sprintf(str
, "Manufacturer: 0x%x\n",
239 be32_to_cpu(cap
.manufacturer_id
));
241 /* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */
242 rc
= tpm_getcap(chip
, TPM_CAP_VERSION_1_2
, &cap
,
243 "attempting to determine the 1.2 version",
244 sizeof(cap
.tpm_version_1_2
));
247 "TCG version: %d.%d\nFirmware version: %d.%d\n",
248 cap
.tpm_version_1_2
.Major
,
249 cap
.tpm_version_1_2
.Minor
,
250 cap
.tpm_version_1_2
.revMajor
,
251 cap
.tpm_version_1_2
.revMinor
);
253 /* Otherwise just use TPM_STRUCT_VER */
254 if (tpm_getcap(chip
, TPM_CAP_VERSION_1_1
, &cap
,
255 "attempting to determine the 1.1 version",
256 sizeof(cap
.tpm_version
)))
260 "TCG version: %d.%d\nFirmware version: %d.%d\n",
261 cap
.tpm_version
.Major
,
262 cap
.tpm_version
.Minor
,
263 cap
.tpm_version
.revMajor
,
264 cap
.tpm_version
.revMinor
);
271 static DEVICE_ATTR_RO(caps
);
273 static ssize_t
cancel_store(struct device
*dev
, struct device_attribute
*attr
,
274 const char *buf
, size_t count
)
276 struct tpm_chip
*chip
= to_tpm_chip(dev
);
278 if (tpm_try_get_ops(chip
))
281 chip
->ops
->cancel(chip
);
285 static DEVICE_ATTR_WO(cancel
);
287 static ssize_t
durations_show(struct device
*dev
, struct device_attribute
*attr
,
290 struct tpm_chip
*chip
= to_tpm_chip(dev
);
292 if (chip
->duration
[TPM_LONG
] == 0)
295 return sprintf(buf
, "%d %d %d [%s]\n",
296 jiffies_to_usecs(chip
->duration
[TPM_SHORT
]),
297 jiffies_to_usecs(chip
->duration
[TPM_MEDIUM
]),
298 jiffies_to_usecs(chip
->duration
[TPM_LONG
]),
299 chip
->duration_adjusted
300 ? "adjusted" : "original");
302 static DEVICE_ATTR_RO(durations
);
304 static ssize_t
timeouts_show(struct device
*dev
, struct device_attribute
*attr
,
307 struct tpm_chip
*chip
= to_tpm_chip(dev
);
309 return sprintf(buf
, "%d %d %d %d [%s]\n",
310 jiffies_to_usecs(chip
->timeout_a
),
311 jiffies_to_usecs(chip
->timeout_b
),
312 jiffies_to_usecs(chip
->timeout_c
),
313 jiffies_to_usecs(chip
->timeout_d
),
314 chip
->timeout_adjusted
315 ? "adjusted" : "original");
317 static DEVICE_ATTR_RO(timeouts
);
319 static struct attribute
*tpm_dev_attrs
[] = {
320 &dev_attr_pubek
.attr
,
322 &dev_attr_enabled
.attr
,
323 &dev_attr_active
.attr
,
324 &dev_attr_owned
.attr
,
325 &dev_attr_temp_deactivated
.attr
,
327 &dev_attr_cancel
.attr
,
328 &dev_attr_durations
.attr
,
329 &dev_attr_timeouts
.attr
,
333 static const struct attribute_group tpm_dev_group
= {
334 .attrs
= tpm_dev_attrs
,
337 void tpm_sysfs_add_device(struct tpm_chip
*chip
)
339 /* XXX: If you wish to remove this restriction, you must first update
340 * tpm_sysfs to explicitly lock chip->ops.
342 if (chip
->flags
& TPM_CHIP_FLAG_TPM2
)
345 /* The sysfs routines rely on an implicit tpm_try_get_ops, device_del
346 * is called before ops is null'd and the sysfs core synchronizes this
347 * removal so that no callbacks are running or can run again
349 WARN_ON(chip
->groups_cnt
!= 0);
350 chip
->groups
[chip
->groups_cnt
++] = &tpm_dev_group
;