|
@@ -282,7 +282,7 @@ int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
|
|
sizeof(cmd.params.pcrread_in.pcr_select));
|
|
sizeof(cmd.params.pcrread_in.pcr_select));
|
|
cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
|
|
cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
|
|
|
|
|
|
- rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
|
|
|
|
|
|
+ rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0,
|
|
"attempting to read a pcr value");
|
|
"attempting to read a pcr value");
|
|
if (rc == 0) {
|
|
if (rc == 0) {
|
|
buf = cmd.params.pcrread_out.digest;
|
|
buf = cmd.params.pcrread_out.digest;
|
|
@@ -330,7 +330,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
|
|
cmd.params.pcrextend_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
|
|
cmd.params.pcrextend_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
|
|
memcpy(cmd.params.pcrextend_in.digest, hash, TPM_DIGEST_SIZE);
|
|
memcpy(cmd.params.pcrextend_in.digest, hash, TPM_DIGEST_SIZE);
|
|
|
|
|
|
- rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
|
|
|
|
|
|
+ rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0,
|
|
"attempting extend a PCR value");
|
|
"attempting extend a PCR value");
|
|
|
|
|
|
return rc;
|
|
return rc;
|
|
@@ -376,7 +376,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max)
|
|
cmd.header.in = tpm2_getrandom_header;
|
|
cmd.header.in = tpm2_getrandom_header;
|
|
cmd.params.getrandom_in.size = cpu_to_be16(num_bytes);
|
|
cmd.params.getrandom_in.size = cpu_to_be16(num_bytes);
|
|
|
|
|
|
- err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
|
|
|
|
|
|
+ err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0,
|
|
"attempting get random");
|
|
"attempting get random");
|
|
if (err)
|
|
if (err)
|
|
break;
|
|
break;
|
|
@@ -434,12 +434,12 @@ static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle,
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * tpm2_seal_trusted() - seal a trusted key
|
|
|
|
- * @chip_num: A specific chip number for the request or TPM_ANY_NUM
|
|
|
|
- * @options: authentication values and other options
|
|
|
|
|
|
+ * tpm2_seal_trusted() - seal the payload of a trusted key
|
|
|
|
+ * @chip_num: TPM chip to use
|
|
* @payload: the key data in clear and encrypted form
|
|
* @payload: the key data in clear and encrypted form
|
|
|
|
+ * @options: authentication values and other options
|
|
*
|
|
*
|
|
- * Returns < 0 on error and 0 on success.
|
|
|
|
|
|
+ * Return: < 0 on error and 0 on success.
|
|
*/
|
|
*/
|
|
int tpm2_seal_trusted(struct tpm_chip *chip,
|
|
int tpm2_seal_trusted(struct tpm_chip *chip,
|
|
struct trusted_key_payload *payload,
|
|
struct trusted_key_payload *payload,
|
|
@@ -512,7 +512,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "sealing data");
|
|
|
|
|
|
+ rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, "sealing data");
|
|
if (rc)
|
|
if (rc)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
@@ -538,10 +538,18 @@ out:
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|
|
-static int tpm2_load(struct tpm_chip *chip,
|
|
|
|
- struct trusted_key_payload *payload,
|
|
|
|
- struct trusted_key_options *options,
|
|
|
|
- u32 *blob_handle)
|
|
|
|
|
|
+/**
|
|
|
|
+ * tpm2_load_cmd() - execute a TPM2_Load command
|
|
|
|
+ * @chip_num: TPM chip to use
|
|
|
|
+ * @payload: the key data in clear and encrypted form
|
|
|
|
+ * @options: authentication values and other options
|
|
|
|
+ *
|
|
|
|
+ * Return: same as with tpm_transmit_cmd
|
|
|
|
+ */
|
|
|
|
+static int tpm2_load_cmd(struct tpm_chip *chip,
|
|
|
|
+ struct trusted_key_payload *payload,
|
|
|
|
+ struct trusted_key_options *options,
|
|
|
|
+ u32 *blob_handle, unsigned int flags)
|
|
{
|
|
{
|
|
struct tpm_buf buf;
|
|
struct tpm_buf buf;
|
|
unsigned int private_len;
|
|
unsigned int private_len;
|
|
@@ -576,7 +584,7 @@ static int tpm2_load(struct tpm_chip *chip,
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "loading blob");
|
|
|
|
|
|
+ rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags, "loading blob");
|
|
if (!rc)
|
|
if (!rc)
|
|
*blob_handle = be32_to_cpup(
|
|
*blob_handle = be32_to_cpup(
|
|
(__be32 *) &buf.data[TPM_HEADER_SIZE]);
|
|
(__be32 *) &buf.data[TPM_HEADER_SIZE]);
|
|
@@ -590,7 +598,16 @@ out:
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|
|
-static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
|
|
|
|
|
|
+/**
|
|
|
|
+ * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command
|
|
|
|
+ * @chip_num: TPM chip to use
|
|
|
|
+ * @payload: the key data in clear and encrypted form
|
|
|
|
+ * @options: authentication values and other options
|
|
|
|
+ *
|
|
|
|
+ * Return: same as with tpm_transmit_cmd
|
|
|
|
+ */
|
|
|
|
+static void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
|
|
|
|
+ unsigned int flags)
|
|
{
|
|
{
|
|
struct tpm_buf buf;
|
|
struct tpm_buf buf;
|
|
int rc;
|
|
int rc;
|
|
@@ -604,7 +621,8 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
|
|
|
|
|
|
tpm_buf_append_u32(&buf, handle);
|
|
tpm_buf_append_u32(&buf, handle);
|
|
|
|
|
|
- rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "flushing context");
|
|
|
|
|
|
+ rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags,
|
|
|
|
+ "flushing context");
|
|
if (rc)
|
|
if (rc)
|
|
dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle,
|
|
dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle,
|
|
rc);
|
|
rc);
|
|
@@ -612,10 +630,18 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
|
|
tpm_buf_destroy(&buf);
|
|
tpm_buf_destroy(&buf);
|
|
}
|
|
}
|
|
|
|
|
|
-static int tpm2_unseal(struct tpm_chip *chip,
|
|
|
|
- struct trusted_key_payload *payload,
|
|
|
|
- struct trusted_key_options *options,
|
|
|
|
- u32 blob_handle)
|
|
|
|
|
|
+/**
|
|
|
|
+ * tpm2_unseal_cmd() - execute a TPM2_Unload command
|
|
|
|
+ * @chip_num: TPM chip to use
|
|
|
|
+ * @payload: the key data in clear and encrypted form
|
|
|
|
+ * @options: authentication values and other options
|
|
|
|
+ *
|
|
|
|
+ * Return: same as with tpm_transmit_cmd
|
|
|
|
+ */
|
|
|
|
+static int tpm2_unseal_cmd(struct tpm_chip *chip,
|
|
|
|
+ struct trusted_key_payload *payload,
|
|
|
|
+ struct trusted_key_options *options,
|
|
|
|
+ u32 blob_handle, unsigned int flags)
|
|
{
|
|
{
|
|
struct tpm_buf buf;
|
|
struct tpm_buf buf;
|
|
u16 data_len;
|
|
u16 data_len;
|
|
@@ -635,7 +661,7 @@ static int tpm2_unseal(struct tpm_chip *chip,
|
|
options->blobauth /* hmac */,
|
|
options->blobauth /* hmac */,
|
|
TPM_DIGEST_SIZE);
|
|
TPM_DIGEST_SIZE);
|
|
|
|
|
|
- rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "unsealing");
|
|
|
|
|
|
+ rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags, "unsealing");
|
|
if (rc > 0)
|
|
if (rc > 0)
|
|
rc = -EPERM;
|
|
rc = -EPERM;
|
|
|
|
|
|
@@ -654,12 +680,12 @@ static int tpm2_unseal(struct tpm_chip *chip,
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * tpm_unseal_trusted() - unseal a trusted key
|
|
|
|
- * @chip_num: A specific chip number for the request or TPM_ANY_NUM
|
|
|
|
- * @options: authentication values and other options
|
|
|
|
|
|
+ * tpm_unseal_trusted() - unseal the payload of a trusted key
|
|
|
|
+ * @chip_num: TPM chip to use
|
|
* @payload: the key data in clear and encrypted form
|
|
* @payload: the key data in clear and encrypted form
|
|
|
|
+ * @options: authentication values and other options
|
|
*
|
|
*
|
|
- * Returns < 0 on error and 0 on success.
|
|
|
|
|
|
+ * Return: < 0 on error and 0 on success.
|
|
*/
|
|
*/
|
|
int tpm2_unseal_trusted(struct tpm_chip *chip,
|
|
int tpm2_unseal_trusted(struct tpm_chip *chip,
|
|
struct trusted_key_payload *payload,
|
|
struct trusted_key_payload *payload,
|
|
@@ -668,14 +694,17 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
|
|
u32 blob_handle;
|
|
u32 blob_handle;
|
|
int rc;
|
|
int rc;
|
|
|
|
|
|
- rc = tpm2_load(chip, payload, options, &blob_handle);
|
|
|
|
|
|
+ mutex_lock(&chip->tpm_mutex);
|
|
|
|
+ rc = tpm2_load_cmd(chip, payload, options, &blob_handle,
|
|
|
|
+ TPM_TRANSMIT_UNLOCKED);
|
|
if (rc)
|
|
if (rc)
|
|
- return rc;
|
|
|
|
-
|
|
|
|
- rc = tpm2_unseal(chip, payload, options, blob_handle);
|
|
|
|
-
|
|
|
|
- tpm2_flush_context(chip, blob_handle);
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
|
|
+ rc = tpm2_unseal_cmd(chip, payload, options, blob_handle,
|
|
|
|
+ TPM_TRANSMIT_UNLOCKED);
|
|
|
|
+ tpm2_flush_context_cmd(chip, blob_handle, TPM_TRANSMIT_UNLOCKED);
|
|
|
|
+out:
|
|
|
|
+ mutex_unlock(&chip->tpm_mutex);
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -701,7 +730,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value,
|
|
cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id);
|
|
cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id);
|
|
cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
|
|
cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
|
|
|
|
|
|
- rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), desc);
|
|
|
|
|
|
+ rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, desc);
|
|
if (!rc)
|
|
if (!rc)
|
|
*value = be32_to_cpu(cmd.params.get_tpm_pt_out.value);
|
|
*value = be32_to_cpu(cmd.params.get_tpm_pt_out.value);
|
|
|
|
|
|
@@ -735,7 +764,7 @@ static int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
|
|
cmd.header.in = tpm2_startup_header;
|
|
cmd.header.in = tpm2_startup_header;
|
|
|
|
|
|
cmd.params.startup_in.startup_type = cpu_to_be16(startup_type);
|
|
cmd.params.startup_in.startup_type = cpu_to_be16(startup_type);
|
|
- return tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
|
|
|
|
|
|
+ return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0,
|
|
"attempting to start the TPM");
|
|
"attempting to start the TPM");
|
|
}
|
|
}
|
|
|
|
|
|
@@ -763,7 +792,7 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
|
|
cmd.header.in = tpm2_shutdown_header;
|
|
cmd.header.in = tpm2_shutdown_header;
|
|
cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
|
|
cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
|
|
|
|
|
|
- rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), "stopping the TPM");
|
|
|
|
|
|
+ rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, "stopping the TPM");
|
|
|
|
|
|
/* In places where shutdown command is sent there's no much we can do
|
|
/* In places where shutdown command is sent there's no much we can do
|
|
* except print the error code on a system failure.
|
|
* except print the error code on a system failure.
|
|
@@ -828,7 +857,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
|
|
cmd.header.in = tpm2_selftest_header;
|
|
cmd.header.in = tpm2_selftest_header;
|
|
cmd.params.selftest_in.full_test = full;
|
|
cmd.params.selftest_in.full_test = full;
|
|
|
|
|
|
- rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE,
|
|
|
|
|
|
+ rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE, 0,
|
|
"continue selftest");
|
|
"continue selftest");
|
|
|
|
|
|
/* At least some prototype chips seem to give RC_TESTING error
|
|
/* At least some prototype chips seem to give RC_TESTING error
|
|
@@ -880,7 +909,7 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
|
|
cmd.params.pcrread_in.pcr_select[1] = 0x00;
|
|
cmd.params.pcrread_in.pcr_select[1] = 0x00;
|
|
cmd.params.pcrread_in.pcr_select[2] = 0x00;
|
|
cmd.params.pcrread_in.pcr_select[2] = 0x00;
|
|
|
|
|
|
- rc = tpm_transmit_cmd(chip, (u8 *) &cmd, sizeof(cmd), NULL);
|
|
|
|
|
|
+ rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, NULL);
|
|
if (rc < 0)
|
|
if (rc < 0)
|
|
break;
|
|
break;
|
|
|
|
|
|
@@ -928,7 +957,7 @@ int tpm2_probe(struct tpm_chip *chip)
|
|
cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
|
|
cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
|
|
cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
|
|
cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
|
|
|
|
|
|
- rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd));
|
|
|
|
|
|
+ rc = tpm_transmit(chip, (const u8 *)&cmd, sizeof(cmd), 0);
|
|
if (rc < 0)
|
|
if (rc < 0)
|
|
return rc;
|
|
return rc;
|
|
else if (rc < TPM_HEADER_SIZE)
|
|
else if (rc < TPM_HEADER_SIZE)
|