[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/2] backends/tpm: Send TPM2_Shutdown upon VM reset
From: |
Stefan Berger |
Subject: |
[PATCH 2/2] backends/tpm: Send TPM2_Shutdown upon VM reset |
Date: |
Fri, 27 May 2022 13:30:58 -0400 |
Send a TPM2_Shutdown(TPM2_SU_CLEAR) command to the TPM emulator when the
VM is reset. However, this is only necessary for a TPM 2 and only if the
TPM2_Shutdown command has not been sent by the VM as the last command as
it would do under normal circumstances. Further, it also doesn't need to
be sent if the VM was just started.
This fixes a bug where well-timed VM resets may trigger the TPM 2's
dictionary attack lockout logic due to the TPM 2 not having received a
TPM2_Shutdown command when it was reset.
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2087538
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
backends/tpm/tpm_emulator.c | 35 +++++++++++++++++++++++++++++++++++
backends/tpm/tpm_int.h | 3 +++
backends/tpm/trace-events | 1 +
3 files changed, 39 insertions(+)
diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
index 89ecb04a2a..c928d7abd1 100644
--- a/backends/tpm/tpm_emulator.c
+++ b/backends/tpm/tpm_emulator.c
@@ -389,8 +389,43 @@ err_exit:
return -1;
}
+static void tpm_emulator_send_tpm2_shutdown(TPMEmulator *tpm_emu)
+{
+ const struct tpm2_shutdown {
+ struct tpm_req_hdr hdr;
+ uint16_t shutdownType;
+ } tpm2_shutdown_clear = {
+ .hdr = {
+ .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
+ .len = cpu_to_be32(sizeof(tpm2_shutdown_clear)),
+ .ordinal = cpu_to_be32(TPM2_CC_Shutdown),
+ },
+ .shutdownType = cpu_to_be16(TPM2_SU_CLEAR),
+ };
+ Error *local_err = NULL;
+ uint8_t result[10];
+
+ trace_tpm_emulator_send_tpm2_shutdown(tpm_emu->last_command);
+
+ if (tpm_emulator_unix_tx_bufs(tpm_emu, (uint8_t *)&tpm2_shutdown_clear,
+ sizeof(tpm2_shutdown_clear),
+ result, sizeof(result),
+ NULL, &local_err) < 0) {
+ error_report_err(local_err);
+ }
+}
+
static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize)
{
+ TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
+
+ /* In case of VM reset we may need to send a TPM2_Shutdown command */
+ if (tpm_emu->tpm_version == TPM_VERSION_2_0 &&
+ tpm_emu->last_command != TPM_ORDINAL_NONE &&
+ tpm_emu->last_command != TPM2_CC_Shutdown) {
+ tpm_emulator_send_tpm2_shutdown(tpm_emu);
+ }
+
return tpm_emulator_startup_tpm_resume(tb, buffersize, false);
}
diff --git a/backends/tpm/tpm_int.h b/backends/tpm/tpm_int.h
index ba6109306e..2730d4ff02 100644
--- a/backends/tpm/tpm_int.h
+++ b/backends/tpm/tpm_int.h
@@ -64,6 +64,7 @@ struct tpm_resp_hdr {
/* TPM2 defines */
#define TPM2_ST_NO_SESSIONS 0x8001
+#define TPM2_CC_Shutdown 0x00000145
#define TPM2_CC_ReadClock 0x00000181
#define TPM2_CC_GetCapability 0x0000017a
@@ -71,6 +72,8 @@ struct tpm_resp_hdr {
#define TPM2_PT_MAX_COMMAND_SIZE 0x11e
+#define TPM2_SU_CLEAR 0x0
+
#define TPM_RC_INSUFFICIENT 0x9a
#define TPM_RC_FAILURE 0x101
#define TPM_RC_LOCALITY 0x907
diff --git a/backends/tpm/trace-events b/backends/tpm/trace-events
index 3298766dd7..cd16d41804 100644
--- a/backends/tpm/trace-events
+++ b/backends/tpm/trace-events
@@ -31,3 +31,4 @@ tpm_emulator_set_state_blobs_error(const char *msg) "error
while setting state b
tpm_emulator_set_state_blobs_done(void) "Done setting state blobs"
tpm_emulator_pre_save(void) ""
tpm_emulator_inst_init(void) ""
+tpm_emulator_send_tpm2_shutdown(uint32_t ord) "Sending
TPM2_Shutdown(TPM2_SU_CLEAR); last ordinal from VM was: 0x%08x"
--
2.35.3