Commit | Line | Data |
---|---|---|
b886d83c | 1 | // SPDX-License-Identifier: GPL-2.0-only |
000a07b0 JG |
2 | /* |
3 | * Copyright (C) 2004 IBM Corporation | |
4 | * Authors: | |
5 | * Leendert van Doorn <leendert@watson.ibm.com> | |
6 | * Dave Safford <safford@watson.ibm.com> | |
7 | * Reiner Sailer <sailer@watson.ibm.com> | |
8 | * Kylene Hall <kjhall@us.ibm.com> | |
9 | * | |
1e3b73a9 JG |
10 | * Copyright (C) 2013 Obsidian Research Corp |
11 | * Jason Gunthorpe <jgunthorpe@obsidianresearch.com> | |
12 | * | |
000a07b0 | 13 | * sysfs filesystem inspection interface to the TPM |
000a07b0 JG |
14 | */ |
15 | #include <linux/device.h> | |
16 | #include "tpm.h" | |
17 | ||
da379f3c JS |
18 | struct tpm_readpubek_out { |
19 | u8 algorithm[4]; | |
20 | u8 encscheme[2]; | |
21 | u8 sigscheme[2]; | |
22 | __be32 paramsize; | |
23 | u8 parameters[12]; | |
24 | __be32 keysize; | |
25 | u8 modulus[256]; | |
26 | u8 checksum[20]; | |
27 | } __packed; | |
28 | ||
c659af78 | 29 | #define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256) |
a69faebf | 30 | #define TPM_ORD_READPUBEK 124 |
da379f3c | 31 | |
1e3b73a9 JG |
32 | static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, |
33 | char *buf) | |
000a07b0 | 34 | { |
da379f3c JS |
35 | struct tpm_buf tpm_buf; |
36 | struct tpm_readpubek_out *out; | |
da379f3c | 37 | int i; |
000a07b0 | 38 | char *str = buf; |
062807f2 | 39 | struct tpm_chip *chip = to_tpm_chip(dev); |
da379f3c | 40 | char anti_replay[20]; |
000a07b0 | 41 | |
da379f3c JS |
42 | memset(&anti_replay, 0, sizeof(anti_replay)); |
43 | ||
2677ca98 | 44 | if (tpm_try_get_ops(chip)) |
c6286100 | 45 | return 0; |
13b47cfc | 46 | |
2677ca98 JS |
47 | if (tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK)) |
48 | goto out_ops; | |
49 | ||
da379f3c | 50 | tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay)); |
000a07b0 | 51 | |
2677ca98 | 52 | if (tpm_transmit_cmd(chip, &tpm_buf, READ_PUBEK_RESULT_MIN_BODY_SIZE, |
47a6c28b | 53 | "attempting to read the PUBEK")) |
2677ca98 | 54 | goto out_buf; |
da379f3c JS |
55 | |
56 | out = (struct tpm_readpubek_out *)&tpm_buf.data[10]; | |
000a07b0 JG |
57 | str += |
58 | sprintf(str, | |
e08c6d3b AS |
59 | "Algorithm: %4ph\n" |
60 | "Encscheme: %2ph\n" | |
61 | "Sigscheme: %2ph\n" | |
62 | "Parameters: %12ph\n" | |
000a07b0 JG |
63 | "Modulus length: %d\n" |
64 | "Modulus:\n", | |
e08c6d3b AS |
65 | out->algorithm, |
66 | out->encscheme, | |
67 | out->sigscheme, | |
68 | out->parameters, | |
da379f3c | 69 | be32_to_cpu(out->keysize)); |
000a07b0 | 70 | |
e08c6d3b AS |
71 | for (i = 0; i < 256; i += 16) |
72 | str += sprintf(str, "%16ph\n", &out->modulus[i]); | |
da379f3c | 73 | |
2677ca98 | 74 | out_buf: |
da379f3c | 75 | tpm_buf_destroy(&tpm_buf); |
2677ca98 JS |
76 | out_ops: |
77 | tpm_put_ops(chip); | |
78 | return str - buf; | |
000a07b0 | 79 | } |
1e3b73a9 | 80 | static DEVICE_ATTR_RO(pubek); |
000a07b0 | 81 | |
1e3b73a9 JG |
82 | static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr, |
83 | char *buf) | |
000a07b0 JG |
84 | { |
85 | cap_t cap; | |
86 | u8 digest[TPM_DIGEST_SIZE]; | |
95adc6b4 | 87 | u32 i, j, num_pcrs; |
000a07b0 | 88 | char *str = buf; |
062807f2 | 89 | struct tpm_chip *chip = to_tpm_chip(dev); |
000a07b0 | 90 | |
2677ca98 JS |
91 | if (tpm_try_get_ops(chip)) |
92 | return 0; | |
93 | ||
41484674 JS |
94 | if (tpm1_getcap(chip, TPM_CAP_PROP_PCR, &cap, |
95 | "attempting to determine the number of PCRS", | |
2677ca98 JS |
96 | sizeof(cap.num_pcrs))) { |
97 | tpm_put_ops(chip); | |
000a07b0 | 98 | return 0; |
2677ca98 | 99 | } |
000a07b0 JG |
100 | |
101 | num_pcrs = be32_to_cpu(cap.num_pcrs); | |
102 | for (i = 0; i < num_pcrs; i++) { | |
41484674 JS |
103 | if (tpm1_pcr_read(chip, i, digest)) { |
104 | str = buf; | |
000a07b0 | 105 | break; |
41484674 | 106 | } |
000a07b0 JG |
107 | str += sprintf(str, "PCR-%02d: ", i); |
108 | for (j = 0; j < TPM_DIGEST_SIZE; j++) | |
109 | str += sprintf(str, "%02X ", digest[j]); | |
110 | str += sprintf(str, "\n"); | |
111 | } | |
2677ca98 | 112 | tpm_put_ops(chip); |
000a07b0 JG |
113 | return str - buf; |
114 | } | |
1e3b73a9 | 115 | static DEVICE_ATTR_RO(pcrs); |
000a07b0 | 116 | |
1e3b73a9 JG |
117 | static ssize_t enabled_show(struct device *dev, struct device_attribute *attr, |
118 | char *buf) | |
000a07b0 | 119 | { |
2677ca98 JS |
120 | struct tpm_chip *chip = to_tpm_chip(dev); |
121 | ssize_t rc = 0; | |
000a07b0 | 122 | cap_t cap; |
000a07b0 | 123 | |
2677ca98 | 124 | if (tpm_try_get_ops(chip)) |
000a07b0 JG |
125 | return 0; |
126 | ||
2677ca98 JS |
127 | if (tpm1_getcap(chip, TPM_CAP_FLAG_PERM, &cap, |
128 | "attempting to determine the permanent enabled state", | |
129 | sizeof(cap.perm_flags))) | |
130 | goto out_ops; | |
131 | ||
000a07b0 | 132 | rc = sprintf(buf, "%d\n", !cap.perm_flags.disable); |
2677ca98 JS |
133 | out_ops: |
134 | tpm_put_ops(chip); | |
000a07b0 JG |
135 | return rc; |
136 | } | |
1e3b73a9 | 137 | static DEVICE_ATTR_RO(enabled); |
000a07b0 | 138 | |
5f64822d | 139 | static ssize_t active_show(struct device *dev, struct device_attribute *attr, |
1e3b73a9 | 140 | char *buf) |
000a07b0 | 141 | { |
2677ca98 JS |
142 | struct tpm_chip *chip = to_tpm_chip(dev); |
143 | ssize_t rc = 0; | |
000a07b0 | 144 | cap_t cap; |
000a07b0 | 145 | |
2677ca98 | 146 | if (tpm_try_get_ops(chip)) |
000a07b0 JG |
147 | return 0; |
148 | ||
2677ca98 JS |
149 | if (tpm1_getcap(chip, TPM_CAP_FLAG_PERM, &cap, |
150 | "attempting to determine the permanent active state", | |
151 | sizeof(cap.perm_flags))) | |
152 | goto out_ops; | |
153 | ||
000a07b0 | 154 | rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated); |
2677ca98 JS |
155 | out_ops: |
156 | tpm_put_ops(chip); | |
000a07b0 JG |
157 | return rc; |
158 | } | |
1e3b73a9 | 159 | static DEVICE_ATTR_RO(active); |
000a07b0 | 160 | |
1e3b73a9 JG |
161 | static ssize_t owned_show(struct device *dev, struct device_attribute *attr, |
162 | char *buf) | |
000a07b0 | 163 | { |
2677ca98 JS |
164 | struct tpm_chip *chip = to_tpm_chip(dev); |
165 | ssize_t rc = 0; | |
000a07b0 | 166 | cap_t cap; |
000a07b0 | 167 | |
2677ca98 | 168 | if (tpm_try_get_ops(chip)) |
000a07b0 JG |
169 | return 0; |
170 | ||
2677ca98 JS |
171 | if (tpm1_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap, |
172 | "attempting to determine the owner state", | |
173 | sizeof(cap.owned))) | |
174 | goto out_ops; | |
175 | ||
000a07b0 | 176 | rc = sprintf(buf, "%d\n", cap.owned); |
2677ca98 JS |
177 | out_ops: |
178 | tpm_put_ops(chip); | |
000a07b0 JG |
179 | return rc; |
180 | } | |
1e3b73a9 | 181 | static DEVICE_ATTR_RO(owned); |
000a07b0 | 182 | |
1e3b73a9 JG |
183 | static ssize_t temp_deactivated_show(struct device *dev, |
184 | struct device_attribute *attr, char *buf) | |
000a07b0 | 185 | { |
2677ca98 JS |
186 | struct tpm_chip *chip = to_tpm_chip(dev); |
187 | ssize_t rc = 0; | |
000a07b0 | 188 | cap_t cap; |
000a07b0 | 189 | |
2677ca98 | 190 | if (tpm_try_get_ops(chip)) |
000a07b0 JG |
191 | return 0; |
192 | ||
2677ca98 JS |
193 | if (tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap, |
194 | "attempting to determine the temporary state", | |
195 | sizeof(cap.stclear_flags))) | |
196 | goto out_ops; | |
197 | ||
000a07b0 | 198 | rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated); |
2677ca98 JS |
199 | out_ops: |
200 | tpm_put_ops(chip); | |
000a07b0 JG |
201 | return rc; |
202 | } | |
1e3b73a9 | 203 | static DEVICE_ATTR_RO(temp_deactivated); |
000a07b0 | 204 | |
1e3b73a9 JG |
205 | static ssize_t caps_show(struct device *dev, struct device_attribute *attr, |
206 | char *buf) | |
000a07b0 | 207 | { |
062807f2 | 208 | struct tpm_chip *chip = to_tpm_chip(dev); |
f2f5820e | 209 | struct tpm1_version *version; |
2677ca98 | 210 | ssize_t rc = 0; |
000a07b0 | 211 | char *str = buf; |
2677ca98 | 212 | cap_t cap; |
000a07b0 | 213 | |
2677ca98 | 214 | if (tpm_try_get_ops(chip)) |
000a07b0 | 215 | return 0; |
2677ca98 JS |
216 | |
217 | if (tpm1_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap, | |
218 | "attempting to determine the manufacturer", | |
219 | sizeof(cap.manufacturer_id))) | |
220 | goto out_ops; | |
221 | ||
000a07b0 JG |
222 | str += sprintf(str, "Manufacturer: 0x%x\n", |
223 | be32_to_cpu(cap.manufacturer_id)); | |
224 | ||
f2f5820e JS |
225 | /* TPM 1.2 */ |
226 | if (!tpm1_getcap(chip, TPM_CAP_VERSION_1_2, &cap, | |
f4d916b7 | 227 | "attempting to determine the 1.2 version", |
f2f5820e JS |
228 | sizeof(cap.version2))) { |
229 | version = &cap.version2.version; | |
230 | goto out_print; | |
000a07b0 | 231 | } |
f2f5820e JS |
232 | |
233 | /* TPM 1.1 */ | |
234 | if (tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap, | |
235 | "attempting to determine the 1.1 version", | |
236 | sizeof(cap.version1))) { | |
237 | goto out_ops; | |
238 | } | |
239 | ||
240 | version = &cap.version1; | |
241 | ||
242 | out_print: | |
243 | str += sprintf(str, | |
244 | "TCG version: %d.%d\nFirmware version: %d.%d\n", | |
245 | version->major, version->minor, | |
246 | version->rev_major, version->rev_minor); | |
247 | ||
2677ca98 | 248 | rc = str - buf; |
f2f5820e | 249 | |
2677ca98 JS |
250 | out_ops: |
251 | tpm_put_ops(chip); | |
252 | return rc; | |
000a07b0 | 253 | } |
1e3b73a9 | 254 | static DEVICE_ATTR_RO(caps); |
000a07b0 | 255 | |
1e3b73a9 JG |
256 | static ssize_t cancel_store(struct device *dev, struct device_attribute *attr, |
257 | const char *buf, size_t count) | |
000a07b0 | 258 | { |
062807f2 | 259 | struct tpm_chip *chip = to_tpm_chip(dev); |
2677ca98 JS |
260 | |
261 | if (tpm_try_get_ops(chip)) | |
000a07b0 JG |
262 | return 0; |
263 | ||
5f82e9f0 | 264 | chip->ops->cancel(chip); |
2677ca98 | 265 | tpm_put_ops(chip); |
000a07b0 JG |
266 | return count; |
267 | } | |
1e3b73a9 | 268 | static DEVICE_ATTR_WO(cancel); |
000a07b0 | 269 | |
1e3b73a9 JG |
270 | static ssize_t durations_show(struct device *dev, struct device_attribute *attr, |
271 | char *buf) | |
000a07b0 | 272 | { |
062807f2 | 273 | struct tpm_chip *chip = to_tpm_chip(dev); |
000a07b0 | 274 | |
af782f33 | 275 | if (chip->duration[TPM_LONG] == 0) |
000a07b0 JG |
276 | return 0; |
277 | ||
278 | return sprintf(buf, "%d %d %d [%s]\n", | |
af782f33 CR |
279 | jiffies_to_usecs(chip->duration[TPM_SHORT]), |
280 | jiffies_to_usecs(chip->duration[TPM_MEDIUM]), | |
281 | jiffies_to_usecs(chip->duration[TPM_LONG]), | |
282 | chip->duration_adjusted | |
000a07b0 JG |
283 | ? "adjusted" : "original"); |
284 | } | |
1e3b73a9 | 285 | static DEVICE_ATTR_RO(durations); |
000a07b0 | 286 | |
1e3b73a9 JG |
287 | static ssize_t timeouts_show(struct device *dev, struct device_attribute *attr, |
288 | char *buf) | |
000a07b0 | 289 | { |
062807f2 | 290 | struct tpm_chip *chip = to_tpm_chip(dev); |
000a07b0 JG |
291 | |
292 | return sprintf(buf, "%d %d %d %d [%s]\n", | |
af782f33 CR |
293 | jiffies_to_usecs(chip->timeout_a), |
294 | jiffies_to_usecs(chip->timeout_b), | |
295 | jiffies_to_usecs(chip->timeout_c), | |
296 | jiffies_to_usecs(chip->timeout_d), | |
297 | chip->timeout_adjusted | |
000a07b0 JG |
298 | ? "adjusted" : "original"); |
299 | } | |
1e3b73a9 JG |
300 | static DEVICE_ATTR_RO(timeouts); |
301 | ||
7084eddf JS |
302 | static ssize_t tpm_version_major_show(struct device *dev, |
303 | struct device_attribute *attr, char *buf) | |
304 | { | |
305 | struct tpm_chip *chip = to_tpm_chip(dev); | |
306 | ||
307 | return sprintf(buf, "%s\n", chip->flags & TPM_CHIP_FLAG_TPM2 | |
308 | ? "2" : "1"); | |
309 | } | |
310 | static DEVICE_ATTR_RO(tpm_version_major); | |
311 | ||
089e0fb3 JB |
312 | #ifdef CONFIG_TCG_TPM2_HMAC |
313 | static ssize_t null_name_show(struct device *dev, struct device_attribute *attr, | |
314 | char *buf) | |
315 | { | |
316 | struct tpm_chip *chip = to_tpm_chip(dev); | |
317 | int size = TPM2_NAME_SIZE; | |
318 | ||
319 | bin2hex(buf, chip->null_key_name, size); | |
320 | size *= 2; | |
321 | buf[size++] = '\n'; | |
322 | return size; | |
323 | } | |
324 | static DEVICE_ATTR_RO(null_name); | |
325 | #endif | |
326 | ||
7084eddf | 327 | static struct attribute *tpm1_dev_attrs[] = { |
1e3b73a9 JG |
328 | &dev_attr_pubek.attr, |
329 | &dev_attr_pcrs.attr, | |
330 | &dev_attr_enabled.attr, | |
331 | &dev_attr_active.attr, | |
332 | &dev_attr_owned.attr, | |
333 | &dev_attr_temp_deactivated.attr, | |
334 | &dev_attr_caps.attr, | |
335 | &dev_attr_cancel.attr, | |
336 | &dev_attr_durations.attr, | |
337 | &dev_attr_timeouts.attr, | |
7084eddf | 338 | &dev_attr_tpm_version_major.attr, |
1e3b73a9 JG |
339 | NULL, |
340 | }; | |
341 | ||
7084eddf JS |
342 | static struct attribute *tpm2_dev_attrs[] = { |
343 | &dev_attr_tpm_version_major.attr, | |
089e0fb3 JB |
344 | #ifdef CONFIG_TCG_TPM2_HMAC |
345 | &dev_attr_null_name.attr, | |
346 | #endif | |
7084eddf JS |
347 | NULL |
348 | }; | |
349 | ||
350 | static const struct attribute_group tpm1_dev_group = { | |
351 | .attrs = tpm1_dev_attrs, | |
352 | }; | |
353 | ||
354 | static const struct attribute_group tpm2_dev_group = { | |
355 | .attrs = tpm2_dev_attrs, | |
1e3b73a9 JG |
356 | }; |
357 | ||
aab73d95 JB |
358 | struct tpm_pcr_attr { |
359 | int alg_id; | |
360 | int pcr; | |
361 | struct device_attribute attr; | |
362 | }; | |
363 | ||
364 | #define to_tpm_pcr_attr(a) container_of(a, struct tpm_pcr_attr, attr) | |
365 | ||
366 | static ssize_t pcr_value_show(struct device *dev, | |
367 | struct device_attribute *attr, | |
368 | char *buf) | |
369 | { | |
370 | struct tpm_pcr_attr *ha = to_tpm_pcr_attr(attr); | |
371 | struct tpm_chip *chip = to_tpm_chip(dev); | |
372 | struct tpm_digest digest; | |
373 | int i; | |
374 | int digest_size = 0; | |
375 | int rc; | |
376 | char *str = buf; | |
377 | ||
378 | for (i = 0; i < chip->nr_allocated_banks; i++) | |
379 | if (ha->alg_id == chip->allocated_banks[i].alg_id) | |
380 | digest_size = chip->allocated_banks[i].digest_size; | |
381 | /* should never happen */ | |
382 | if (!digest_size) | |
383 | return -EINVAL; | |
384 | ||
385 | digest.alg_id = ha->alg_id; | |
386 | rc = tpm_pcr_read(chip, ha->pcr, &digest); | |
387 | if (rc) | |
388 | return rc; | |
389 | for (i = 0; i < digest_size; i++) | |
390 | str += sprintf(str, "%02X", digest.digest[i]); | |
391 | str += sprintf(str, "\n"); | |
392 | ||
393 | return str - buf; | |
394 | } | |
395 | ||
396 | /* | |
397 | * The following set of defines represents all the magic to build | |
398 | * the per hash attribute groups for displaying each bank of PCRs. | |
399 | * The only slight problem with this approach is that every PCR is | |
400 | * hard coded to be present, so you don't know if an PCR is missing | |
401 | * until a cat of the file returns -EINVAL | |
402 | * | |
403 | * Also note you must ignore checkpatch warnings in this macro | |
404 | * code. This is deep macro magic that checkpatch.pl doesn't | |
405 | * understand. | |
406 | */ | |
407 | ||
408 | /* Note, this must match TPM2_PLATFORM_PCR which is fixed at 24. */ | |
409 | #define _TPM_HELPER(_alg, _hash, F) \ | |
410 | F(_alg, _hash, 0) \ | |
411 | F(_alg, _hash, 1) \ | |
412 | F(_alg, _hash, 2) \ | |
413 | F(_alg, _hash, 3) \ | |
414 | F(_alg, _hash, 4) \ | |
415 | F(_alg, _hash, 5) \ | |
416 | F(_alg, _hash, 6) \ | |
417 | F(_alg, _hash, 7) \ | |
418 | F(_alg, _hash, 8) \ | |
419 | F(_alg, _hash, 9) \ | |
420 | F(_alg, _hash, 10) \ | |
421 | F(_alg, _hash, 11) \ | |
422 | F(_alg, _hash, 12) \ | |
423 | F(_alg, _hash, 13) \ | |
424 | F(_alg, _hash, 14) \ | |
425 | F(_alg, _hash, 15) \ | |
426 | F(_alg, _hash, 16) \ | |
427 | F(_alg, _hash, 17) \ | |
428 | F(_alg, _hash, 18) \ | |
429 | F(_alg, _hash, 19) \ | |
430 | F(_alg, _hash, 20) \ | |
431 | F(_alg, _hash, 21) \ | |
432 | F(_alg, _hash, 22) \ | |
433 | F(_alg, _hash, 23) | |
434 | ||
435 | /* ignore checkpatch warning about trailing ; in macro. */ | |
436 | #define PCR_ATTR(_alg, _hash, _pcr) \ | |
437 | static struct tpm_pcr_attr dev_attr_pcr_##_hash##_##_pcr = { \ | |
438 | .alg_id = _alg, \ | |
439 | .pcr = _pcr, \ | |
440 | .attr = { \ | |
441 | .attr = { \ | |
442 | .name = __stringify(_pcr), \ | |
443 | .mode = 0444 \ | |
444 | }, \ | |
445 | .show = pcr_value_show \ | |
446 | } \ | |
447 | }; | |
448 | ||
449 | #define PCR_ATTRS(_alg, _hash) \ | |
450 | _TPM_HELPER(_alg, _hash, PCR_ATTR) | |
451 | ||
452 | /* ignore checkpatch warning about trailing , in macro. */ | |
453 | #define PCR_ATTR_VAL(_alg, _hash, _pcr) \ | |
454 | &dev_attr_pcr_##_hash##_##_pcr.attr.attr, | |
455 | ||
456 | #define PCR_ATTR_GROUP_ARRAY(_alg, _hash) \ | |
457 | static struct attribute *pcr_group_attrs_##_hash[] = { \ | |
458 | _TPM_HELPER(_alg, _hash, PCR_ATTR_VAL) \ | |
459 | NULL \ | |
460 | } | |
461 | ||
462 | #define PCR_ATTR_GROUP(_alg, _hash) \ | |
463 | static struct attribute_group pcr_group_##_hash = { \ | |
464 | .name = "pcr-" __stringify(_hash), \ | |
465 | .attrs = pcr_group_attrs_##_hash \ | |
466 | } | |
467 | ||
468 | #define PCR_ATTR_BUILD(_alg, _hash) \ | |
469 | PCR_ATTRS(_alg, _hash) \ | |
470 | PCR_ATTR_GROUP_ARRAY(_alg, _hash); \ | |
471 | PCR_ATTR_GROUP(_alg, _hash) | |
472 | /* | |
473 | * End of macro structure to build an attribute group containing 24 | |
474 | * PCR value files for each supported hash algorithm | |
475 | */ | |
476 | ||
477 | /* | |
478 | * The next set of macros implements the cleverness for each hash to | |
479 | * build a static attribute group called pcr_group_<hash> which can be | |
480 | * added to chip->groups[]. | |
481 | * | |
482 | * The first argument is the TPM algorithm id and the second is the | |
483 | * hash used as both the suffix and the group name. Note: the group | |
484 | * name is a directory in the top level tpm class with the name | |
485 | * pcr-<hash>, so it must not clash with any other names already | |
486 | * in the sysfs directory. | |
487 | */ | |
488 | PCR_ATTR_BUILD(TPM_ALG_SHA1, sha1); | |
489 | PCR_ATTR_BUILD(TPM_ALG_SHA256, sha256); | |
490 | PCR_ATTR_BUILD(TPM_ALG_SHA384, sha384); | |
491 | PCR_ATTR_BUILD(TPM_ALG_SHA512, sha512); | |
492 | PCR_ATTR_BUILD(TPM_ALG_SM3_256, sm3); | |
493 | ||
494 | ||
062807f2 | 495 | void tpm_sysfs_add_device(struct tpm_chip *chip) |
1e3b73a9 | 496 | { |
aab73d95 JB |
497 | int i; |
498 | ||
062807f2 | 499 | WARN_ON(chip->groups_cnt != 0); |
aab73d95 | 500 | |
0aa69878 | 501 | if (tpm_is_firmware_upgrade(chip)) |
502 | return; | |
503 | ||
7084eddf JS |
504 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
505 | chip->groups[chip->groups_cnt++] = &tpm2_dev_group; | |
506 | else | |
507 | chip->groups[chip->groups_cnt++] = &tpm1_dev_group; | |
aab73d95 JB |
508 | |
509 | /* add one group for each bank hash */ | |
510 | for (i = 0; i < chip->nr_allocated_banks; i++) { | |
511 | switch (chip->allocated_banks[i].alg_id) { | |
512 | case TPM_ALG_SHA1: | |
513 | chip->groups[chip->groups_cnt++] = &pcr_group_sha1; | |
514 | break; | |
515 | case TPM_ALG_SHA256: | |
516 | chip->groups[chip->groups_cnt++] = &pcr_group_sha256; | |
517 | break; | |
518 | case TPM_ALG_SHA384: | |
519 | chip->groups[chip->groups_cnt++] = &pcr_group_sha384; | |
520 | break; | |
521 | case TPM_ALG_SHA512: | |
522 | chip->groups[chip->groups_cnt++] = &pcr_group_sha512; | |
523 | break; | |
524 | case TPM_ALG_SM3_256: | |
525 | chip->groups[chip->groups_cnt++] = &pcr_group_sm3; | |
526 | break; | |
527 | default: | |
528 | /* | |
529 | * If triggers, send a patch to add both a | |
530 | * PCR_ATTR_BUILD() macro above for the | |
531 | * missing algorithm as well as an additional | |
532 | * case in this switch statement. | |
533 | */ | |
534 | dev_err(&chip->dev, | |
535 | "TPM with unsupported bank algorithm 0x%04x", | |
536 | chip->allocated_banks[i].alg_id); | |
537 | break; | |
538 | } | |
539 | } | |
540 | ||
541 | /* | |
542 | * This will only trigger if someone has added an additional | |
543 | * hash to the tpm_algorithms enum without incrementing | |
544 | * TPM_MAX_HASHES. | |
545 | */ | |
546 | WARN_ON(chip->groups_cnt > TPM_MAX_HASHES + 1); | |
1e3b73a9 | 547 | } |