qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]