2 * Copyright (C) 2014 Intel Corporation
5 * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
7 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
9 * This file contains TPM2 protocol implementations of the commands
10 * used by the kernel internally.
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; version 2
20 struct tpm2_startup_in
{
24 struct tpm2_self_test_in
{
28 struct tpm2_pcr_read_in
{
29 __be32 pcr_selects_cnt
;
32 u8 pcr_select
[TPM2_PCR_SELECT_MIN
];
35 struct tpm2_pcr_read_out
{
37 __be32 pcr_selects_cnt
;
40 u8 pcr_select
[TPM2_PCR_SELECT_MIN
];
43 u8 digest
[TPM_DIGEST_SIZE
];
46 struct tpm2_null_auth_area
{
53 struct tpm2_pcr_extend_in
{
55 __be32 auth_area_size
;
56 struct tpm2_null_auth_area auth_area
;
59 u8 digest
[TPM_DIGEST_SIZE
];
62 struct tpm2_get_tpm_pt_in
{
68 struct tpm2_get_tpm_pt_out
{
76 struct tpm2_get_random_in
{
80 struct tpm2_get_random_out
{
82 u8 buffer
[TPM_MAX_RNG_DATA
];
85 union tpm2_cmd_params
{
86 struct tpm2_startup_in startup_in
;
87 struct tpm2_self_test_in selftest_in
;
88 struct tpm2_pcr_read_in pcrread_in
;
89 struct tpm2_pcr_read_out pcrread_out
;
90 struct tpm2_pcr_extend_in pcrextend_in
;
91 struct tpm2_get_tpm_pt_in get_tpm_pt_in
;
92 struct tpm2_get_tpm_pt_out get_tpm_pt_out
;
93 struct tpm2_get_random_in getrandom_in
;
94 struct tpm2_get_random_out getrandom_out
;
98 tpm_cmd_header header
;
99 union tpm2_cmd_params params
;
103 * Array with one entry per ordinal defining the maximum amount
104 * of time the chip could take to return the result. The values
105 * of the SHORT, MEDIUM, and LONG durations are taken from the
106 * PC Client Profile (PTP) specification.
108 static const u8 tpm2_ordinal_duration
[TPM2_CC_LAST
- TPM2_CC_FIRST
+ 1] = {
109 TPM_UNDEFINED
, /* 11F */
110 TPM_UNDEFINED
, /* 120 */
112 TPM_UNDEFINED
, /* 122 */
113 TPM_UNDEFINED
, /* 123 */
114 TPM_UNDEFINED
, /* 124 */
115 TPM_UNDEFINED
, /* 125 */
116 TPM_UNDEFINED
, /* 126 */
117 TPM_UNDEFINED
, /* 127 */
118 TPM_UNDEFINED
, /* 128 */
120 TPM_UNDEFINED
, /* 12a */
121 TPM_UNDEFINED
, /* 12b */
122 TPM_UNDEFINED
, /* 12c */
123 TPM_UNDEFINED
, /* 12d */
124 TPM_UNDEFINED
, /* 12e */
125 TPM_UNDEFINED
, /* 12f */
126 TPM_UNDEFINED
, /* 130 */
127 TPM_UNDEFINED
, /* 131 */
128 TPM_UNDEFINED
, /* 132 */
129 TPM_UNDEFINED
, /* 133 */
130 TPM_UNDEFINED
, /* 134 */
131 TPM_UNDEFINED
, /* 135 */
132 TPM_UNDEFINED
, /* 136 */
133 TPM_UNDEFINED
, /* 137 */
134 TPM_UNDEFINED
, /* 138 */
135 TPM_UNDEFINED
, /* 139 */
136 TPM_UNDEFINED
, /* 13a */
137 TPM_UNDEFINED
, /* 13b */
138 TPM_UNDEFINED
, /* 13c */
139 TPM_UNDEFINED
, /* 13d */
140 TPM_MEDIUM
, /* 13e */
141 TPM_UNDEFINED
, /* 13f */
142 TPM_UNDEFINED
, /* 140 */
143 TPM_UNDEFINED
, /* 141 */
144 TPM_UNDEFINED
, /* 142 */
146 TPM_MEDIUM
, /* 144 */
147 TPM_UNDEFINED
, /* 145 */
148 TPM_UNDEFINED
, /* 146 */
149 TPM_UNDEFINED
, /* 147 */
150 TPM_UNDEFINED
, /* 148 */
151 TPM_UNDEFINED
, /* 149 */
152 TPM_UNDEFINED
, /* 14a */
153 TPM_UNDEFINED
, /* 14b */
154 TPM_UNDEFINED
, /* 14c */
155 TPM_UNDEFINED
, /* 14d */
157 TPM_UNDEFINED
, /* 14f */
158 TPM_UNDEFINED
, /* 150 */
159 TPM_UNDEFINED
, /* 151 */
160 TPM_UNDEFINED
, /* 152 */
161 TPM_UNDEFINED
, /* 153 */
162 TPM_UNDEFINED
, /* 154 */
163 TPM_UNDEFINED
, /* 155 */
164 TPM_UNDEFINED
, /* 156 */
165 TPM_UNDEFINED
, /* 157 */
166 TPM_UNDEFINED
, /* 158 */
167 TPM_UNDEFINED
, /* 159 */
168 TPM_UNDEFINED
, /* 15a */
169 TPM_UNDEFINED
, /* 15b */
170 TPM_MEDIUM
, /* 15c */
171 TPM_UNDEFINED
, /* 15d */
172 TPM_UNDEFINED
, /* 15e */
173 TPM_UNDEFINED
, /* 15f */
174 TPM_UNDEFINED
, /* 160 */
175 TPM_UNDEFINED
, /* 161 */
176 TPM_UNDEFINED
, /* 162 */
177 TPM_UNDEFINED
, /* 163 */
178 TPM_UNDEFINED
, /* 164 */
179 TPM_UNDEFINED
, /* 165 */
180 TPM_UNDEFINED
, /* 166 */
181 TPM_UNDEFINED
, /* 167 */
182 TPM_UNDEFINED
, /* 168 */
183 TPM_UNDEFINED
, /* 169 */
184 TPM_UNDEFINED
, /* 16a */
185 TPM_UNDEFINED
, /* 16b */
186 TPM_UNDEFINED
, /* 16c */
187 TPM_UNDEFINED
, /* 16d */
188 TPM_UNDEFINED
, /* 16e */
189 TPM_UNDEFINED
, /* 16f */
190 TPM_UNDEFINED
, /* 170 */
191 TPM_UNDEFINED
, /* 171 */
192 TPM_UNDEFINED
, /* 172 */
193 TPM_UNDEFINED
, /* 173 */
194 TPM_UNDEFINED
, /* 174 */
195 TPM_UNDEFINED
, /* 175 */
196 TPM_UNDEFINED
, /* 176 */
198 TPM_UNDEFINED
, /* 178 */
199 TPM_UNDEFINED
, /* 179 */
200 TPM_MEDIUM
, /* 17a */
202 TPM_UNDEFINED
, /* 17c */
203 TPM_UNDEFINED
, /* 17d */
204 TPM_UNDEFINED
, /* 17e */
205 TPM_UNDEFINED
, /* 17f */
206 TPM_UNDEFINED
, /* 180 */
207 TPM_UNDEFINED
, /* 181 */
208 TPM_MEDIUM
, /* 182 */
209 TPM_UNDEFINED
, /* 183 */
210 TPM_UNDEFINED
, /* 184 */
211 TPM_MEDIUM
, /* 185 */
212 TPM_MEDIUM
, /* 186 */
213 TPM_UNDEFINED
, /* 187 */
214 TPM_UNDEFINED
, /* 188 */
215 TPM_UNDEFINED
, /* 189 */
216 TPM_UNDEFINED
, /* 18a */
217 TPM_UNDEFINED
, /* 18b */
218 TPM_UNDEFINED
, /* 18c */
219 TPM_UNDEFINED
, /* 18d */
220 TPM_UNDEFINED
, /* 18e */
221 TPM_UNDEFINED
/* 18f */
224 #define TPM2_PCR_READ_IN_SIZE \
225 (sizeof(struct tpm_input_header) + \
226 sizeof(struct tpm2_pcr_read_in))
228 static const struct tpm_input_header tpm2_pcrread_header
= {
229 .tag
= cpu_to_be16(TPM2_ST_NO_SESSIONS
),
230 .length
= cpu_to_be32(TPM2_PCR_READ_IN_SIZE
),
231 .ordinal
= cpu_to_be32(TPM2_CC_PCR_READ
)
235 * tpm2_pcr_read() - read a PCR value
236 * @chip: TPM chip to use.
237 * @pcr_idx: index of the PCR to read.
238 * @ref_buf: buffer to store the resulting hash,
240 * 0 is returned when the operation is successful. If a negative number is
241 * returned it remarks a POSIX error code. If a positive number is returned
242 * it remarks a TPM error.
244 int tpm2_pcr_read(struct tpm_chip
*chip
, int pcr_idx
, u8
*res_buf
)
250 if (pcr_idx
>= TPM2_PLATFORM_PCR
)
253 cmd
.header
.in
= tpm2_pcrread_header
;
254 cmd
.params
.pcrread_in
.pcr_selects_cnt
= cpu_to_be32(1);
255 cmd
.params
.pcrread_in
.hash_alg
= cpu_to_be16(TPM2_ALG_SHA1
);
256 cmd
.params
.pcrread_in
.pcr_select_size
= TPM2_PCR_SELECT_MIN
;
258 memset(cmd
.params
.pcrread_in
.pcr_select
, 0,
259 sizeof(cmd
.params
.pcrread_in
.pcr_select
));
260 cmd
.params
.pcrread_in
.pcr_select
[pcr_idx
>> 3] = 1 << (pcr_idx
& 0x7);
262 rc
= tpm_transmit_cmd(chip
, &cmd
, sizeof(cmd
),
263 "attempting to read a pcr value");
265 buf
= cmd
.params
.pcrread_out
.digest
;
266 memcpy(res_buf
, buf
, TPM_DIGEST_SIZE
);
272 #define TPM2_GET_PCREXTEND_IN_SIZE \
273 (sizeof(struct tpm_input_header) + \
274 sizeof(struct tpm2_pcr_extend_in))
276 static const struct tpm_input_header tpm2_pcrextend_header
= {
277 .tag
= cpu_to_be16(TPM2_ST_SESSIONS
),
278 .length
= cpu_to_be32(TPM2_GET_PCREXTEND_IN_SIZE
),
279 .ordinal
= cpu_to_be32(TPM2_CC_PCR_EXTEND
)
283 * tpm2_pcr_extend() - extend a PCR value
284 * @chip: TPM chip to use.
285 * @pcr_idx: index of the PCR.
286 * @hash: hash value to use for the extend operation.
288 * 0 is returned when the operation is successful. If a negative number is
289 * returned it remarks a POSIX error code. If a positive number is returned
290 * it remarks a TPM error.
292 int tpm2_pcr_extend(struct tpm_chip
*chip
, int pcr_idx
, const u8
*hash
)
297 cmd
.header
.in
= tpm2_pcrextend_header
;
298 cmd
.params
.pcrextend_in
.pcr_idx
= cpu_to_be32(pcr_idx
);
299 cmd
.params
.pcrextend_in
.auth_area_size
=
300 cpu_to_be32(sizeof(struct tpm2_null_auth_area
));
301 cmd
.params
.pcrextend_in
.auth_area
.handle
=
302 cpu_to_be32(TPM2_RS_PW
);
303 cmd
.params
.pcrextend_in
.auth_area
.nonce_size
= 0;
304 cmd
.params
.pcrextend_in
.auth_area
.attributes
= 0;
305 cmd
.params
.pcrextend_in
.auth_area
.auth_size
= 0;
306 cmd
.params
.pcrextend_in
.digest_cnt
= cpu_to_be32(1);
307 cmd
.params
.pcrextend_in
.hash_alg
= cpu_to_be16(TPM2_ALG_SHA1
);
308 memcpy(cmd
.params
.pcrextend_in
.digest
, hash
, TPM_DIGEST_SIZE
);
310 rc
= tpm_transmit_cmd(chip
, &cmd
, sizeof(cmd
),
311 "attempting extend a PCR value");
316 #define TPM2_GETRANDOM_IN_SIZE \
317 (sizeof(struct tpm_input_header) + \
318 sizeof(struct tpm2_get_random_in))
320 static const struct tpm_input_header tpm2_getrandom_header
= {
321 .tag
= cpu_to_be16(TPM2_ST_NO_SESSIONS
),
322 .length
= cpu_to_be32(TPM2_GETRANDOM_IN_SIZE
),
323 .ordinal
= cpu_to_be32(TPM2_CC_GET_RANDOM
)
327 * tpm2_get_random() - get random bytes from the TPM RNG
328 * @chip: TPM chip to use
329 * @out: destination buffer for the random bytes
330 * @max: the max number of bytes to write to @out
332 * 0 is returned when the operation is successful. If a negative number is
333 * returned it remarks a POSIX error code. If a positive number is returned
334 * it remarks a TPM error.
336 int tpm2_get_random(struct tpm_chip
*chip
, u8
*out
, size_t max
)
346 num_bytes
= min_t(u32
, max
, sizeof(cmd
.params
.getrandom_out
.buffer
));
348 if (!out
|| !num_bytes
||
349 max
> sizeof(cmd
.params
.getrandom_out
.buffer
))
353 cmd
.header
.in
= tpm2_getrandom_header
;
354 cmd
.params
.getrandom_in
.size
= cpu_to_be16(num_bytes
);
356 err
= tpm_transmit_cmd(chip
, &cmd
, sizeof(cmd
),
357 "attempting get random");
361 recd
= min_t(u32
, be16_to_cpu(cmd
.params
.getrandom_out
.size
),
363 memcpy(dest
, cmd
.params
.getrandom_out
.buffer
, recd
);
368 } while (retries
-- && total
< max
);
370 return total
? total
: -EIO
;
373 #define TPM2_GET_TPM_PT_IN_SIZE \
374 (sizeof(struct tpm_input_header) + \
375 sizeof(struct tpm2_get_tpm_pt_in))
377 static const struct tpm_input_header tpm2_get_tpm_pt_header
= {
378 .tag
= cpu_to_be16(TPM2_ST_NO_SESSIONS
),
379 .length
= cpu_to_be32(TPM2_GET_TPM_PT_IN_SIZE
),
380 .ordinal
= cpu_to_be32(TPM2_CC_GET_CAPABILITY
)
384 * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property
385 * @chip: TPM chip to use.
386 * @property_id: property ID.
387 * @value: output variable.
388 * @desc: passed to tpm_transmit_cmd()
390 * 0 is returned when the operation is successful. If a negative number is
391 * returned it remarks a POSIX error code. If a positive number is returned
392 * it remarks a TPM error.
394 ssize_t
tpm2_get_tpm_pt(struct tpm_chip
*chip
, u32 property_id
, u32
*value
,
400 cmd
.header
.in
= tpm2_get_tpm_pt_header
;
401 cmd
.params
.get_tpm_pt_in
.cap_id
= cpu_to_be32(TPM2_CAP_TPM_PROPERTIES
);
402 cmd
.params
.get_tpm_pt_in
.property_id
= cpu_to_be32(property_id
);
403 cmd
.params
.get_tpm_pt_in
.property_cnt
= cpu_to_be32(1);
405 rc
= tpm_transmit_cmd(chip
, &cmd
, sizeof(cmd
), desc
);
407 *value
= cmd
.params
.get_tpm_pt_out
.value
;
412 #define TPM2_STARTUP_IN_SIZE \
413 (sizeof(struct tpm_input_header) + \
414 sizeof(struct tpm2_startup_in))
416 static const struct tpm_input_header tpm2_startup_header
= {
417 .tag
= cpu_to_be16(TPM2_ST_NO_SESSIONS
),
418 .length
= cpu_to_be32(TPM2_STARTUP_IN_SIZE
),
419 .ordinal
= cpu_to_be32(TPM2_CC_STARTUP
)
423 * tpm2_startup() - send startup command to the TPM chip
424 * @chip: TPM chip to use.
425 * @startup_type startup type. The value is either
426 * TPM_SU_CLEAR or TPM_SU_STATE.
428 * 0 is returned when the operation is successful. If a negative number is
429 * returned it remarks a POSIX error code. If a positive number is returned
430 * it remarks a TPM error.
432 int tpm2_startup(struct tpm_chip
*chip
, u16 startup_type
)
436 cmd
.header
.in
= tpm2_startup_header
;
438 cmd
.params
.startup_in
.startup_type
= cpu_to_be16(startup_type
);
439 return tpm_transmit_cmd(chip
, &cmd
, sizeof(cmd
),
440 "attempting to start the TPM");
442 EXPORT_SYMBOL_GPL(tpm2_startup
);
444 #define TPM2_SHUTDOWN_IN_SIZE \
445 (sizeof(struct tpm_input_header) + \
446 sizeof(struct tpm2_startup_in))
448 static const struct tpm_input_header tpm2_shutdown_header
= {
449 .tag
= cpu_to_be16(TPM2_ST_NO_SESSIONS
),
450 .length
= cpu_to_be32(TPM2_SHUTDOWN_IN_SIZE
),
451 .ordinal
= cpu_to_be32(TPM2_CC_SHUTDOWN
)
455 * tpm2_shutdown() - send shutdown command to the TPM chip
456 * @chip: TPM chip to use.
457 * @shutdown_type shutdown type. The value is either
458 * TPM_SU_CLEAR or TPM_SU_STATE.
460 * 0 is returned when the operation is successful. If a negative number is
461 * returned it remarks a POSIX error code. If a positive number is returned
462 * it remarks a TPM error.
464 int tpm2_shutdown(struct tpm_chip
*chip
, u16 shutdown_type
)
468 cmd
.header
.in
= tpm2_shutdown_header
;
470 cmd
.params
.startup_in
.startup_type
= cpu_to_be16(shutdown_type
);
471 return tpm_transmit_cmd(chip
, &cmd
, sizeof(cmd
),
474 EXPORT_SYMBOL_GPL(tpm2_shutdown
);
477 * tpm2_calc_ordinal_duration() - maximum duration for a command
478 * @chip: TPM chip to use.
479 * @ordinal: command code number.
481 * 0 is returned when the operation is successful. If a negative number is
482 * returned it remarks a POSIX error code. If a positive number is returned
483 * it remarks a TPM error.
485 unsigned long tpm2_calc_ordinal_duration(struct tpm_chip
*chip
, u32 ordinal
)
487 int index
= TPM_UNDEFINED
;
490 if (ordinal
>= TPM2_CC_FIRST
&& ordinal
<= TPM2_CC_LAST
)
491 index
= tpm2_ordinal_duration
[ordinal
- TPM2_CC_FIRST
];
493 if (index
!= TPM_UNDEFINED
)
494 duration
= chip
->vendor
.duration
[index
];
497 duration
= 2 * 60 * HZ
;
501 EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration
);
503 #define TPM2_SELF_TEST_IN_SIZE \
504 (sizeof(struct tpm_input_header) + \
505 sizeof(struct tpm2_self_test_in))
507 static const struct tpm_input_header tpm2_selftest_header
= {
508 .tag
= cpu_to_be16(TPM2_ST_NO_SESSIONS
),
509 .length
= cpu_to_be32(TPM2_SELF_TEST_IN_SIZE
),
510 .ordinal
= cpu_to_be32(TPM2_CC_SELF_TEST
)
514 * tpm2_continue_selftest() - start a self test
515 * @chip: TPM chip to use
516 * @full: test all commands instead of testing only those that were not
519 * 0 is returned when the operation is successful. If a negative number is
520 * returned it remarks a POSIX error code. If a positive number is returned
521 * it remarks a TPM error.
523 static int tpm2_start_selftest(struct tpm_chip
*chip
, bool full
)
528 cmd
.header
.in
= tpm2_selftest_header
;
529 cmd
.params
.selftest_in
.full_test
= full
;
531 rc
= tpm_transmit_cmd(chip
, &cmd
, TPM2_SELF_TEST_IN_SIZE
,
532 "continue selftest");
534 /* At least some prototype chips seem to give RC_TESTING error
535 * immediately. This is a workaround for that.
537 if (rc
== TPM2_RC_TESTING
) {
538 dev_warn(chip
->pdev
, "Got RC_TESTING, ignoring\n");
546 * tpm2_do_selftest() - run a full self test
547 * @chip: TPM chip to use
549 * During the self test TPM2 commands return with the error code RC_TESTING.
550 * Waiting is done by issuing PCR read until it executes successfully.
552 * 0 is returned when the operation is successful. If a negative number is
553 * returned it remarks a POSIX error code. If a positive number is returned
554 * it remarks a TPM error.
556 int tpm2_do_selftest(struct tpm_chip
*chip
)
560 unsigned int delay_msec
= 100;
561 unsigned long duration
;
565 duration
= tpm2_calc_ordinal_duration(chip
, TPM2_CC_SELF_TEST
);
567 loops
= jiffies_to_msecs(duration
) / delay_msec
;
569 rc
= tpm2_start_selftest(chip
, true);
573 for (i
= 0; i
< loops
; i
++) {
574 /* Attempt to read a PCR value */
575 cmd
.header
.in
= tpm2_pcrread_header
;
576 cmd
.params
.pcrread_in
.pcr_selects_cnt
= cpu_to_be32(1);
577 cmd
.params
.pcrread_in
.hash_alg
= cpu_to_be16(TPM2_ALG_SHA1
);
578 cmd
.params
.pcrread_in
.pcr_select_size
= TPM2_PCR_SELECT_MIN
;
579 cmd
.params
.pcrread_in
.pcr_select
[0] = 0x01;
580 cmd
.params
.pcrread_in
.pcr_select
[1] = 0x00;
581 cmd
.params
.pcrread_in
.pcr_select
[2] = 0x00;
583 rc
= tpm_transmit_cmd(chip
, (u8
*) &cmd
, sizeof(cmd
), NULL
);
587 rc
= be32_to_cpu(cmd
.header
.out
.return_code
);
588 if (rc
!= TPM2_RC_TESTING
)
596 EXPORT_SYMBOL_GPL(tpm2_do_selftest
);
599 * tpm2_gen_interrupt() - generate an interrupt
600 * @chip: TPM chip to use
601 * @quiet: surpress the error message
603 * 0 is returned when the operation is successful. If a negative number is
604 * returned it remarks a POSIX error code. If a positive number is returned
605 * it remarks a TPM error.
607 int tpm2_gen_interrupt(struct tpm_chip
*chip
, bool quiet
)
609 const char *desc
= NULL
;
613 desc
= "attempting to generate an interrupt";
615 return tpm2_get_tpm_pt(chip
, TPM2_CAP_TPM_PROPERTIES
, &dummy
, desc
);
617 EXPORT_SYMBOL_GPL(tpm2_gen_interrupt
);