tpm2-cmd.c 17.9 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
J
Jarkko Sakkinen 已提交
2
/*
J
Jarkko Sakkinen 已提交
3
 * Copyright (C) 2014, 2015 Intel Corporation
J
Jarkko Sakkinen 已提交
4 5 6 7 8 9 10 11 12 13 14
 *
 * Authors:
 * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
 *
 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
 *
 * This file contains TPM2 protocol implementations of the commands
 * used by the kernel internally.
 */

#include "tpm.h"
15 16 17
#include <crypto/hash_info.h>

static struct tpm2_hash tpm2_hash_map[] = {
18 19 20 21 22
	{HASH_ALGO_SHA1, TPM_ALG_SHA1},
	{HASH_ALGO_SHA256, TPM_ALG_SHA256},
	{HASH_ALGO_SHA384, TPM_ALG_SHA384},
	{HASH_ALGO_SHA512, TPM_ALG_SHA512},
	{HASH_ALGO_SM3_256, TPM_ALG_SM3_256},
23 24
};

T
Tomas Winkler 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
int tpm2_get_timeouts(struct tpm_chip *chip)
{
	/* Fixed timeouts for TPM2 */
	chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
	chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B);
	chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C);
	chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D);

	/* PTP spec timeouts */
	chip->duration[TPM_SHORT] = msecs_to_jiffies(TPM2_DURATION_SHORT);
	chip->duration[TPM_MEDIUM] = msecs_to_jiffies(TPM2_DURATION_MEDIUM);
	chip->duration[TPM_LONG] = msecs_to_jiffies(TPM2_DURATION_LONG);

	/* Key creation commands long timeouts */
	chip->duration[TPM_LONG_LONG] =
		msecs_to_jiffies(TPM2_DURATION_LONG_LONG);

	chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS;

	return 0;
}

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
/**
 * tpm2_ordinal_duration_index() - returns an index to the chip duration table
 * @ordinal: TPM command ordinal.
 *
 * The function returns an index to the chip duration table
 * (enum tpm_duration), that describes the maximum amount of
 * time the chip could take to return the result for a  particular ordinal.
 *
 * The values of the MEDIUM, and LONG durations are taken
 * from the PC Client Profile (PTP) specification (750, 2000 msec)
 *
 * LONG_LONG is for commands that generates keys which empirically takes
 * a longer time on some systems.
 *
 * Return:
 * * TPM_MEDIUM
 * * TPM_LONG
 * * TPM_LONG_LONG
 * * TPM_UNDEFINED
J
Jarkko Sakkinen 已提交
66
 */
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
static u8 tpm2_ordinal_duration_index(u32 ordinal)
{
	switch (ordinal) {
	/* Startup */
	case TPM2_CC_STARTUP:                 /* 144 */
		return TPM_MEDIUM;

	case TPM2_CC_SELF_TEST:               /* 143 */
		return TPM_LONG;

	case TPM2_CC_GET_RANDOM:              /* 17B */
		return TPM_LONG;

	case TPM2_CC_SEQUENCE_UPDATE:         /* 15C */
		return TPM_MEDIUM;
	case TPM2_CC_SEQUENCE_COMPLETE:       /* 13E */
		return TPM_MEDIUM;
	case TPM2_CC_EVENT_SEQUENCE_COMPLETE: /* 185 */
		return TPM_MEDIUM;
	case TPM2_CC_HASH_SEQUENCE_START:     /* 186 */
		return TPM_MEDIUM;

	case TPM2_CC_VERIFY_SIGNATURE:        /* 177 */
		return TPM_LONG;

	case TPM2_CC_PCR_EXTEND:              /* 182 */
		return TPM_MEDIUM;

	case TPM2_CC_HIERARCHY_CONTROL:       /* 121 */
		return TPM_LONG;
	case TPM2_CC_HIERARCHY_CHANGE_AUTH:   /* 129 */
		return TPM_LONG;

	case TPM2_CC_GET_CAPABILITY:          /* 17A */
		return TPM_MEDIUM;

	case TPM2_CC_NV_READ:                 /* 14E */
		return TPM_LONG;

	case TPM2_CC_CREATE_PRIMARY:          /* 131 */
		return TPM_LONG_LONG;
	case TPM2_CC_CREATE:                  /* 153 */
		return TPM_LONG_LONG;
	case TPM2_CC_CREATE_LOADED:           /* 191 */
		return TPM_LONG_LONG;

	default:
		return TPM_UNDEFINED;
	}
}

/**
 * tpm2_calc_ordinal_duration() - calculate the maximum command duration
 * @chip:    TPM chip to use.
 * @ordinal: TPM command ordinal.
 *
 * The function returns the maximum amount of time the chip could take
 * to return the result for a particular ordinal in jiffies.
 *
 * Return: A maximal duration time for an ordinal in jiffies.
 */
unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
{
	unsigned int index;

	index = tpm2_ordinal_duration_index(ordinal);

	if (index != TPM_UNDEFINED)
		return chip->duration[index];
	else
		return msecs_to_jiffies(TPM2_DURATION_DEFAULT);
}

J
Jarkko Sakkinen 已提交
140

141 142 143 144 145 146 147 148 149 150 151
struct tpm2_pcr_read_out {
	__be32	update_cnt;
	__be32	pcr_selects_cnt;
	__be16	hash_alg;
	u8	pcr_select_size;
	u8	pcr_select[TPM2_PCR_SELECT_MIN];
	__be32	digests_cnt;
	__be16	digest_size;
	u8	digest[];
} __packed;

J
Jarkko Sakkinen 已提交
152 153 154 155
/**
 * tpm2_pcr_read() - read a PCR value
 * @chip:	TPM chip to use.
 * @pcr_idx:	index of the PCR to read.
156 157
 * @digest:	PCR bank and buffer current PCR value is written to.
 * @digest_size_ptr:	pointer to variable that stores the digest size.
J
Jarkko Sakkinen 已提交
158
 *
W
Winkler, Tomas 已提交
159
 * Return: Same as with tpm_transmit_cmd.
J
Jarkko Sakkinen 已提交
160
 */
161 162
int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
		  struct tpm_digest *digest, u16 *digest_size_ptr)
J
Jarkko Sakkinen 已提交
163
{
164
	int i;
J
Jarkko Sakkinen 已提交
165
	int rc;
166 167 168
	struct tpm_buf buf;
	struct tpm2_pcr_read_out *out;
	u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0};
169 170
	u16 digest_size;
	u16 expected_digest_size = 0;
J
Jarkko Sakkinen 已提交
171 172 173 174

	if (pcr_idx >= TPM2_PLATFORM_PCR)
		return -EINVAL;

175 176 177 178 179 180 181 182 183 184 185
	if (!digest_size_ptr) {
		for (i = 0; i < chip->nr_allocated_banks &&
		     chip->allocated_banks[i].alg_id != digest->alg_id; i++)
			;

		if (i == chip->nr_allocated_banks)
			return -EINVAL;

		expected_digest_size = chip->allocated_banks[i].digest_size;
	}

186 187 188 189 190 191 192
	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ);
	if (rc)
		return rc;

	pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);

	tpm_buf_append_u32(&buf, 1);
193
	tpm_buf_append_u16(&buf, digest->alg_id);
194 195 196 197
	tpm_buf_append_u8(&buf, TPM2_PCR_SELECT_MIN);
	tpm_buf_append(&buf, (const unsigned char *)pcr_select,
		       sizeof(pcr_select));

198 199 200 201 202 203 204 205 206 207
	rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to read a pcr value");
	if (rc)
		goto out;

	out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE];
	digest_size = be16_to_cpu(out->digest_size);
	if (digest_size > sizeof(digest->digest) ||
	    (!digest_size_ptr && digest_size != expected_digest_size)) {
		rc = -EINVAL;
		goto out;
J
Jarkko Sakkinen 已提交
208 209
	}

210 211 212 213 214
	if (digest_size_ptr)
		*digest_size_ptr = digest_size;

	memcpy(digest->digest, out->digest, digest_size);
out:
215
	tpm_buf_destroy(&buf);
J
Jarkko Sakkinen 已提交
216 217 218
	return rc;
}

219 220 221 222 223 224
struct tpm2_null_auth_area {
	__be32  handle;
	__be16  nonce_size;
	u8  attributes;
	__be16  auth_size;
} __packed;
J
Jarkko Sakkinen 已提交
225 226 227

/**
 * tpm2_pcr_extend() - extend a PCR value
W
Winkler, Tomas 已提交
228
 *
J
Jarkko Sakkinen 已提交
229 230
 * @chip:	TPM chip to use.
 * @pcr_idx:	index of the PCR.
231
 * @digests:	list of pcr banks and corresponding digest values to extend.
J
Jarkko Sakkinen 已提交
232
 *
W
Winkler, Tomas 已提交
233
 * Return: Same as with tpm_transmit_cmd.
J
Jarkko Sakkinen 已提交
234
 */
235
int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
236
		    struct tpm_digest *digests)
J
Jarkko Sakkinen 已提交
237
{
238 239
	struct tpm_buf buf;
	struct tpm2_null_auth_area auth_area;
J
Jarkko Sakkinen 已提交
240
	int rc;
241
	int i;
J
Jarkko Sakkinen 已提交
242

243 244 245 246 247 248 249 250 251 252 253 254 255 256
	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND);
	if (rc)
		return rc;

	tpm_buf_append_u32(&buf, pcr_idx);

	auth_area.handle = cpu_to_be32(TPM2_RS_PW);
	auth_area.nonce_size = 0;
	auth_area.attributes = 0;
	auth_area.auth_size = 0;

	tpm_buf_append_u32(&buf, sizeof(struct tpm2_null_auth_area));
	tpm_buf_append(&buf, (const unsigned char *)&auth_area,
		       sizeof(auth_area));
257
	tpm_buf_append_u32(&buf, chip->nr_allocated_banks);
258

259
	for (i = 0; i < chip->nr_allocated_banks; i++) {
260 261 262
		tpm_buf_append_u16(&buf, digests[i].alg_id);
		tpm_buf_append(&buf, (const unsigned char *)&digests[i].digest,
			       chip->allocated_banks[i].digest_size);
263 264
	}

265
	rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value");
J
Jarkko Sakkinen 已提交
266

267 268
	tpm_buf_destroy(&buf);

J
Jarkko Sakkinen 已提交
269 270 271
	return rc;
}

272 273 274 275
struct tpm2_get_random_out {
	__be16 size;
	u8 buffer[TPM_MAX_RNG_DATA];
} __packed;
J
Jarkko Sakkinen 已提交
276 277 278

/**
 * tpm2_get_random() - get random bytes from the TPM RNG
W
Winkler, Tomas 已提交
279
 *
280 281 282
 * @chip:	a &tpm_chip instance
 * @dest:	destination buffer
 * @max:	the max number of random bytes to pull
J
Jarkko Sakkinen 已提交
283
 *
W
Winkler, Tomas 已提交
284
 * Return:
285
 *   size of the buffer on success,
286
 *   -errno otherwise (positive TPM return codes are masked to -EIO)
J
Jarkko Sakkinen 已提交
287
 */
288
int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
J
Jarkko Sakkinen 已提交
289
{
290 291 292 293
	struct tpm2_get_random_out *out;
	struct tpm_buf buf;
	u32 recd;
	u32 num_bytes = max;
J
Jarkko Sakkinen 已提交
294 295 296
	int err;
	int total = 0;
	int retries = 5;
297
	u8 *dest_ptr = dest;
J
Jarkko Sakkinen 已提交
298

299
	if (!num_bytes || max > TPM_MAX_RNG_DATA)
J
Jarkko Sakkinen 已提交
300 301
		return -EINVAL;

302 303 304
	err = tpm_buf_init(&buf, 0, 0);
	if (err)
		return err;
J
Jarkko Sakkinen 已提交
305

306 307 308
	do {
		tpm_buf_reset(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_RANDOM);
		tpm_buf_append_u16(&buf, num_bytes);
309
		err = tpm_transmit_cmd(chip, &buf,
310 311
				       offsetof(struct tpm2_get_random_out,
						buffer),
312
				       "attempting get random");
313 314 315
		if (err) {
			if (err > 0)
				err = -EIO;
316
			goto out;
317
		}
J
Jarkko Sakkinen 已提交
318

319 320 321 322
		out = (struct tpm2_get_random_out *)
			&buf.data[TPM_HEADER_SIZE];
		recd = min_t(u32, be16_to_cpu(out->size), num_bytes);
		if (tpm_buf_length(&buf) <
323 324 325
		    TPM_HEADER_SIZE +
		    offsetof(struct tpm2_get_random_out, buffer) +
		    recd) {
326 327 328 329
			err = -EFAULT;
			goto out;
		}
		memcpy(dest_ptr, out->buffer, recd);
J
Jarkko Sakkinen 已提交
330

331
		dest_ptr += recd;
J
Jarkko Sakkinen 已提交
332 333 334 335
		total += recd;
		num_bytes -= recd;
	} while (retries-- && total < max);

336
	tpm_buf_destroy(&buf);
J
Jarkko Sakkinen 已提交
337
	return total ? total : -EIO;
338 339 340
out:
	tpm_buf_destroy(&buf);
	return err;
J
Jarkko Sakkinen 已提交
341 342
}

343
/**
344
 * tpm2_flush_context() - execute a TPM2_FlushContext command
345 346
 * @chip:	TPM chip to use
 * @handle:	context handle
347
 */
348
void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
349 350 351 352 353 354 355 356 357 358 359 360 361
{
	struct tpm_buf buf;
	int rc;

	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
	if (rc) {
		dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n",
			 handle);
		return;
	}

	tpm_buf_append_u32(&buf, handle);

362
	tpm_transmit_cmd(chip, &buf, 0, "flushing context");
363 364
	tpm_buf_destroy(&buf);
}
365
EXPORT_SYMBOL_GPL(tpm2_flush_context);
366

367 368 369 370 371 372 373 374
struct tpm2_get_cap_out {
	u8 more_data;
	__be32 subcap_id;
	__be32 property_cnt;
	__be32 property_id;
	__be32 value;
} __packed;

J
Jarkko Sakkinen 已提交
375 376
/**
 * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property
377
 * @chip:		a &tpm_chip instance
J
Jarkko Sakkinen 已提交
378 379 380 381
 * @property_id:	property ID.
 * @value:		output variable.
 * @desc:		passed to tpm_transmit_cmd()
 *
382 383 384
 * Return:
 *   0 on success,
 *   -errno or a TPM return code otherwise
J
Jarkko Sakkinen 已提交
385 386 387 388
 */
ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,  u32 *value,
			const char *desc)
{
389 390
	struct tpm2_get_cap_out *out;
	struct tpm_buf buf;
J
Jarkko Sakkinen 已提交
391 392
	int rc;

393 394 395 396 397 398
	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
	if (rc)
		return rc;
	tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES);
	tpm_buf_append_u32(&buf, property_id);
	tpm_buf_append_u32(&buf, 1);
399
	rc = tpm_transmit_cmd(chip, &buf, 0, NULL);
400 401 402 403 404 405
	if (!rc) {
		out = (struct tpm2_get_cap_out *)
			&buf.data[TPM_HEADER_SIZE];
		*value = be32_to_cpu(out->value);
	}
	tpm_buf_destroy(&buf);
J
Jarkko Sakkinen 已提交
406 407
	return rc;
}
408
EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt);
J
Jarkko Sakkinen 已提交
409 410

/**
411
 * tpm2_shutdown() - send a TPM shutdown command
W
Winkler, Tomas 已提交
412
 *
413 414 415 416 417 418
 * Sends a TPM shutdown command. The shutdown command is used in call
 * sites where the system is going down. If it fails, there is not much
 * that can be done except print an error message.
 *
 * @chip:		a &tpm_chip instance
 * @shutdown_type:	TPM_SU_CLEAR or TPM_SU_STATE.
J
Jarkko Sakkinen 已提交
419
 */
420
void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
J
Jarkko Sakkinen 已提交
421
{
422
	struct tpm_buf buf;
423
	int rc;
J
Jarkko Sakkinen 已提交
424

425 426 427 428
	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN);
	if (rc)
		return;
	tpm_buf_append_u16(&buf, shutdown_type);
429
	tpm_transmit_cmd(chip, &buf, 0, "stopping the TPM");
430
	tpm_buf_destroy(&buf);
J
Jarkko Sakkinen 已提交
431 432 433
}

/**
434
 * tpm2_do_selftest() - ensure that all self tests have passed
W
Winkler, Tomas 已提交
435
 *
J
Jarkko Sakkinen 已提交
436 437
 * @chip: TPM chip to use
 *
W
Winkler, Tomas 已提交
438 439
 * Return: Same as with tpm_transmit_cmd.
 *
440 441 442 443 444
 * The TPM can either run all self tests synchronously and then return
 * RC_SUCCESS once all tests were successful. Or it can choose to run the tests
 * asynchronously and return RC_TESTING immediately while the self tests still
 * execute in the background. This function handles both cases and waits until
 * all tests have completed.
J
Jarkko Sakkinen 已提交
445
 */
446
static int tpm2_do_selftest(struct tpm_chip *chip)
J
Jarkko Sakkinen 已提交
447
{
448 449
	struct tpm_buf buf;
	int full;
J
Jarkko Sakkinen 已提交
450 451
	int rc;

452 453 454 455
	for (full = 0; full < 2; full++) {
		rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST);
		if (rc)
			return rc;
J
Jarkko Sakkinen 已提交
456

457
		tpm_buf_append_u8(&buf, full);
458
		rc = tpm_transmit_cmd(chip, &buf, 0,
459 460
				      "attempting the self test");
		tpm_buf_destroy(&buf);
J
Jarkko Sakkinen 已提交
461

462 463 464 465
		if (rc == TPM2_RC_TESTING)
			rc = TPM2_RC_SUCCESS;
		if (rc == TPM2_RC_INITIALIZE || rc == TPM2_RC_SUCCESS)
			return rc;
J
Jarkko Sakkinen 已提交
466 467 468 469 470
	}

	return rc;
}

471
/**
472 473
 * tpm2_probe() - probe for the TPM 2.0 protocol
 * @chip:	a &tpm_chip instance
474
 *
475 476 477
 * Send an idempotent TPM 2.0 command and see whether there is TPM2 chip in the
 * other end based on the response tag. The flag TPM_CHIP_FLAG_TPM2 is set by
 * this function if this is the case.
W
Winkler, Tomas 已提交
478
 *
479 480 481
 * Return:
 *   0 on success,
 *   -errno otherwise
482 483 484
 */
int tpm2_probe(struct tpm_chip *chip)
{
J
Jarkko Sakkinen 已提交
485
	struct tpm_header *out;
486
	struct tpm_buf buf;
487 488
	int rc;

489 490
	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
	if (rc)
491
		return rc;
492 493 494
	tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES);
	tpm_buf_append_u32(&buf, TPM_PT_TOTAL_COMMANDS);
	tpm_buf_append_u32(&buf, 1);
495
	rc = tpm_transmit_cmd(chip, &buf, 0, NULL);
496 497
	/* We ignore TPM return codes on purpose. */
	if (rc >=  0) {
J
Jarkko Sakkinen 已提交
498
		out = (struct tpm_header *)buf.data;
499 500 501 502
		if (be16_to_cpu(out->tag) == TPM2_ST_NO_SESSIONS)
			chip->flags |= TPM_CHIP_FLAG_TPM2;
	}
	tpm_buf_destroy(&buf);
503 504 505
	return 0;
}
EXPORT_SYMBOL_GPL(tpm2_probe);
506

507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
static int tpm2_init_bank_info(struct tpm_chip *chip, u32 bank_index)
{
	struct tpm_bank_info *bank = chip->allocated_banks + bank_index;
	struct tpm_digest digest = { .alg_id = bank->alg_id };
	int i;

	/*
	 * Avoid unnecessary PCR read operations to reduce overhead
	 * and obtain identifiers of the crypto subsystem.
	 */
	for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
		enum hash_algo crypto_algo = tpm2_hash_map[i].crypto_id;

		if (bank->alg_id != tpm2_hash_map[i].tpm_id)
			continue;

		bank->digest_size = hash_digest_size[crypto_algo];
		bank->crypto_id = crypto_algo;
		return 0;
	}

528 529
	bank->crypto_id = HASH_ALGO__LAST;

530 531 532
	return tpm2_pcr_read(chip, 0, &digest, &bank->digest_size);
}

533 534 535 536 537 538
struct tpm2_pcr_selection {
	__be16  hash_alg;
	u8  size_of_select;
	u8  pcr_select[3];
} __packed;

539
ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
540 541 542 543 544 545 546
{
	struct tpm2_pcr_selection pcr_selection;
	struct tpm_buf buf;
	void *marker;
	void *end;
	void *pcr_select_offset;
	u32 sizeof_pcr_selection;
547 548 549
	u32 nr_possible_banks;
	u32 nr_alloc_banks = 0;
	u16 hash_alg;
550 551 552 553 554 555 556 557 558 559 560 561
	u32 rsp_len;
	int rc;
	int i = 0;

	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
	if (rc)
		return rc;

	tpm_buf_append_u32(&buf, TPM2_CAP_PCRS);
	tpm_buf_append_u32(&buf, 0);
	tpm_buf_append_u32(&buf, 1);

562
	rc = tpm_transmit_cmd(chip, &buf, 9, "get tpm pcr allocation");
563 564 565
	if (rc)
		goto out;

566
	nr_possible_banks = be32_to_cpup(
567 568
		(__be32 *)&buf.data[TPM_HEADER_SIZE + 5]);

569 570 571 572 573
	chip->allocated_banks = kcalloc(nr_possible_banks,
					sizeof(*chip->allocated_banks),
					GFP_KERNEL);
	if (!chip->allocated_banks) {
		rc = -ENOMEM;
574 575 576 577 578 579 580 581
		goto out;
	}

	marker = &buf.data[TPM_HEADER_SIZE + 9];

	rsp_len = be32_to_cpup((__be32 *)&buf.data[2]);
	end = &buf.data[rsp_len];

582
	for (i = 0; i < nr_possible_banks; i++) {
583 584 585 586 587 588 589 590
		pcr_select_offset = marker +
			offsetof(struct tpm2_pcr_selection, size_of_select);
		if (pcr_select_offset >= end) {
			rc = -EFAULT;
			break;
		}

		memcpy(&pcr_selection, marker, sizeof(pcr_selection));
591 592 593 594 595
		hash_alg = be16_to_cpu(pcr_selection.hash_alg);

		pcr_select_offset = memchr_inv(pcr_selection.pcr_select, 0,
					       pcr_selection.size_of_select);
		if (pcr_select_offset) {
596 597 598 599 600 601
			chip->allocated_banks[nr_alloc_banks].alg_id = hash_alg;

			rc = tpm2_init_bank_info(chip, nr_alloc_banks);
			if (rc < 0)
				break;

602 603 604
			nr_alloc_banks++;
		}

605 606 607 608 609 610
		sizeof_pcr_selection = sizeof(pcr_selection.hash_alg) +
			sizeof(pcr_selection.size_of_select) +
			pcr_selection.size_of_select;
		marker = marker + sizeof_pcr_selection;
	}

611
	chip->nr_allocated_banks = nr_alloc_banks;
612 613 614 615 616
out:
	tpm_buf_destroy(&buf);

	return rc;
}
617

618
int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
J
Jarkko Sakkinen 已提交
619 620 621
{
	struct tpm_buf buf;
	u32 nr_commands;
622
	__be32 *attrs;
J
Jarkko Sakkinen 已提交
623 624 625 626 627 628 629 630 631 632 633 634 635
	u32 cc;
	int i;
	int rc;

	rc = tpm2_get_tpm_pt(chip, TPM_PT_TOTAL_COMMANDS, &nr_commands, NULL);
	if (rc)
		goto out;

	if (nr_commands > 0xFFFFF) {
		rc = -EFAULT;
		goto out;
	}

636
	chip->cc_attrs_tbl = devm_kcalloc(&chip->dev, 4, nr_commands,
J
Jarkko Sakkinen 已提交
637
					  GFP_KERNEL);
638 639 640 641
	if (!chip->cc_attrs_tbl) {
		rc = -ENOMEM;
		goto out;
	}
J
Jarkko Sakkinen 已提交
642 643 644 645 646 647 648 649 650

	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
	if (rc)
		goto out;

	tpm_buf_append_u32(&buf, TPM2_CAP_COMMANDS);
	tpm_buf_append_u32(&buf, TPM2_CC_FIRST);
	tpm_buf_append_u32(&buf, nr_commands);

651
	rc = tpm_transmit_cmd(chip, &buf, 9 + 4 * nr_commands, NULL);
J
Jarkko Sakkinen 已提交
652 653 654 655 656 657 658 659 660 661 662 663 664
	if (rc) {
		tpm_buf_destroy(&buf);
		goto out;
	}

	if (nr_commands !=
	    be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE + 5])) {
		tpm_buf_destroy(&buf);
		goto out;
	}

	chip->nr_commands = nr_commands;

665
	attrs = (__be32 *)&buf.data[TPM_HEADER_SIZE + 9];
J
Jarkko Sakkinen 已提交
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
	for (i = 0; i < nr_commands; i++, attrs++) {
		chip->cc_attrs_tbl[i] = be32_to_cpup(attrs);
		cc = chip->cc_attrs_tbl[i] & 0xFFFF;

		if (cc == TPM2_CC_CONTEXT_SAVE || cc == TPM2_CC_FLUSH_CONTEXT) {
			chip->cc_attrs_tbl[i] &=
				~(GENMASK(2, 0) << TPM2_CC_ATTR_CHANDLES);
			chip->cc_attrs_tbl[i] |= 1 << TPM2_CC_ATTR_CHANDLES;
		}
	}

	tpm_buf_destroy(&buf);

out:
	if (rc > 0)
		rc = -ENODEV;
	return rc;
}
684
EXPORT_SYMBOL_GPL(tpm2_get_cc_attrs_tbl);
J
Jarkko Sakkinen 已提交
685

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
/**
 * tpm2_startup - turn on the TPM
 * @chip: TPM chip to use
 *
 * Normally the firmware should start the TPM. This function is provided as a
 * workaround if this does not happen. A legal case for this could be for
 * example when a TPM emulator is used.
 *
 * Return: same as tpm_transmit_cmd()
 */

static int tpm2_startup(struct tpm_chip *chip)
{
	struct tpm_buf buf;
	int rc;

	dev_info(&chip->dev, "starting up the TPM manually\n");

	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
	if (rc < 0)
		return rc;

	tpm_buf_append_u16(&buf, TPM2_SU_CLEAR);
709
	rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to start the TPM");
710 711 712 713 714
	tpm_buf_destroy(&buf);

	return rc;
}

715 716 717 718 719
/**
 * tpm2_auto_startup - Perform the standard automatic TPM initialization
 *                     sequence
 * @chip: TPM chip to use
 *
J
Jarkko Sakkinen 已提交
720
 * Returns 0 on success, < 0 in case of fatal error.
721 722 723 724 725
 */
int tpm2_auto_startup(struct tpm_chip *chip)
{
	int rc;

726
	rc = tpm2_get_timeouts(chip);
727 728 729 730
	if (rc)
		goto out;

	rc = tpm2_do_selftest(chip);
731
	if (rc && rc != TPM2_RC_INITIALIZE)
732 733 734
		goto out;

	if (rc == TPM2_RC_INITIALIZE) {
735
		rc = tpm2_startup(chip);
736 737 738 739
		if (rc)
			goto out;

		rc = tpm2_do_selftest(chip);
740
		if (rc)
741 742 743
			goto out;
	}

J
Jarkko Sakkinen 已提交
744
	rc = tpm2_get_cc_attrs_tbl(chip);
745 746 747 748 749 750

out:
	if (rc > 0)
		rc = -ENODEV;
	return rc;
}
J
Jarkko Sakkinen 已提交
751 752 753 754 755 756 757 758 759 760 761

int tpm2_find_cc(struct tpm_chip *chip, u32 cc)
{
	int i;

	for (i = 0; i < chip->nr_commands; i++)
		if (cc == (chip->cc_attrs_tbl[i] & GENMASK(15, 0)))
			return i;

	return -1;
}