xref: /openbmc/linux/drivers/char/tpm/tpm-sysfs.c (revision ae0be8de)
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 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 	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 
90 out_buf:
91 	tpm_buf_destroy(&tpm_buf);
92 out_ops:
93 	tpm_put_ops(chip);
94 	return str - buf;
95 }
96 static DEVICE_ATTR_RO(pubek);
97 
98 static 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 }
131 static DEVICE_ATTR_RO(pcrs);
132 
133 static 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);
149 out_ops:
150 	tpm_put_ops(chip);
151 	return rc;
152 }
153 static DEVICE_ATTR_RO(enabled);
154 
155 static 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);
171 out_ops:
172 	tpm_put_ops(chip);
173 	return rc;
174 }
175 static DEVICE_ATTR_RO(active);
176 
177 static 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);
193 out_ops:
194 	tpm_put_ops(chip);
195 	return rc;
196 }
197 static DEVICE_ATTR_RO(owned);
198 
199 static 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);
215 out_ops:
216 	tpm_put_ops(chip);
217 	return rc;
218 }
219 static DEVICE_ATTR_RO(temp_deactivated);
220 
221 static 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;
265 out_ops:
266 	tpm_put_ops(chip);
267 	return rc;
268 }
269 static DEVICE_ATTR_RO(caps);
270 
271 static 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 }
283 static DEVICE_ATTR_WO(cancel);
284 
285 static 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 }
300 static DEVICE_ATTR_RO(durations);
301 
302 static 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 }
315 static DEVICE_ATTR_RO(timeouts);
316 
317 static 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 
331 static const struct attribute_group tpm_dev_group = {
332 	.attrs = tpm_dev_attrs,
333 };
334 
335 void 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