blob: d26b439976bc9d70803a6f0d6613f1e5c1221b7c [file] [log] [blame]
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -08001/*
Jarkko Sakkinen954650e2015-05-30 08:09:04 +03002 * Copyright (C) 2014, 2015 Intel Corporation
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -08003 *
4 * Authors:
5 * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
6 *
7 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
8 *
9 * This file contains TPM2 protocol implementations of the commands
10 * used by the kernel internally.
11 *
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
15 * of the License.
16 */
17
18#include "tpm.h"
Jarkko Sakkinen5ca4c202015-11-05 21:43:06 +020019#include <crypto/hash_info.h>
Jarkko Sakkinen954650e2015-05-30 08:09:04 +030020#include <keys/trusted-type.h>
21
22enum tpm2_object_attributes {
Jarkko Sakkinenc0b5eed2016-02-13 11:51:23 +020023 TPM2_OA_USER_WITH_AUTH = BIT(6),
24};
25
26enum tpm2_session_attributes {
27 TPM2_SA_CONTINUE_SESSION = BIT(0),
Jarkko Sakkinen954650e2015-05-30 08:09:04 +030028};
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -080029
Jarkko Sakkinen5ca4c202015-11-05 21:43:06 +020030struct tpm2_hash {
31 unsigned int crypto_id;
32 unsigned int tpm_id;
33};
34
35static struct tpm2_hash tpm2_hash_map[] = {
36 {HASH_ALGO_SHA1, TPM2_ALG_SHA1},
37 {HASH_ALGO_SHA256, TPM2_ALG_SHA256},
38 {HASH_ALGO_SHA384, TPM2_ALG_SHA384},
39 {HASH_ALGO_SHA512, TPM2_ALG_SHA512},
40 {HASH_ALGO_SM3_256, TPM2_ALG_SM3_256},
41};
42
Tomas Winkler899102b2018-10-19 21:22:48 +030043/**
44 * tpm2_ordinal_duration_index() - returns an index to the chip duration table
45 * @ordinal: TPM command ordinal.
46 *
47 * The function returns an index to the chip duration table
48 * (enum tpm_duration), that describes the maximum amount of
49 * time the chip could take to return the result for a particular ordinal.
50 *
51 * The values of the MEDIUM, and LONG durations are taken
52 * from the PC Client Profile (PTP) specification (750, 2000 msec)
53 *
54 * LONG_LONG is for commands that generates keys which empirically takes
55 * a longer time on some systems.
56 *
57 * Return:
58 * * TPM_MEDIUM
59 * * TPM_LONG
60 * * TPM_LONG_LONG
61 * * TPM_UNDEFINED
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -080062 */
Tomas Winkler899102b2018-10-19 21:22:48 +030063static u8 tpm2_ordinal_duration_index(u32 ordinal)
64{
65 switch (ordinal) {
66 /* Startup */
67 case TPM2_CC_STARTUP: /* 144 */
68 return TPM_MEDIUM;
69
70 case TPM2_CC_SELF_TEST: /* 143 */
71 return TPM_LONG;
72
73 case TPM2_CC_GET_RANDOM: /* 17B */
74 return TPM_LONG;
75
76 case TPM2_CC_SEQUENCE_UPDATE: /* 15C */
77 return TPM_MEDIUM;
78 case TPM2_CC_SEQUENCE_COMPLETE: /* 13E */
79 return TPM_MEDIUM;
80 case TPM2_CC_EVENT_SEQUENCE_COMPLETE: /* 185 */
81 return TPM_MEDIUM;
82 case TPM2_CC_HASH_SEQUENCE_START: /* 186 */
83 return TPM_MEDIUM;
84
85 case TPM2_CC_VERIFY_SIGNATURE: /* 177 */
86 return TPM_LONG;
87
88 case TPM2_CC_PCR_EXTEND: /* 182 */
89 return TPM_MEDIUM;
90
91 case TPM2_CC_HIERARCHY_CONTROL: /* 121 */
92 return TPM_LONG;
93 case TPM2_CC_HIERARCHY_CHANGE_AUTH: /* 129 */
94 return TPM_LONG;
95
96 case TPM2_CC_GET_CAPABILITY: /* 17A */
97 return TPM_MEDIUM;
98
99 case TPM2_CC_NV_READ: /* 14E */
100 return TPM_LONG;
101
102 case TPM2_CC_CREATE_PRIMARY: /* 131 */
103 return TPM_LONG_LONG;
104 case TPM2_CC_CREATE: /* 153 */
105 return TPM_LONG_LONG;
106 case TPM2_CC_CREATE_LOADED: /* 191 */
107 return TPM_LONG_LONG;
108
109 default:
110 return TPM_UNDEFINED;
111 }
112}
113
114/**
115 * tpm2_calc_ordinal_duration() - calculate the maximum command duration
116 * @chip: TPM chip to use.
117 * @ordinal: TPM command ordinal.
118 *
119 * The function returns the maximum amount of time the chip could take
120 * to return the result for a particular ordinal in jiffies.
121 *
122 * Return: A maximal duration time for an ordinal in jiffies.
123 */
124unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
125{
126 unsigned int index;
127
128 index = tpm2_ordinal_duration_index(ordinal);
129
130 if (index != TPM_UNDEFINED)
131 return chip->duration[index];
132 else
133 return msecs_to_jiffies(TPM2_DURATION_DEFAULT);
134}
135EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration);
136
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800137
Roberto Sassu91f7f3d2017-06-23 15:41:56 +0200138struct tpm2_pcr_read_out {
139 __be32 update_cnt;
140 __be32 pcr_selects_cnt;
141 __be16 hash_alg;
142 u8 pcr_select_size;
143 u8 pcr_select[TPM2_PCR_SELECT_MIN];
144 __be32 digests_cnt;
145 __be16 digest_size;
146 u8 digest[];
147} __packed;
148
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800149/**
150 * tpm2_pcr_read() - read a PCR value
151 * @chip: TPM chip to use.
152 * @pcr_idx: index of the PCR to read.
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200153 * @res_buf: buffer to store the resulting hash.
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800154 *
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200155 * Return: Same as with tpm_transmit_cmd.
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800156 */
157int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
158{
159 int rc;
Roberto Sassu91f7f3d2017-06-23 15:41:56 +0200160 struct tpm_buf buf;
161 struct tpm2_pcr_read_out *out;
162 u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0};
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800163
164 if (pcr_idx >= TPM2_PLATFORM_PCR)
165 return -EINVAL;
166
Roberto Sassu91f7f3d2017-06-23 15:41:56 +0200167 rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ);
168 if (rc)
169 return rc;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800170
Roberto Sassu91f7f3d2017-06-23 15:41:56 +0200171 pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800172
Roberto Sassu91f7f3d2017-06-23 15:41:56 +0200173 tpm_buf_append_u32(&buf, 1);
174 tpm_buf_append_u16(&buf, TPM2_ALG_SHA1);
175 tpm_buf_append_u8(&buf, TPM2_PCR_SELECT_MIN);
176 tpm_buf_append(&buf, (const unsigned char *)pcr_select,
177 sizeof(pcr_select));
178
179 rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
180 res_buf ? "attempting to read a pcr value" : NULL);
181 if (rc == 0 && res_buf) {
182 out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE];
183 memcpy(res_buf, out->digest, SHA1_DIGEST_SIZE);
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800184 }
185
Roberto Sassu91f7f3d2017-06-23 15:41:56 +0200186 tpm_buf_destroy(&buf);
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800187 return rc;
188}
189
Nayna Jainc1f92b42017-01-30 04:59:41 -0500190struct tpm2_null_auth_area {
191 __be32 handle;
192 __be16 nonce_size;
193 u8 attributes;
194 __be16 auth_size;
195} __packed;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800196
197/**
198 * tpm2_pcr_extend() - extend a PCR value
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200199 *
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800200 * @chip: TPM chip to use.
201 * @pcr_idx: index of the PCR.
Nayna Jainc1f92b42017-01-30 04:59:41 -0500202 * @count: number of digests passed.
203 * @digests: list of pcr banks and corresponding digest values to extend.
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800204 *
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200205 * Return: Same as with tpm_transmit_cmd.
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800206 */
Nayna Jainc1f92b42017-01-30 04:59:41 -0500207int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,
208 struct tpm2_digest *digests)
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800209{
Nayna Jainc1f92b42017-01-30 04:59:41 -0500210 struct tpm_buf buf;
211 struct tpm2_null_auth_area auth_area;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800212 int rc;
Nayna Jainc1f92b42017-01-30 04:59:41 -0500213 int i;
214 int j;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800215
Nayna Jainc1f92b42017-01-30 04:59:41 -0500216 if (count > ARRAY_SIZE(chip->active_banks))
217 return -EINVAL;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800218
Nayna Jainc1f92b42017-01-30 04:59:41 -0500219 rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND);
220 if (rc)
221 return rc;
222
223 tpm_buf_append_u32(&buf, pcr_idx);
224
225 auth_area.handle = cpu_to_be32(TPM2_RS_PW);
226 auth_area.nonce_size = 0;
227 auth_area.attributes = 0;
228 auth_area.auth_size = 0;
229
230 tpm_buf_append_u32(&buf, sizeof(struct tpm2_null_auth_area));
231 tpm_buf_append(&buf, (const unsigned char *)&auth_area,
232 sizeof(auth_area));
233 tpm_buf_append_u32(&buf, count);
234
235 for (i = 0; i < count; i++) {
236 for (j = 0; j < ARRAY_SIZE(tpm2_hash_map); j++) {
237 if (digests[i].alg_id != tpm2_hash_map[j].tpm_id)
238 continue;
239 tpm_buf_append_u16(&buf, digests[i].alg_id);
240 tpm_buf_append(&buf, (const unsigned char
241 *)&digests[i].digest,
242 hash_digest_size[tpm2_hash_map[j].crypto_id]);
243 }
244 }
245
Jarkko Sakkinen745b3612017-01-06 14:03:45 +0200246 rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800247 "attempting extend a PCR value");
248
Nayna Jainc1f92b42017-01-30 04:59:41 -0500249 tpm_buf_destroy(&buf);
250
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800251 return rc;
252}
253
Nayna Jainc1f92b42017-01-30 04:59:41 -0500254
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300255struct tpm2_get_random_out {
256 __be16 size;
257 u8 buffer[TPM_MAX_RNG_DATA];
258} __packed;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800259
260/**
261 * tpm2_get_random() - get random bytes from the TPM RNG
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200262 *
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300263 * @chip: a &tpm_chip instance
264 * @dest: destination buffer
265 * @max: the max number of random bytes to pull
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800266 *
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200267 * Return:
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300268 * size of the buffer on success,
269 * -errno otherwise
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800270 */
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300271int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800272{
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300273 struct tpm2_get_random_out *out;
274 struct tpm_buf buf;
275 u32 recd;
276 u32 num_bytes = max;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800277 int err;
278 int total = 0;
279 int retries = 5;
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300280 u8 *dest_ptr = dest;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800281
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300282 if (!num_bytes || max > TPM_MAX_RNG_DATA)
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800283 return -EINVAL;
284
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300285 err = tpm_buf_init(&buf, 0, 0);
286 if (err)
287 return err;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800288
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300289 do {
290 tpm_buf_reset(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_RANDOM);
291 tpm_buf_append_u16(&buf, num_bytes);
292 err = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
Stefan Bergerc659af72017-01-19 07:19:12 -0500293 offsetof(struct tpm2_get_random_out,
294 buffer),
295 0, "attempting get random");
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800296 if (err)
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300297 goto out;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800298
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300299 out = (struct tpm2_get_random_out *)
300 &buf.data[TPM_HEADER_SIZE];
301 recd = min_t(u32, be16_to_cpu(out->size), num_bytes);
302 if (tpm_buf_length(&buf) <
Jarkko Sakkinen84b59f62018-09-03 04:01:26 +0300303 TPM_HEADER_SIZE +
304 offsetof(struct tpm2_get_random_out, buffer) +
305 recd) {
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300306 err = -EFAULT;
307 goto out;
308 }
309 memcpy(dest_ptr, out->buffer, recd);
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800310
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300311 dest_ptr += recd;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800312 total += recd;
313 num_bytes -= recd;
314 } while (retries-- && total < max);
315
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300316 tpm_buf_destroy(&buf);
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800317 return total ? total : -EIO;
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300318out:
319 tpm_buf_destroy(&buf);
320 return err;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800321}
322
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800323/**
Jarkko Sakkinen9aa36b32016-11-26 13:39:35 +0200324 * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command
325 * @chip: TPM chip to use
326 * @payload: the key data in clear and encrypted form
327 * @options: authentication values and other options
328 *
329 * Return: same as with tpm_transmit_cmd
330 */
331void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
332 unsigned int flags)
333{
334 struct tpm_buf buf;
335 int rc;
336
337 rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
338 if (rc) {
339 dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n",
340 handle);
341 return;
342 }
343
344 tpm_buf_append_u32(&buf, handle);
345
Jarkko Sakkinen745b3612017-01-06 14:03:45 +0200346 (void) tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, flags,
Jarkko Sakkinen9aa36b32016-11-26 13:39:35 +0200347 "flushing context");
348
349 tpm_buf_destroy(&buf);
350}
351
352/**
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200353 * tpm_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer.
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300354 *
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200355 * @buf: an allocated tpm_buf instance
356 * @session_handle: session handle
357 * @nonce: the session nonce, may be NULL if not used
358 * @nonce_len: the session nonce length, may be 0 if not used
359 * @attributes: the session attributes
360 * @hmac: the session HMAC or password, may be NULL if not used
361 * @hmac_len: the session HMAC or password length, maybe 0 if not used
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300362 */
363static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle,
364 const u8 *nonce, u16 nonce_len,
365 u8 attributes,
366 const u8 *hmac, u16 hmac_len)
367{
368 tpm_buf_append_u32(buf, 9 + nonce_len + hmac_len);
369 tpm_buf_append_u32(buf, session_handle);
370 tpm_buf_append_u16(buf, nonce_len);
371
372 if (nonce && nonce_len)
373 tpm_buf_append(buf, nonce, nonce_len);
374
375 tpm_buf_append_u8(buf, attributes);
376 tpm_buf_append_u16(buf, hmac_len);
377
378 if (hmac && hmac_len)
379 tpm_buf_append(buf, hmac, hmac_len);
380}
381
382/**
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300383 * tpm2_seal_trusted() - seal the payload of a trusted key
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200384 *
385 * @chip: TPM chip to use
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300386 * @payload: the key data in clear and encrypted form
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300387 * @options: authentication values and other options
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300388 *
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300389 * Return: < 0 on error and 0 on success.
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300390 */
391int tpm2_seal_trusted(struct tpm_chip *chip,
392 struct trusted_key_payload *payload,
393 struct trusted_key_options *options)
394{
395 unsigned int blob_len;
396 struct tpm_buf buf;
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300397 u32 hash;
Jarkko Sakkinen5ca4c202015-11-05 21:43:06 +0200398 int i;
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300399 int rc;
400
Jarkko Sakkinen5ca4c202015-11-05 21:43:06 +0200401 for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
402 if (options->hash == tpm2_hash_map[i].crypto_id) {
403 hash = tpm2_hash_map[i].tpm_id;
404 break;
405 }
406 }
407
408 if (i == ARRAY_SIZE(tpm2_hash_map))
409 return -EINVAL;
410
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300411 rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
412 if (rc)
413 return rc;
414
415 tpm_buf_append_u32(&buf, options->keyhandle);
416 tpm2_buf_append_auth(&buf, TPM2_RS_PW,
417 NULL /* nonce */, 0,
418 0 /* session_attributes */,
419 options->keyauth /* hmac */,
420 TPM_DIGEST_SIZE);
421
422 /* sensitive */
Jarkko Sakkinen2e311252015-10-30 14:57:02 +0200423 tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len + 1);
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300424
425 tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE);
426 tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE);
Jarkko Sakkinen2e311252015-10-30 14:57:02 +0200427 tpm_buf_append_u16(&buf, payload->key_len + 1);
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300428 tpm_buf_append(&buf, payload->key, payload->key_len);
Jarkko Sakkinen2e311252015-10-30 14:57:02 +0200429 tpm_buf_append_u8(&buf, payload->migratable);
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300430
431 /* public */
Jarkko Sakkinenf3c82ad2016-01-06 16:43:30 +0200432 tpm_buf_append_u16(&buf, 14 + options->policydigest_len);
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300433 tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH);
Jarkko Sakkinen5ca4c202015-11-05 21:43:06 +0200434 tpm_buf_append_u16(&buf, hash);
Jarkko Sakkinen5beb0c42015-10-31 17:53:44 +0200435
436 /* policy */
Jarkko Sakkinenf3c82ad2016-01-06 16:43:30 +0200437 if (options->policydigest_len) {
Jarkko Sakkinen5beb0c42015-10-31 17:53:44 +0200438 tpm_buf_append_u32(&buf, 0);
Jarkko Sakkinenf3c82ad2016-01-06 16:43:30 +0200439 tpm_buf_append_u16(&buf, options->policydigest_len);
Jarkko Sakkinen5beb0c42015-10-31 17:53:44 +0200440 tpm_buf_append(&buf, options->policydigest,
Jarkko Sakkinenf3c82ad2016-01-06 16:43:30 +0200441 options->policydigest_len);
Jarkko Sakkinen5beb0c42015-10-31 17:53:44 +0200442 } else {
Jarkko Sakkinenc0b5eed2016-02-13 11:51:23 +0200443 tpm_buf_append_u32(&buf, TPM2_OA_USER_WITH_AUTH);
Jarkko Sakkinen5beb0c42015-10-31 17:53:44 +0200444 tpm_buf_append_u16(&buf, 0);
445 }
446
447 /* public parameters */
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300448 tpm_buf_append_u16(&buf, TPM2_ALG_NULL);
449 tpm_buf_append_u16(&buf, 0);
450
451 /* outside info */
452 tpm_buf_append_u16(&buf, 0);
453
454 /* creation PCR */
455 tpm_buf_append_u32(&buf, 0);
456
457 if (buf.flags & TPM_BUF_OVERFLOW) {
458 rc = -E2BIG;
459 goto out;
460 }
461
Jarkko Sakkinen745b3612017-01-06 14:03:45 +0200462 rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 4, 0,
Stefan Bergerc659af72017-01-19 07:19:12 -0500463 "sealing data");
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300464 if (rc)
465 goto out;
466
467 blob_len = be32_to_cpup((__be32 *) &buf.data[TPM_HEADER_SIZE]);
468 if (blob_len > MAX_BLOB_SIZE) {
469 rc = -E2BIG;
470 goto out;
471 }
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300472 if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 4 + blob_len) {
Stefan Bergerc659af72017-01-19 07:19:12 -0500473 rc = -EFAULT;
474 goto out;
475 }
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300476
477 memcpy(payload->blob, &buf.data[TPM_HEADER_SIZE + 4], blob_len);
478 payload->blob_len = blob_len;
479
480out:
481 tpm_buf_destroy(&buf);
482
Jarkko Sakkinen5ca4c202015-11-05 21:43:06 +0200483 if (rc > 0) {
Jarkko Sakkinen7d761112017-01-25 23:00:22 +0200484 if (tpm2_rc_value(rc) == TPM2_RC_HASH)
Jarkko Sakkinen5ca4c202015-11-05 21:43:06 +0200485 rc = -EINVAL;
486 else
487 rc = -EPERM;
488 }
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300489
490 return rc;
491}
492
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300493/**
494 * tpm2_load_cmd() - execute a TPM2_Load command
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200495 *
496 * @chip: TPM chip to use
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300497 * @payload: the key data in clear and encrypted form
498 * @options: authentication values and other options
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200499 * @blob_handle: returned blob handle
500 * @flags: tpm transmit flags
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300501 *
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200502 * Return: 0 on success.
503 * -E2BIG on wrong payload size.
504 * -EPERM on tpm error status.
505 * < 0 error from tpm_transmit_cmd.
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300506 */
507static int tpm2_load_cmd(struct tpm_chip *chip,
508 struct trusted_key_payload *payload,
509 struct trusted_key_options *options,
510 u32 *blob_handle, unsigned int flags)
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300511{
512 struct tpm_buf buf;
513 unsigned int private_len;
514 unsigned int public_len;
515 unsigned int blob_len;
516 int rc;
517
518 private_len = be16_to_cpup((__be16 *) &payload->blob[0]);
519 if (private_len > (payload->blob_len - 2))
520 return -E2BIG;
521
522 public_len = be16_to_cpup((__be16 *) &payload->blob[2 + private_len]);
523 blob_len = private_len + public_len + 4;
524 if (blob_len > payload->blob_len)
525 return -E2BIG;
526
527 rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
528 if (rc)
529 return rc;
530
531 tpm_buf_append_u32(&buf, options->keyhandle);
532 tpm2_buf_append_auth(&buf, TPM2_RS_PW,
533 NULL /* nonce */, 0,
534 0 /* session_attributes */,
535 options->keyauth /* hmac */,
536 TPM_DIGEST_SIZE);
537
538 tpm_buf_append(&buf, payload->blob, blob_len);
539
540 if (buf.flags & TPM_BUF_OVERFLOW) {
541 rc = -E2BIG;
542 goto out;
543 }
544
Jarkko Sakkinen745b3612017-01-06 14:03:45 +0200545 rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 4, flags,
Stefan Bergerc659af72017-01-19 07:19:12 -0500546 "loading blob");
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300547 if (!rc)
548 *blob_handle = be32_to_cpup(
549 (__be32 *) &buf.data[TPM_HEADER_SIZE]);
550
551out:
552 tpm_buf_destroy(&buf);
553
554 if (rc > 0)
555 rc = -EPERM;
556
557 return rc;
558}
559
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300560/**
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300561 * tpm2_unseal_cmd() - execute a TPM2_Unload command
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200562 *
563 * @chip: TPM chip to use
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300564 * @payload: the key data in clear and encrypted form
565 * @options: authentication values and other options
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200566 * @blob_handle: blob handle
567 * @flags: tpm_transmit_cmd flags
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300568 *
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200569 * Return: 0 on success
570 * -EPERM on tpm error status
571 * < 0 error from tpm_transmit_cmd
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300572 */
573static int tpm2_unseal_cmd(struct tpm_chip *chip,
574 struct trusted_key_payload *payload,
575 struct trusted_key_options *options,
576 u32 blob_handle, unsigned int flags)
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300577{
578 struct tpm_buf buf;
Jarkko Sakkinen2e311252015-10-30 14:57:02 +0200579 u16 data_len;
580 u8 *data;
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300581 int rc;
582
583 rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
584 if (rc)
585 return rc;
586
587 tpm_buf_append_u32(&buf, blob_handle);
Jarkko Sakkinen5beb0c42015-10-31 17:53:44 +0200588 tpm2_buf_append_auth(&buf,
589 options->policyhandle ?
590 options->policyhandle : TPM2_RS_PW,
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300591 NULL /* nonce */, 0,
Jarkko Sakkinenc0b5eed2016-02-13 11:51:23 +0200592 TPM2_SA_CONTINUE_SESSION,
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300593 options->blobauth /* hmac */,
594 TPM_DIGEST_SIZE);
595
Jarkko Sakkinen745b3612017-01-06 14:03:45 +0200596 rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 6, flags,
Stefan Bergerc659af72017-01-19 07:19:12 -0500597 "unsealing");
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300598 if (rc > 0)
599 rc = -EPERM;
600
601 if (!rc) {
Jarkko Sakkinen2e311252015-10-30 14:57:02 +0200602 data_len = be16_to_cpup(
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300603 (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]);
Jeremy Boone3be23272018-02-08 12:28:08 -0800604 if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE + 1) {
605 rc = -EFAULT;
606 goto out;
607 }
Stefan Bergerc659af72017-01-19 07:19:12 -0500608
Jarkko Sakkinence63c052018-03-26 15:14:06 +0300609 if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 6 + data_len) {
Stefan Bergerc659af72017-01-19 07:19:12 -0500610 rc = -EFAULT;
611 goto out;
612 }
Jarkko Sakkinen2e311252015-10-30 14:57:02 +0200613 data = &buf.data[TPM_HEADER_SIZE + 6];
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300614
Jarkko Sakkinen2e311252015-10-30 14:57:02 +0200615 memcpy(payload->key, data, data_len - 1);
616 payload->key_len = data_len - 1;
617 payload->migratable = data[data_len - 1];
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300618 }
619
Stefan Bergerc659af72017-01-19 07:19:12 -0500620out:
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300621 tpm_buf_destroy(&buf);
622 return rc;
623}
624
625/**
Baruch Siachcbef69a2016-11-06 11:02:45 +0200626 * tpm2_unseal_trusted() - unseal the payload of a trusted key
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200627 *
628 * @chip: TPM chip to use
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300629 * @payload: the key data in clear and encrypted form
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300630 * @options: authentication values and other options
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300631 *
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200632 * Return: Same as with tpm_transmit_cmd.
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300633 */
634int tpm2_unseal_trusted(struct tpm_chip *chip,
635 struct trusted_key_payload *payload,
636 struct trusted_key_options *options)
637{
638 u32 blob_handle;
639 int rc;
640
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300641 mutex_lock(&chip->tpm_mutex);
642 rc = tpm2_load_cmd(chip, payload, options, &blob_handle,
643 TPM_TRANSMIT_UNLOCKED);
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300644 if (rc)
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300645 goto out;
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300646
Jarkko Sakkinend4816ed2016-08-16 22:00:38 +0300647 rc = tpm2_unseal_cmd(chip, payload, options, blob_handle,
648 TPM_TRANSMIT_UNLOCKED);
649 tpm2_flush_context_cmd(chip, blob_handle, TPM_TRANSMIT_UNLOCKED);
650out:
651 mutex_unlock(&chip->tpm_mutex);
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300652 return rc;
653}
654
Jarkko Sakkinen2ab32412018-03-26 15:14:05 +0300655struct tpm2_get_cap_out {
656 u8 more_data;
657 __be32 subcap_id;
658 __be32 property_cnt;
659 __be32 property_id;
660 __be32 value;
661} __packed;
662
Jarkko Sakkinen954650e2015-05-30 08:09:04 +0300663/**
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800664 * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property
Jarkko Sakkinen2ab32412018-03-26 15:14:05 +0300665 * @chip: a &tpm_chip instance
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800666 * @property_id: property ID.
667 * @value: output variable.
668 * @desc: passed to tpm_transmit_cmd()
669 *
Jarkko Sakkinen2ab32412018-03-26 15:14:05 +0300670 * Return:
671 * 0 on success,
672 * -errno or a TPM return code otherwise
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800673 */
674ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value,
675 const char *desc)
676{
Jarkko Sakkinen2ab32412018-03-26 15:14:05 +0300677 struct tpm2_get_cap_out *out;
678 struct tpm_buf buf;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800679 int rc;
680
Jarkko Sakkinen2ab32412018-03-26 15:14:05 +0300681 rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
682 if (rc)
683 return rc;
684 tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES);
685 tpm_buf_append_u32(&buf, property_id);
686 tpm_buf_append_u32(&buf, 1);
687 rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, NULL);
688 if (!rc) {
689 out = (struct tpm2_get_cap_out *)
690 &buf.data[TPM_HEADER_SIZE];
691 *value = be32_to_cpu(out->value);
692 }
693 tpm_buf_destroy(&buf);
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800694 return rc;
695}
Jarkko Sakkineneb5854e2016-06-12 16:42:09 +0300696EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt);
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800697
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800698/**
Jarkko Sakkinencc26c6e2018-06-05 22:22:58 +0300699 * tpm2_shutdown() - send a TPM shutdown command
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200700 *
Jarkko Sakkinencc26c6e2018-06-05 22:22:58 +0300701 * Sends a TPM shutdown command. The shutdown command is used in call
702 * sites where the system is going down. If it fails, there is not much
703 * that can be done except print an error message.
704 *
705 * @chip: a &tpm_chip instance
706 * @shutdown_type: TPM_SU_CLEAR or TPM_SU_STATE.
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800707 */
Jarkko Sakkinen74d6b3c2015-01-29 07:43:47 +0200708void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800709{
Jarkko Sakkinencc26c6e2018-06-05 22:22:58 +0300710 struct tpm_buf buf;
Jarkko Sakkinen74d6b3c2015-01-29 07:43:47 +0200711 int rc;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800712
Jarkko Sakkinencc26c6e2018-06-05 22:22:58 +0300713 rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN);
714 if (rc)
715 return;
716 tpm_buf_append_u16(&buf, shutdown_type);
717 tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
718 "stopping the TPM");
719 tpm_buf_destroy(&buf);
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800720}
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800721
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800722/**
Alexander Steffen2482b1b2017-08-31 19:18:56 +0200723 * tpm2_do_selftest() - ensure that all self tests have passed
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200724 *
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800725 * @chip: TPM chip to use
726 *
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200727 * Return: Same as with tpm_transmit_cmd.
728 *
Alexander Steffen125a2212017-08-31 19:18:58 +0200729 * The TPM can either run all self tests synchronously and then return
730 * RC_SUCCESS once all tests were successful. Or it can choose to run the tests
731 * asynchronously and return RC_TESTING immediately while the self tests still
732 * execute in the background. This function handles both cases and waits until
733 * all tests have completed.
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800734 */
Jason Gunthorpecae8b442016-07-12 11:41:49 -0600735static int tpm2_do_selftest(struct tpm_chip *chip)
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800736{
James Bottomley2be8ffe2018-03-22 17:32:20 +0200737 struct tpm_buf buf;
738 int full;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800739 int rc;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800740
James Bottomley2be8ffe2018-03-22 17:32:20 +0200741 for (full = 0; full < 2; full++) {
742 rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST);
743 if (rc)
744 return rc;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800745
James Bottomley2be8ffe2018-03-22 17:32:20 +0200746 tpm_buf_append_u8(&buf, full);
747 rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
748 "attempting the self test");
749 tpm_buf_destroy(&buf);
Alexander Steffen125a2212017-08-31 19:18:58 +0200750
James Bottomley2be8ffe2018-03-22 17:32:20 +0200751 if (rc == TPM2_RC_TESTING)
752 rc = TPM2_RC_SUCCESS;
753 if (rc == TPM2_RC_INITIALIZE || rc == TPM2_RC_SUCCESS)
754 return rc;
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800755 }
756
757 return rc;
758}
Jarkko Sakkinen7a1d7e62014-12-12 11:46:38 -0800759
760/**
Jarkko Sakkinen94e266b2018-03-26 15:14:04 +0300761 * tpm2_probe() - probe for the TPM 2.0 protocol
762 * @chip: a &tpm_chip instance
Jarkko Sakkinen4d5f2052015-02-04 16:21:09 +0200763 *
Jarkko Sakkinen94e266b2018-03-26 15:14:04 +0300764 * Send an idempotent TPM 2.0 command and see whether there is TPM2 chip in the
765 * other end based on the response tag. The flag TPM_CHIP_FLAG_TPM2 is set by
766 * this function if this is the case.
Winkler, Tomas794c6e12016-11-23 12:04:12 +0200767 *
Jarkko Sakkinen94e266b2018-03-26 15:14:04 +0300768 * Return:
769 * 0 on success,
770 * -errno otherwise
Jarkko Sakkinen4d5f2052015-02-04 16:21:09 +0200771 */
772int tpm2_probe(struct tpm_chip *chip)
773{
Jarkko Sakkinen94e266b2018-03-26 15:14:04 +0300774 struct tpm_output_header *out;
775 struct tpm_buf buf;
Jarkko Sakkinen4d5f2052015-02-04 16:21:09 +0200776 int rc;
777
Jarkko Sakkinen94e266b2018-03-26 15:14:04 +0300778 rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
779 if (rc)
Jarkko Sakkinen4d5f2052015-02-04 16:21:09 +0200780 return rc;
Jarkko Sakkinen94e266b2018-03-26 15:14:04 +0300781 tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES);
782 tpm_buf_append_u32(&buf, TPM_PT_TOTAL_COMMANDS);
783 tpm_buf_append_u32(&buf, 1);
784 rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, NULL);
785 /* We ignore TPM return codes on purpose. */
786 if (rc >= 0) {
787 out = (struct tpm_output_header *)buf.data;
788 if (be16_to_cpu(out->tag) == TPM2_ST_NO_SESSIONS)
789 chip->flags |= TPM_CHIP_FLAG_TPM2;
790 }
791 tpm_buf_destroy(&buf);
Jarkko Sakkinen4d5f2052015-02-04 16:21:09 +0200792 return 0;
793}
794EXPORT_SYMBOL_GPL(tpm2_probe);
Jason Gunthorpecae8b442016-07-12 11:41:49 -0600795
Nayna Jain1db15342017-01-30 04:59:40 -0500796struct tpm2_pcr_selection {
797 __be16 hash_alg;
798 u8 size_of_select;
799 u8 pcr_select[3];
800} __packed;
801
Jarkko Sakkinen61841be2017-02-15 20:02:28 +0200802static ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
Nayna Jain1db15342017-01-30 04:59:40 -0500803{
804 struct tpm2_pcr_selection pcr_selection;
805 struct tpm_buf buf;
806 void *marker;
807 void *end;
808 void *pcr_select_offset;
809 unsigned int count;
810 u32 sizeof_pcr_selection;
811 u32 rsp_len;
812 int rc;
813 int i = 0;
814
815 rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
816 if (rc)
817 return rc;
818
819 tpm_buf_append_u32(&buf, TPM2_CAP_PCRS);
820 tpm_buf_append_u32(&buf, 0);
821 tpm_buf_append_u32(&buf, 1);
822
Jarkko Sakkinen745b3612017-01-06 14:03:45 +0200823 rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 9, 0,
Nayna Jain1db15342017-01-30 04:59:40 -0500824 "get tpm pcr allocation");
825 if (rc)
826 goto out;
827
828 count = be32_to_cpup(
829 (__be32 *)&buf.data[TPM_HEADER_SIZE + 5]);
830
831 if (count > ARRAY_SIZE(chip->active_banks)) {
832 rc = -ENODEV;
833 goto out;
834 }
835
836 marker = &buf.data[TPM_HEADER_SIZE + 9];
837
838 rsp_len = be32_to_cpup((__be32 *)&buf.data[2]);
839 end = &buf.data[rsp_len];
840
841 for (i = 0; i < count; i++) {
842 pcr_select_offset = marker +
843 offsetof(struct tpm2_pcr_selection, size_of_select);
844 if (pcr_select_offset >= end) {
845 rc = -EFAULT;
846 break;
847 }
848
849 memcpy(&pcr_selection, marker, sizeof(pcr_selection));
850 chip->active_banks[i] = be16_to_cpu(pcr_selection.hash_alg);
851 sizeof_pcr_selection = sizeof(pcr_selection.hash_alg) +
852 sizeof(pcr_selection.size_of_select) +
853 pcr_selection.size_of_select;
854 marker = marker + sizeof_pcr_selection;
855 }
856
857out:
858 if (i < ARRAY_SIZE(chip->active_banks))
859 chip->active_banks[i] = TPM2_ALG_ERROR;
860
861 tpm_buf_destroy(&buf);
862
863 return rc;
864}
Jarkko Sakkinen61841be2017-02-15 20:02:28 +0200865
Jarkko Sakkinen58472f52016-11-10 20:42:07 -0800866static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
867{
868 struct tpm_buf buf;
869 u32 nr_commands;
Jarkko Sakkinen171360d2017-09-13 09:58:49 -0700870 __be32 *attrs;
Jarkko Sakkinen58472f52016-11-10 20:42:07 -0800871 u32 cc;
872 int i;
873 int rc;
874
875 rc = tpm2_get_tpm_pt(chip, TPM_PT_TOTAL_COMMANDS, &nr_commands, NULL);
876 if (rc)
877 goto out;
878
879 if (nr_commands > 0xFFFFF) {
880 rc = -EFAULT;
881 goto out;
882 }
883
Kees Cooka86854d2018-06-12 14:07:58 -0700884 chip->cc_attrs_tbl = devm_kcalloc(&chip->dev, 4, nr_commands,
Jarkko Sakkinen58472f52016-11-10 20:42:07 -0800885 GFP_KERNEL);
886
887 rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
888 if (rc)
889 goto out;
890
891 tpm_buf_append_u32(&buf, TPM2_CAP_COMMANDS);
892 tpm_buf_append_u32(&buf, TPM2_CC_FIRST);
893 tpm_buf_append_u32(&buf, nr_commands);
894
Jarkko Sakkinen745b3612017-01-06 14:03:45 +0200895 rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
896 9 + 4 * nr_commands, 0, NULL);
Jarkko Sakkinen58472f52016-11-10 20:42:07 -0800897 if (rc) {
898 tpm_buf_destroy(&buf);
899 goto out;
900 }
901
902 if (nr_commands !=
903 be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE + 5])) {
904 tpm_buf_destroy(&buf);
905 goto out;
906 }
907
908 chip->nr_commands = nr_commands;
909
Jarkko Sakkinen171360d2017-09-13 09:58:49 -0700910 attrs = (__be32 *)&buf.data[TPM_HEADER_SIZE + 9];
Jarkko Sakkinen58472f52016-11-10 20:42:07 -0800911 for (i = 0; i < nr_commands; i++, attrs++) {
912 chip->cc_attrs_tbl[i] = be32_to_cpup(attrs);
913 cc = chip->cc_attrs_tbl[i] & 0xFFFF;
914
915 if (cc == TPM2_CC_CONTEXT_SAVE || cc == TPM2_CC_FLUSH_CONTEXT) {
916 chip->cc_attrs_tbl[i] &=
917 ~(GENMASK(2, 0) << TPM2_CC_ATTR_CHANDLES);
918 chip->cc_attrs_tbl[i] |= 1 << TPM2_CC_ATTR_CHANDLES;
919 }
920 }
921
922 tpm_buf_destroy(&buf);
923
924out:
925 if (rc > 0)
926 rc = -ENODEV;
927 return rc;
928}
929
Jarkko Sakkinen61841be2017-02-15 20:02:28 +0200930/**
931 * tpm2_auto_startup - Perform the standard automatic TPM initialization
932 * sequence
933 * @chip: TPM chip to use
934 *
Jarkko Sakkinen58472f52016-11-10 20:42:07 -0800935 * Returns 0 on success, < 0 in case of fatal error.
Jarkko Sakkinen61841be2017-02-15 20:02:28 +0200936 */
937int tpm2_auto_startup(struct tpm_chip *chip)
938{
939 int rc;
940
941 rc = tpm_get_timeouts(chip);
942 if (rc)
943 goto out;
944
945 rc = tpm2_do_selftest(chip);
James Bottomley2be8ffe2018-03-22 17:32:20 +0200946 if (rc && rc != TPM2_RC_INITIALIZE)
Jarkko Sakkinen61841be2017-02-15 20:02:28 +0200947 goto out;
Jarkko Sakkinen61841be2017-02-15 20:02:28 +0200948
949 if (rc == TPM2_RC_INITIALIZE) {
Jarkko Sakkinen19cbe4f2017-06-21 09:31:34 +0200950 rc = tpm_startup(chip);
Jarkko Sakkinen61841be2017-02-15 20:02:28 +0200951 if (rc)
952 goto out;
953
954 rc = tpm2_do_selftest(chip);
James Bottomley2be8ffe2018-03-22 17:32:20 +0200955 if (rc)
Jarkko Sakkinen61841be2017-02-15 20:02:28 +0200956 goto out;
Jarkko Sakkinen61841be2017-02-15 20:02:28 +0200957 }
958
959 rc = tpm2_get_pcr_allocation(chip);
Jarkko Sakkinen58472f52016-11-10 20:42:07 -0800960 if (rc)
961 goto out;
962
963 rc = tpm2_get_cc_attrs_tbl(chip);
Jarkko Sakkinen61841be2017-02-15 20:02:28 +0200964
965out:
966 if (rc > 0)
967 rc = -ENODEV;
968 return rc;
969}
Jarkko Sakkinen58472f52016-11-10 20:42:07 -0800970
971int tpm2_find_cc(struct tpm_chip *chip, u32 cc)
972{
973 int i;
974
975 for (i = 0; i < chip->nr_commands; i++)
976 if (cc == (chip->cc_attrs_tbl[i] & GENMASK(15, 0)))
977 return i;
978
979 return -1;
980}