cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tpm-sysfs.c (13364B)


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