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