diff options
Diffstat (limited to 'drivers/char/tpm/tpm2-cmd.c')
-rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 308 |
1 files changed, 151 insertions, 157 deletions
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 3acf4fd4e5a5..a6bec13afa69 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -40,129 +40,121 @@ static struct tpm2_hash tpm2_hash_map[] = { {HASH_ALGO_SM3_256, TPM2_ALG_SM3_256}, }; -/* - * Array with one entry per ordinal defining the maximum amount - * of time the chip could take to return the result. The values - * of the SHORT, MEDIUM, and LONG durations are taken from the - * PC Client Profile (PTP) specification. - * LONG_LONG is for commands that generates keys which empirically - * takes longer time on some systems. +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; +} + +/** + * 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 */ -static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { - TPM_UNDEFINED, /* 11F */ - TPM_UNDEFINED, /* 120 */ - TPM_LONG, /* 121 */ - TPM_UNDEFINED, /* 122 */ - TPM_UNDEFINED, /* 123 */ - TPM_UNDEFINED, /* 124 */ - TPM_UNDEFINED, /* 125 */ - TPM_UNDEFINED, /* 126 */ - TPM_UNDEFINED, /* 127 */ - TPM_UNDEFINED, /* 128 */ - TPM_LONG, /* 129 */ - TPM_UNDEFINED, /* 12a */ - TPM_UNDEFINED, /* 12b */ - TPM_UNDEFINED, /* 12c */ - TPM_UNDEFINED, /* 12d */ - TPM_UNDEFINED, /* 12e */ - TPM_UNDEFINED, /* 12f */ - TPM_UNDEFINED, /* 130 */ - TPM_LONG_LONG, /* 131 */ - TPM_UNDEFINED, /* 132 */ - TPM_UNDEFINED, /* 133 */ - TPM_UNDEFINED, /* 134 */ - TPM_UNDEFINED, /* 135 */ - TPM_UNDEFINED, /* 136 */ - TPM_UNDEFINED, /* 137 */ - TPM_UNDEFINED, /* 138 */ - TPM_UNDEFINED, /* 139 */ - TPM_UNDEFINED, /* 13a */ - TPM_UNDEFINED, /* 13b */ - TPM_UNDEFINED, /* 13c */ - TPM_UNDEFINED, /* 13d */ - TPM_MEDIUM, /* 13e */ - TPM_UNDEFINED, /* 13f */ - TPM_UNDEFINED, /* 140 */ - TPM_UNDEFINED, /* 141 */ - TPM_UNDEFINED, /* 142 */ - TPM_LONG, /* 143 */ - TPM_MEDIUM, /* 144 */ - TPM_UNDEFINED, /* 145 */ - TPM_UNDEFINED, /* 146 */ - TPM_UNDEFINED, /* 147 */ - TPM_UNDEFINED, /* 148 */ - TPM_UNDEFINED, /* 149 */ - TPM_UNDEFINED, /* 14a */ - TPM_UNDEFINED, /* 14b */ - TPM_UNDEFINED, /* 14c */ - TPM_UNDEFINED, /* 14d */ - TPM_LONG, /* 14e */ - TPM_UNDEFINED, /* 14f */ - TPM_UNDEFINED, /* 150 */ - TPM_UNDEFINED, /* 151 */ - TPM_UNDEFINED, /* 152 */ - TPM_LONG_LONG, /* 153 */ - TPM_UNDEFINED, /* 154 */ - TPM_UNDEFINED, /* 155 */ - TPM_UNDEFINED, /* 156 */ - TPM_UNDEFINED, /* 157 */ - TPM_UNDEFINED, /* 158 */ - TPM_UNDEFINED, /* 159 */ - TPM_UNDEFINED, /* 15a */ - TPM_UNDEFINED, /* 15b */ - TPM_MEDIUM, /* 15c */ - TPM_UNDEFINED, /* 15d */ - TPM_UNDEFINED, /* 15e */ - TPM_UNDEFINED, /* 15f */ - TPM_UNDEFINED, /* 160 */ - TPM_UNDEFINED, /* 161 */ - TPM_UNDEFINED, /* 162 */ - TPM_UNDEFINED, /* 163 */ - TPM_UNDEFINED, /* 164 */ - TPM_UNDEFINED, /* 165 */ - TPM_UNDEFINED, /* 166 */ - TPM_UNDEFINED, /* 167 */ - TPM_UNDEFINED, /* 168 */ - TPM_UNDEFINED, /* 169 */ - TPM_UNDEFINED, /* 16a */ - TPM_UNDEFINED, /* 16b */ - TPM_UNDEFINED, /* 16c */ - TPM_UNDEFINED, /* 16d */ - TPM_UNDEFINED, /* 16e */ - TPM_UNDEFINED, /* 16f */ - TPM_UNDEFINED, /* 170 */ - TPM_UNDEFINED, /* 171 */ - TPM_UNDEFINED, /* 172 */ - TPM_UNDEFINED, /* 173 */ - TPM_UNDEFINED, /* 174 */ - TPM_UNDEFINED, /* 175 */ - TPM_UNDEFINED, /* 176 */ - TPM_LONG, /* 177 */ - TPM_UNDEFINED, /* 178 */ - TPM_UNDEFINED, /* 179 */ - TPM_MEDIUM, /* 17a */ - TPM_LONG, /* 17b */ - TPM_UNDEFINED, /* 17c */ - TPM_UNDEFINED, /* 17d */ - TPM_UNDEFINED, /* 17e */ - TPM_UNDEFINED, /* 17f */ - TPM_UNDEFINED, /* 180 */ - TPM_UNDEFINED, /* 181 */ - TPM_MEDIUM, /* 182 */ - TPM_UNDEFINED, /* 183 */ - TPM_UNDEFINED, /* 184 */ - TPM_MEDIUM, /* 185 */ - TPM_MEDIUM, /* 186 */ - TPM_UNDEFINED, /* 187 */ - TPM_UNDEFINED, /* 188 */ - TPM_UNDEFINED, /* 189 */ - TPM_UNDEFINED, /* 18a */ - TPM_UNDEFINED, /* 18b */ - TPM_UNDEFINED, /* 18c */ - TPM_UNDEFINED, /* 18d */ - TPM_UNDEFINED, /* 18e */ - TPM_UNDEFINED /* 18f */ -}; +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); +} + struct tpm2_pcr_read_out { __be32 update_cnt; @@ -183,7 +175,7 @@ struct tpm2_pcr_read_out { * * Return: Same as with tpm_transmit_cmd. */ -int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) +int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) { int rc; struct tpm_buf buf; @@ -233,7 +225,7 @@ struct tpm2_null_auth_area { * * Return: Same as with tpm_transmit_cmd. */ -int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count, +int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, u32 count, struct tpm2_digest *digests) { struct tpm_buf buf; @@ -280,7 +272,6 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count, return rc; } - struct tpm2_get_random_out { __be16 size; u8 buffer[TPM_MAX_RNG_DATA]; @@ -351,11 +342,10 @@ out: /** * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command - * @chip: TPM chip to use - * @payload: the key data in clear and encrypted form - * @options: authentication values and other options + * @chip: TPM chip to use + * @handle: context handle + * @flags: tpm transmit flags - bitmap * - * Return: same as with tpm_transmit_cmd */ void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, unsigned int flags) @@ -748,32 +738,6 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) tpm_buf_destroy(&buf); } -/* - * tpm2_calc_ordinal_duration() - maximum duration for a command - * - * @chip: TPM chip to use. - * @ordinal: command code number. - * - * Return: maximum duration for a command - */ -unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) -{ - int index = TPM_UNDEFINED; - int duration = 0; - - if (ordinal >= TPM2_CC_FIRST && ordinal <= TPM2_CC_LAST) - index = tpm2_ordinal_duration[ordinal - TPM2_CC_FIRST]; - - if (index != TPM_UNDEFINED) - duration = chip->duration[index]; - - if (duration <= 0) - duration = msecs_to_jiffies(TPM2_DURATION_DEFAULT); - - return duration; -} -EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration); - /** * tpm2_do_selftest() - ensure that all self tests have passed * @@ -983,6 +947,36 @@ out: } /** + * 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); + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, + "attempting to start the TPM"); + tpm_buf_destroy(&buf); + + return rc; +} + +/** * tpm2_auto_startup - Perform the standard automatic TPM initialization * sequence * @chip: TPM chip to use @@ -993,7 +987,7 @@ int tpm2_auto_startup(struct tpm_chip *chip) { int rc; - rc = tpm_get_timeouts(chip); + rc = tpm2_get_timeouts(chip); if (rc) goto out; @@ -1002,7 +996,7 @@ int tpm2_auto_startup(struct tpm_chip *chip) goto out; if (rc == TPM2_RC_INITIALIZE) { - rc = tpm_startup(chip); + rc = tpm2_startup(chip); if (rc) goto out; |