From nobody Sat May 18 10:30:01 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1521236921902331.88285991740804; Fri, 16 Mar 2018 14:48:41 -0700 (PDT) Received: from localhost ([::1]:59750 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ewxDK-000437-Vb for importer@patchew.org; Fri, 16 Mar 2018 17:48:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36854) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ewxBZ-00035g-Ms for qemu-devel@nongnu.org; Fri, 16 Mar 2018 17:46:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ewxBW-0003Wd-CN for qemu-devel@nongnu.org; Fri, 16 Mar 2018 17:46:49 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:36930) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ewxBW-0003WA-2d for qemu-devel@nongnu.org; Fri, 16 Mar 2018 17:46:46 -0400 Received: from pps.filterd (m0098393.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w2GLjA40017943 for ; Fri, 16 Mar 2018 17:46:44 -0400 Received: from e36.co.us.ibm.com (e36.co.us.ibm.com [32.97.110.154]) by mx0a-001b2d01.pphosted.com with ESMTP id 2grj6crjbq-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Fri, 16 Mar 2018 17:46:44 -0400 Received: from localhost by e36.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 16 Mar 2018 15:46:43 -0600 Received: from b03cxnp08028.gho.boulder.ibm.com (9.17.130.20) by e36.co.us.ibm.com (192.168.1.136) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 16 Mar 2018 15:46:41 -0600 Received: from b03ledav002.gho.boulder.ibm.com (b03ledav002.gho.boulder.ibm.com [9.17.130.233]) by b03cxnp08028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w2GLkfF0327970; Fri, 16 Mar 2018 14:46:41 -0700 Received: from b03ledav002.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1C462136040; Fri, 16 Mar 2018 15:46:41 -0600 (MDT) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b03ledav002.gho.boulder.ibm.com (Postfix) with ESMTP id A547A13603A; Fri, 16 Mar 2018 15:46:40 -0600 (MDT) From: Stefan Berger To: qemu-devel@nongnu.org Date: Fri, 16 Mar 2018 17:46:33 -0400 X-Mailer: git-send-email 2.5.5 In-Reply-To: <1521236796-24551-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1521236796-24551-1-git-send-email-stefanb@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18031621-0020-0000-0000-00000D99F046 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008687; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000254; SDB=6.01004051; UDB=6.00511034; IPR=6.00783340; MB=3.00020080; MTD=3.00000008; XFM=3.00000015; UTC=2018-03-16 21:46:43 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18031621-0021-0000-0000-00006085EE98 Message-Id: <1521236796-24551-2-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-03-16_14:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1803160253 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.156.1 Subject: [Qemu-devel] [PATCH v5 for 2.13 1/4] tpm: extend TPM emulator with state migration support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: marcandre.lureau@gmail.com, dgilbert@redhat.com, Stefan Berger Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Extend the TPM emulator backend device with state migration support. The external TPM emulator 'swtpm' provides a protocol over its control channel to retrieve its state blobs. We implement functions for getting and setting the different state blobs. In case the setting of the state blobs fails, we return a negative errno code to fail the start of the VM. Since we have an external TPM emulator, we need to make sure that we do not migrate the state for as long as it is busy processing a request. We need to wait for notification that the request has completed processing. Signed-off-by: Stefan Berger --- hw/tpm/tpm_emulator.c | 318 ++++++++++++++++++++++++++++++++++++++++++++++= ++-- hw/tpm/trace-events | 8 +- 2 files changed, 314 insertions(+), 12 deletions(-) diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index 6418ef0..6d6158d 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -4,7 +4,7 @@ * Copyright (c) 2017 Intel Corporation * Author: Amarnath Valluri * - * Copyright (c) 2010 - 2013 IBM Corporation + * Copyright (c) 2010 - 2013, 2018 IBM Corporation * Authors: * Stefan Berger * @@ -49,6 +49,19 @@ #define TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(S, cap) (((S)->caps & (cap)) =3D= =3D (cap)) =20 /* data structures */ + +/* blobs from the TPM; part of VM state when migrating */ +typedef struct TPMBlobBuffers { + uint32_t permanent_flags; + TPMSizedBuffer permanent; + + uint32_t volatil_flags; + TPMSizedBuffer volatil; + + uint32_t savestate_flags; + TPMSizedBuffer savestate; +} TPMBlobBuffers; + typedef struct TPMEmulator { TPMBackend parent; =20 @@ -64,6 +77,8 @@ typedef struct TPMEmulator { =20 unsigned int established_flag:1; unsigned int established_flag_cached:1; + + TPMBlobBuffers state_blobs; } TPMEmulator; =20 =20 @@ -293,7 +308,8 @@ static int tpm_emulator_set_buffer_size(TPMBackend *tb, return 0; } =20 -static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize) +static int tpm_emulator_startup_tpm_resume(TPMBackend *tb, size_t buffersi= ze, + bool is_resume) { TPMEmulator *tpm_emu =3D TPM_EMULATOR(tb); ptm_init init =3D { @@ -301,12 +317,17 @@ static int tpm_emulator_startup_tpm(TPMBackend *tb, s= ize_t buffersize) }; ptm_res res; =20 + trace_tpm_emulator_startup_tpm_resume(is_resume, buffersize); + if (buffersize !=3D 0 && tpm_emulator_set_buffer_size(tb, buffersize, NULL) < 0) { goto err_exit; } =20 - trace_tpm_emulator_startup_tpm(); + if (is_resume) { + init.u.req.init_flags |=3D cpu_to_be32(PTM_INIT_FLAG_DELETE_VOLATI= LE); + } + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_INIT, &init, sizeof(init), sizeof(init)) < 0) { error_report("tpm-emulator: could not send INIT: %s", @@ -325,6 +346,11 @@ err_exit: return -1; } =20 +static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize) +{ + return tpm_emulator_startup_tpm_resume(tb, buffersize, false); +} + static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb) { TPMEmulator *tpm_emu =3D TPM_EMULATOR(tb); @@ -423,16 +449,21 @@ static size_t tpm_emulator_get_buffer_size(TPMBackend= *tb) static int tpm_emulator_block_migration(TPMEmulator *tpm_emu) { Error *err =3D NULL; + ptm_cap caps =3D PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB | + PTM_CAP_STOP; =20 - error_setg(&tpm_emu->migration_blocker, - "Migration disabled: TPM emulator not yet migratable"); - migrate_add_blocker(tpm_emu->migration_blocker, &err); - if (err) { - error_report_err(err); - error_free(tpm_emu->migration_blocker); - tpm_emu->migration_blocker =3D NULL; + if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) { + error_setg(&tpm_emu->migration_blocker, + "Migration disabled: TPM emulator does not support " + "migration"); + migrate_add_blocker(tpm_emu->migration_blocker, &err); + if (err) { + error_report_err(err); + error_free(tpm_emu->migration_blocker); + tpm_emu->migration_blocker =3D NULL; =20 - return -1; + return -1; + } } =20 return 0; @@ -570,6 +601,267 @@ static const QemuOptDesc tpm_emulator_cmdline_opts[] = =3D { { /* end of list */ }, }; =20 +/* + * Transfer a TPM state blob from the TPM into a provided buffer. + * + * @tpm_emu: TPMEmulator + * @type: the type of blob to transfer + * @tsb: the TPMSizeBuffer to fill with the blob + * @flags: the flags to return to the caller + */ +static int tpm_emulator_get_state_blob(TPMEmulator *tpm_emu, + uint8_t type, + TPMSizedBuffer *tsb, + uint32_t *flags) +{ + ptm_getstate pgs; + ptm_res res; + ssize_t n; + uint32_t totlength, length; + + tpm_sized_buffer_reset(tsb); + + pgs.u.req.state_flags =3D cpu_to_be32(PTM_STATE_FLAG_DECRYPTED); + pgs.u.req.type =3D cpu_to_be32(type); + pgs.u.req.offset =3D 0; + + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_STATEBLOB, + &pgs, sizeof(pgs.u.req), + offsetof(ptm_getstate, u.resp.data)) < 0) { + error_report("tpm-emulator: could not get state blob type %d : %s", + type, strerror(errno)); + return -1; + } + + res =3D be32_to_cpu(pgs.u.resp.tpm_result); + if (res !=3D 0 && (res & 0x800) =3D=3D 0) { + error_report("tpm-emulator: Getting the stateblob (type %d) failed= " + "with a TPM error 0x%x", type, res); + return -1; + } + + totlength =3D be32_to_cpu(pgs.u.resp.totlength); + length =3D be32_to_cpu(pgs.u.resp.length); + if (totlength !=3D length) { + error_report("tpm-emulator: Expecting to read %u bytes " + "but would get %u", totlength, length); + return -1; + } + + *flags =3D be32_to_cpu(pgs.u.resp.state_flags); + + if (totlength > 0) { + tsb->buffer =3D g_try_malloc(totlength); + if (!tsb->buffer) { + error_report("tpm-emulator: Out of memory allocating %u bytes", + totlength); + return -1; + } + + n =3D qemu_chr_fe_read_all(&tpm_emu->ctrl_chr, tsb->buffer, totlen= gth); + if (n !=3D totlength) { + error_report("tpm-emulator: Could not read stateblob (type %d)= ; " + "expected %u bytes, got %zd", + type, totlength, n); + return -1; + } + } + tsb->size =3D totlength; + + trace_tpm_emulator_get_state_blob(type, tsb->size, *flags); + + return 0; +} + +static int tpm_emulator_get_state_blobs(TPMEmulator *tpm_emu) +{ + TPMBlobBuffers *state_blobs =3D &tpm_emu->state_blobs; + + if (tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_PERMANENT, + &state_blobs->permanent, + &state_blobs->permanent_flags) < 0 || + tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_VOLATILE, + &state_blobs->volatil, + &state_blobs->volatil_flags) < 0 || + tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_SAVESTATE, + &state_blobs->savestate, + &state_blobs->savestate_flags) < 0) { + goto err_exit; + } + + return 0; + + err_exit: + tpm_sized_buffer_reset(&state_blobs->volatil); + tpm_sized_buffer_reset(&state_blobs->permanent); + tpm_sized_buffer_reset(&state_blobs->savestate); + + return -1; +} + +/* + * Transfer a TPM state blob to the TPM emulator. + * + * @tpm_emu: TPMEmulator + * @type: the type of TPM state blob to transfer + * @tsb: TPMSizedBuffer containing the TPM state blob + * @flags: Flags describing the (encryption) state of the TPM state blob + */ +static int tpm_emulator_set_state_blob(TPMEmulator *tpm_emu, + uint32_t type, + TPMSizedBuffer *tsb, + uint32_t flags) +{ + ssize_t n; + ptm_setstate pss; + ptm_res tpm_result; + + if (tsb->size =3D=3D 0) { + return 0; + } + + pss =3D (ptm_setstate) { + .u.req.state_flags =3D cpu_to_be32(flags), + .u.req.type =3D cpu_to_be32(type), + .u.req.length =3D cpu_to_be32(tsb->size), + }; + + /* write the header only */ + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_STATEBLOB, &pss, + offsetof(ptm_setstate, u.req.data), 0) < 0) { + error_report("tpm-emulator: could not set state blob type %d : %s", + type, strerror(errno)); + return -1; + } + + /* now the body */ + n =3D qemu_chr_fe_write_all(&tpm_emu->ctrl_chr, tsb->buffer, tsb->size= ); + if (n !=3D tsb->size) { + error_report("tpm-emulator: Writing the stateblob (type %d) " + "failed; could not write %u bytes, but only %zd", + type, tsb->size, n); + return -1; + } + + /* now get the result */ + n =3D qemu_chr_fe_read_all(&tpm_emu->ctrl_chr, + (uint8_t *)&pss, sizeof(pss.u.resp)); + if (n !=3D sizeof(pss.u.resp)) { + error_report("tpm-emulator: Reading response from writing stateblo= b " + "(type %d) failed; expected %zu bytes, got %zd", type, + sizeof(pss.u.resp), n); + return -1; + } + + tpm_result =3D be32_to_cpu(pss.u.resp.tpm_result); + if (tpm_result !=3D 0) { + error_report("tpm-emulator: Setting the stateblob (type %d) failed= " + "with a TPM error 0x%x", type, tpm_result); + return -1; + } + + trace_tpm_emulator_set_state_blob(type, tsb->size, flags); + + return 0; +} + +/* + * Set all the TPM state blobs. + * + * Returns a negative errno code in case of error. + */ +static int tpm_emulator_set_state_blobs(TPMBackend *tb) +{ + TPMEmulator *tpm_emu =3D TPM_EMULATOR(tb); + TPMBlobBuffers *state_blobs =3D &tpm_emu->state_blobs; + + trace_tpm_emulator_set_state_blobs(); + + if (tpm_emulator_stop_tpm(tb) < 0) { + trace_tpm_emulator_set_state_blobs_error("Could not stop TPM"); + return -EIO; + } + + if (tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_PERMANENT, + &state_blobs->permanent, + state_blobs->permanent_flags) < 0 || + tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_VOLATILE, + &state_blobs->volatil, + state_blobs->volatil_flags) < 0 || + tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_SAVESTATE, + &state_blobs->savestate, + state_blobs->savestate_flags) < 0) { + return -EBADMSG; + } + + trace_tpm_emulator_set_state_blobs_done(); + + return 0; +} + +static int tpm_emulator_pre_save(void *opaque) +{ + TPMBackend *tb =3D opaque; + TPMEmulator *tpm_emu =3D TPM_EMULATOR(tb); + + trace_tpm_emulator_pre_save(); + + tpm_backend_finish_sync(tb); + + /* get the state blobs from the TPM */ + return tpm_emulator_get_state_blobs(tpm_emu); +} + +/* + * Load the TPM state blobs into the TPM. + * + * Returns negative errno codes in case of error. + */ +static int tpm_emulator_post_load(void *opaque, int version_id) +{ + TPMBackend *tb =3D opaque; + int ret; + + ret =3D tpm_emulator_set_state_blobs(tb); + if (ret < 0) { + return ret; + } + + if (tpm_emulator_startup_tpm_resume(tb, 0, true) < 0) { + return -EIO; + } + + return 0; +} + +static const VMStateDescription vmstate_tpm_emulator =3D { + .name =3D "tpm-emulator", + .version_id =3D 1, + .pre_save =3D tpm_emulator_pre_save, + .post_load =3D tpm_emulator_post_load, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(state_blobs.permanent_flags, TPMEmulator), + VMSTATE_UINT32(state_blobs.permanent.size, TPMEmulator), + VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.permanent.buffer, + TPMEmulator, 1, 0, + state_blobs.permanent.size), + + VMSTATE_UINT32(state_blobs.volatil_flags, TPMEmulator), + VMSTATE_UINT32(state_blobs.volatil.size, TPMEmulator), + VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.volatil.buffer, + TPMEmulator, 1, 0, + state_blobs.volatil.size), + + VMSTATE_UINT32(state_blobs.savestate_flags, TPMEmulator), + VMSTATE_UINT32(state_blobs.savestate.size, TPMEmulator), + VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.savestate.buffer, + TPMEmulator, 1, 0, + state_blobs.savestate.size), + + VMSTATE_END_OF_LIST() + } +}; + static void tpm_emulator_inst_init(Object *obj) { TPMEmulator *tpm_emu =3D TPM_EMULATOR(obj); @@ -579,6 +871,8 @@ static void tpm_emulator_inst_init(Object *obj) tpm_emu->options =3D g_new0(TPMEmulatorOptions, 1); tpm_emu->cur_locty_number =3D ~0; qemu_mutex_init(&tpm_emu->mutex); + + vmstate_register(NULL, -1, &vmstate_tpm_emulator, obj); } =20 /* @@ -615,6 +909,8 @@ static void tpm_emulator_inst_finalize(Object *obj) } =20 qemu_mutex_destroy(&tpm_emu->mutex); + + vmstate_unregister(NULL, &vmstate_tpm_emulator, obj); } =20 static void tpm_emulator_class_init(ObjectClass *klass, void *data) diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events index 9a65384..c5bfbf1 100644 --- a/hw/tpm/trace-events +++ b/hw/tpm/trace-events @@ -20,13 +20,19 @@ tpm_emulator_set_locality(uint8_t locty) "setting local= ity to %d" tpm_emulator_handle_request(void) "processing TPM command" tpm_emulator_probe_caps(uint64_t caps) "capabilities: 0x%"PRIx64 tpm_emulator_set_buffer_size(uint32_t buffersize, uint32_t minsize, uint32= _t maxsize) "buffer size: %u, min: %u, max: %u" -tpm_emulator_startup_tpm(void) "startup" +tpm_emulator_startup_tpm_resume(bool is_resume, size_t buffersize) "is_res= ume: %d, buffer size: %zu" tpm_emulator_get_tpm_established_flag(uint8_t flag) "got established flag:= %d" tpm_emulator_cancel_cmd_not_supt(void) "Backend does not support CANCEL_TP= M_CMD" tpm_emulator_handle_device_opts_tpm12(void) "TPM Version 1.2" tpm_emulator_handle_device_opts_tpm2(void) "TPM Version 2" tpm_emulator_handle_device_opts_unspec(void) "TPM Version Unspecified" tpm_emulator_handle_device_opts_startup_error(void) "Startup error" +tpm_emulator_get_state_blob(uint8_t type, uint32_t size, uint32_t flags) "= got state blob type %d, %u bytes, flags 0x%08x" +tpm_emulator_set_state_blob(uint8_t type, uint32_t size, uint32_t flags) "= set state blob type %d, %u bytes, flags 0x%08x" +tpm_emulator_set_state_blobs(void) "setting state blobs" +tpm_emulator_set_state_blobs_error(const char *msg) "error while setting s= tate blobs: %s" +tpm_emulator_set_state_blobs_done(void) "Done setting state blobs" +tpm_emulator_pre_save(void) "" tpm_emulator_inst_init(void) "" =20 # hw/tpm/tpm_tis.c --=20 2.5.5 From nobody Sat May 18 10:30:01 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1521236922706272.6771208314226; Fri, 16 Mar 2018 14:48:42 -0700 (PDT) Received: from localhost ([::1]:59751 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ewxDN-00044g-Sh for importer@patchew.org; Fri, 16 Mar 2018 17:48:41 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36888) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ewxBb-00036F-9f for qemu-devel@nongnu.org; Fri, 16 Mar 2018 17:46:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ewxBY-0003YX-6Y for qemu-devel@nongnu.org; Fri, 16 Mar 2018 17:46:51 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:38984 helo=mx0a-001b2d01.pphosted.com) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ewxBY-0003YE-1E for qemu-devel@nongnu.org; Fri, 16 Mar 2018 17:46:48 -0400 Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w2GLitLc073939 for ; Fri, 16 Mar 2018 17:46:47 -0400 Received: from e35.co.us.ibm.com (e35.co.us.ibm.com [32.97.110.153]) by mx0a-001b2d01.pphosted.com with ESMTP id 2grhf09vv5-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Fri, 16 Mar 2018 17:46:47 -0400 Received: from localhost by e35.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 16 Mar 2018 15:46:45 -0600 Received: from b03cxnp08025.gho.boulder.ibm.com (9.17.130.17) by e35.co.us.ibm.com (192.168.1.135) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 16 Mar 2018 15:46:43 -0600 Received: from b03ledav002.gho.boulder.ibm.com (b03ledav002.gho.boulder.ibm.com [9.17.130.233]) by b03cxnp08025.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w2GLkgxS9896256; Fri, 16 Mar 2018 14:46:42 -0700 Received: from b03ledav002.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8855E13603C; Fri, 16 Mar 2018 15:46:42 -0600 (MDT) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b03ledav002.gho.boulder.ibm.com (Postfix) with ESMTP id 33C1613603A; Fri, 16 Mar 2018 15:46:42 -0600 (MDT) From: Stefan Berger To: qemu-devel@nongnu.org Date: Fri, 16 Mar 2018 17:46:34 -0400 X-Mailer: git-send-email 2.5.5 In-Reply-To: <1521236796-24551-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1521236796-24551-1-git-send-email-stefanb@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18031621-0012-0000-0000-000015E8EF46 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008687; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000254; SDB=6.01004051; UDB=6.00511034; IPR=6.00783340; MB=3.00020080; MTD=3.00000008; XFM=3.00000015; UTC=2018-03-16 21:46:44 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18031621-0013-0000-0000-000051E65099 Message-Id: <1521236796-24551-3-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-03-16_14:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1803160253 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.158.5 Subject: [Qemu-devel] [PATCH v5 for 2.13 2/4] tpm: extend TPM TIS with state migration support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: marcandre.lureau@gmail.com, dgilbert@redhat.com, Stefan Berger Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Extend the TPM TIS interface with state migration support. We need to synchronize with the backend thread to make sure that a command being processed by the external TPM emulator has completed and its response been received. Signed-off-by: Stefan Berger --- hw/tpm/tpm_tis.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++= +-- hw/tpm/trace-events | 1 + 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 2ac7e74..fec3d73 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -894,9 +894,57 @@ static void tpm_tis_reset(DeviceState *dev) tpm_backend_startup_tpm(s->be_driver, s->be_buffer_size); } =20 +/* persistent state handling */ + +static int tpm_tis_pre_save(void *opaque) +{ + TPMState *s =3D opaque; + uint8_t locty =3D s->active_locty; + + trace_tpm_tis_pre_save(locty, s->rw_offset); + + if (DEBUG_TIS) { + tpm_tis_dump_state(opaque, 0); + } + + /* + * Synchronize with backend completion. + */ + tpm_backend_finish_sync(s->be_driver); + + return 0; +} + +static const VMStateDescription vmstate_locty =3D { + .name =3D "tpm-tis/locty", + .version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(state, TPMLocality), + VMSTATE_UINT32(inte, TPMLocality), + VMSTATE_UINT32(ints, TPMLocality), + VMSTATE_UINT8(access, TPMLocality), + VMSTATE_UINT32(sts, TPMLocality), + VMSTATE_UINT32(iface_id, TPMLocality), + VMSTATE_END_OF_LIST(), + } +}; + static const VMStateDescription vmstate_tpm_tis =3D { - .name =3D "tpm", - .unmigratable =3D 1, + .name =3D "tpm-tis", + .version_id =3D 1, + .pre_save =3D tpm_tis_pre_save, + .fields =3D (VMStateField[]) { + VMSTATE_BUFFER(buffer, TPMState), + VMSTATE_UINT16(rw_offset, TPMState), + VMSTATE_UINT8(active_locty, TPMState), + VMSTATE_UINT8(aborting_locty, TPMState), + VMSTATE_UINT8(next_locty, TPMState), + + VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 1, + vmstate_locty, TPMLocality), + + VMSTATE_END_OF_LIST() + } }; =20 static Property tpm_tis_properties[] =3D { diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events index c5bfbf1..25bee0c 100644 --- a/hw/tpm/trace-events +++ b/hw/tpm/trace-events @@ -50,3 +50,4 @@ tpm_tis_mmio_write_locty_seized(uint8_t locty, uint8_t ac= tive) "Locality %d seiz tpm_tis_mmio_write_init_abort(void) "Initiating abort" tpm_tis_mmio_write_lowering_irq(void) "Lowering IRQ" tpm_tis_mmio_write_data2send(uint32_t value, unsigned size) "Data to send = to TPM: 0x%08x (size=3D%d)" +tpm_tis_pre_save(uint8_t locty, uint32_t rw_offset) "locty: %d, rw_offset = =3D %u" --=20 2.5.5 From nobody Sat May 18 10:30:01 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1521237073756821.3085616924832; Fri, 16 Mar 2018 14:51:13 -0700 (PDT) Received: from localhost ([::1]:59762 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ewxFL-0005hs-7w for importer@patchew.org; Fri, 16 Mar 2018 17:50:43 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36925) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ewxBc-00037E-Pr for qemu-devel@nongnu.org; Fri, 16 Mar 2018 17:46:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ewxBZ-0003a0-KF for qemu-devel@nongnu.org; Fri, 16 Mar 2018 17:46:52 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:32842) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ewxBZ-0003Z3-Bh for qemu-devel@nongnu.org; Fri, 16 Mar 2018 17:46:49 -0400 Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w2GLkMvW133785 for ; Fri, 16 Mar 2018 17:46:48 -0400 Received: from e38.co.us.ibm.com (e38.co.us.ibm.com [32.97.110.159]) by mx0a-001b2d01.pphosted.com with ESMTP id 2grmbnb7mb-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Fri, 16 Mar 2018 17:46:47 -0400 Received: from localhost by e38.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 16 Mar 2018 15:46:47 -0600 Received: from b03cxnp07028.gho.boulder.ibm.com (9.17.130.15) by e38.co.us.ibm.com (192.168.1.138) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 16 Mar 2018 15:46:44 -0600 Received: from b03ledav002.gho.boulder.ibm.com (b03ledav002.gho.boulder.ibm.com [9.17.130.233]) by b03cxnp07028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w2GLkinS12517722; Fri, 16 Mar 2018 14:46:44 -0700 Received: from b03ledav002.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 13CA913603C; Fri, 16 Mar 2018 15:46:44 -0600 (MDT) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b03ledav002.gho.boulder.ibm.com (Postfix) with ESMTP id A965013604B; Fri, 16 Mar 2018 15:46:43 -0600 (MDT) From: Stefan Berger To: qemu-devel@nongnu.org Date: Fri, 16 Mar 2018 17:46:35 -0400 X-Mailer: git-send-email 2.5.5 In-Reply-To: <1521236796-24551-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1521236796-24551-1-git-send-email-stefanb@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18031621-0028-0000-0000-0000094FEF1A X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008687; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000254; SDB=6.01004051; UDB=6.00511034; IPR=6.00783340; MB=3.00020079; MTD=3.00000008; XFM=3.00000015; UTC=2018-03-16 21:46:46 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18031621-0029-0000-0000-000039FEE1E2 Message-Id: <1521236796-24551-4-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-03-16_14:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1803160253 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.156.1 Subject: [Qemu-devel] [PATCH v5 for 2.13 3/4] docs: tpm: add VM save/restore example and troubleshooting guide X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: marcandre.lureau@gmail.com, dgilbert@redhat.com, Stefan Berger Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Extend the docs related to TPM with specs related to VM save and restore and a troubleshooting guide for TPM migration. Signed-off-by: Stefan Berger --- docs/specs/tpm.txt | 106 +++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 106 insertions(+) diff --git a/docs/specs/tpm.txt b/docs/specs/tpm.txt index d1d7157..c230c4c 100644 --- a/docs/specs/tpm.txt +++ b/docs/specs/tpm.txt @@ -200,3 +200,109 @@ crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0 PCR-00: 35 4E 3B CE 23 9F 38 59 ... ... PCR-23: 00 00 00 00 00 00 00 00 ... + + +=3D=3D=3D Migration with the TPM emulator =3D=3D=3D + +The TPM emulator supports the following types of virtual machine migration: + +- VM save / restore (migration into a file) +- Network migration +- Snapshotting (migration into storage like QoW2 or QED) + +The following command sequences can be used to test VM save / restore. + + +In a 1st terminal start an instance of a swtpm using the following command: + +mkdir /tmp/mytpm1 +swtpm socket --tpmstate dir=3D/tmp/mytpm1 \ + --ctrl type=3Dunixio,path=3D/tmp/mytpm1/swtpm-sock \ + --log level=3D20 --tpm2 + +In a 2nd terminal start the VM: + +qemu-system-x86_64 -display sdl -enable-kvm \ + -m 1024 -boot d -bios bios-256k.bin -boot menu=3Don \ + -chardev socket,id=3Dchrtpm,path=3D/tmp/mytpm1/swtpm-sock \ + -tpmdev emulator,id=3Dtpm0,chardev=3Dchrtpm \ + -device tpm-tis,tpmdev=3Dtpm0 \ + -monitor stdio \ + test.img + +Verify that the attached TPM is working as expected using applications ins= ide +the VM. + +To store the state of the VM use the following command in the QEMU monitor= in +the 2nd terminal: + +(qemu) migrate "exec:cat > testvm.bin" +(qemu) quit + +At this point a file called 'testvm.bin' should exists and the swtpm and Q= EMU +processes should have ended. + +To test 'VM restore' you have to start the swtpm with the same parameters +as before. If previously a TPM 2 [--tpm2] was saved, --tpm2 must now be +passed again on the command line. + +In the 1st terminal restart the swtpm with the same command line as before: + +swtpm socket --tpmstate dir=3D/tmp/mytpm1 \ + --ctrl type=3Dunixio,path=3D/tmp/mytpm1/swtpm-sock \ + --log level=3D20 --tpm2 + +In the 2nd terminal restore the state of the VM using the additonal +'-incoming' option. + +qemu-system-x86_64 -display sdl -enable-kvm \ + -m 1024 -boot d -bios bios-256k.bin -boot menu=3Don \ + -chardev socket,id=3Dchrtpm,path=3D/tmp/mytpm1/swtpm-sock \ + -tpmdev emulator,id=3Dtpm0,chardev=3Dchrtpm \ + -device tpm-tis,tpmdev=3Dtpm0 \ + -incoming "exec:cat < testvm.bin" \ + test.img + + +Troubleshooting migration: + +There are several reasons why migration may fail. In case of problems, +please ensure that the command lines adhere to the following rules and, +if possible, that identical versions of QEMU and swtpm are used at all +times. + +VM save and restore: + - QEMU command line parameters should be identical apart from the + '-incoming' option on VM restore + - swtpm command line parameters should be identical + +VM migration to 'localhost': + - QEMU command line parameters should be identical apart from the + '-incoming' option on the destination side + - swtpm command line parameters should point to two different + directories on the source and destination swtpm (--tpmstate dir=3D...) + (especially if different versions of libtpms were to be used on the + same machine). + +VM migration across the network: + - QEMU command line parameters should be identical apart from the + '-incoming' option on the destination side + - swtpm command line parameters should be identical + +VM Snapshotting: + - QEMU command line parameters should be identical + - swtpm command line parameters should be identical + + +Besides that, migration failure reasons on the swtpm level may include +the following: + + - the versions of the swtpm on the source and destination sides are + incompatible + - downgrading of TPM state may not be supported + - the source and destination libtpms were compiled with different + compile-time options and the destination side refuses to accept the + state + - different migration keys are used on the source and destination side + and the destination side cannot decrypt the migrated state + (swtpm ... --migration-key ... ) --=20 2.5.5 From nobody Sat May 18 10:30:01 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1521237048799522.4087681633825; Fri, 16 Mar 2018 14:50:48 -0700 (PDT) Received: from localhost ([::1]:59763 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ewxFM-0005jN-UZ for importer@patchew.org; Fri, 16 Mar 2018 17:50:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36936) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ewxBd-000382-H0 for qemu-devel@nongnu.org; Fri, 16 Mar 2018 17:46:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ewxBa-0003ax-Cz for qemu-devel@nongnu.org; Fri, 16 Mar 2018 17:46:53 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:48308 helo=mx0a-001b2d01.pphosted.com) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ewxBa-0003aY-6p for qemu-devel@nongnu.org; Fri, 16 Mar 2018 17:46:50 -0400 Received: from pps.filterd (m0098417.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w2GLiVOb095080 for ; Fri, 16 Mar 2018 17:46:49 -0400 Received: from e37.co.us.ibm.com (e37.co.us.ibm.com [32.97.110.158]) by mx0a-001b2d01.pphosted.com with ESMTP id 2grkejdj12-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Fri, 16 Mar 2018 17:46:48 -0400 Received: from localhost by e37.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 16 Mar 2018 15:46:48 -0600 Received: from b03cxnp08025.gho.boulder.ibm.com (9.17.130.17) by e37.co.us.ibm.com (192.168.1.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 16 Mar 2018 15:46:46 -0600 Received: from b03ledav002.gho.boulder.ibm.com (b03ledav002.gho.boulder.ibm.com [9.17.130.233]) by b03cxnp08025.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w2GLkjhN12452096; Fri, 16 Mar 2018 14:46:45 -0700 Received: from b03ledav002.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 95375136040; Fri, 16 Mar 2018 15:46:45 -0600 (MDT) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b03ledav002.gho.boulder.ibm.com (Postfix) with ESMTP id 2AC5C13603C; Fri, 16 Mar 2018 15:46:45 -0600 (MDT) From: Stefan Berger To: qemu-devel@nongnu.org Date: Fri, 16 Mar 2018 17:46:36 -0400 X-Mailer: git-send-email 2.5.5 In-Reply-To: <1521236796-24551-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1521236796-24551-1-git-send-email-stefanb@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18031621-0024-0000-0000-00001816F59D X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008687; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000254; SDB=6.01004051; UDB=6.00511034; IPR=6.00783340; MB=3.00020080; MTD=3.00000008; XFM=3.00000015; UTC=2018-03-16 21:46:47 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18031621-0025-0000-0000-00004F21ECFE Message-Id: <1521236796-24551-5-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-03-16_14:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1803160253 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.158.5 Subject: [Qemu-devel] [PATCH v5 for 2.13 4/4] tpm: Add test cases that uses the external swtpm with CRB interface X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: marcandre.lureau@gmail.com, dgilbert@redhat.com, Stefan Berger Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add a test program for testing the CRB with the external swtpm. The 1st test case extends a PCR and reads back the value and compares it against an expected return packet. The 2nd test case repeats the 1st test case and then migrates the external swtpm's state along with the VM state to a destination QEMU and swtpm and checks that the PCR has the expected value now. Signed-off-by: Stefan Berger --- tests/Makefile.include | 3 + tests/tpm-crb-swtpm-test.c | 243 +++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 246 insertions(+) create mode 100644 tests/tpm-crb-swtpm-test.c diff --git a/tests/Makefile.include b/tests/Makefile.include index 42fd426..bd4f56f 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -297,6 +297,7 @@ check-qtest-i386-$(CONFIG_VHOST_USER_NET_TEST_i386) += =3D tests/vhost-user-test$(EX ifeq ($(CONFIG_VHOST_USER_NET_TEST_i386),) check-qtest-x86_64-$(CONFIG_VHOST_USER_NET_TEST_x86_64) +=3D tests/vhost-u= ser-test$(EXESUF) endif +check-qtest-i386-$(CONFIG_TPM) +=3D tests/tpm-crb-swtpm-test$(EXESUF) check-qtest-i386-$(CONFIG_TPM) +=3D tests/tpm-crb-test$(EXESUF) check-qtest-i386-$(CONFIG_TPM) +=3D tests/tpm-tis-test$(EXESUF) check-qtest-i386-$(CONFIG_SLIRP) +=3D tests/test-netfilter$(EXESUF) @@ -719,6 +720,8 @@ tests/test-util-sockets$(EXESUF): tests/test-util-socke= ts.o \ tests/test-io-task$(EXESUF): tests/test-io-task.o $(test-io-obj-y) tests/test-io-channel-socket$(EXESUF): tests/test-io-channel-socket.o \ tests/io-channel-helpers.o tests/socket-helpers.o $(test-io-obj-y) +tests/tpm-crb-swtpm-test$(EXESUF): tests/tpm-crb-swtpm-test.o tests/tpm-em= u.o \ + tests/tpm-util.o $(test-io-obj-y) tests/tpm-crb-test$(EXESUF): tests/tpm-crb-test.o tests/tpm-emu.o $(test-i= o-obj-y) tests/tpm-tis-test$(EXESUF): tests/tpm-tis-test.o tests/tpm-emu.o $(test-i= o-obj-y) tests/test-io-channel-file$(EXESUF): tests/test-io-channel-file.o \ diff --git a/tests/tpm-crb-swtpm-test.c b/tests/tpm-crb-swtpm-test.c new file mode 100644 index 0000000..844d52d --- /dev/null +++ b/tests/tpm-crb-swtpm-test.c @@ -0,0 +1,243 @@ +/* + * QTest testcase for TPM CRB talking to external swtpm and swtpm migration + * + * Copyright (c) 2018 IBM Corporation + * with parts borrowed from migration-test.c that is: + * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Berger + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include + +#include "hw/acpi/tpm.h" +#include "io/channel-socket.h" +#include "libqtest.h" +#include "tpm-util.h" +#include "sysemu/tpm.h" +#include "qapi/qmp/qdict.h" + +typedef struct TestState { + char *src_tpm_path; + char *dst_tpm_path; + char *uri; +} TestState; + +bool got_stop; + +static void migrate(QTestState *who, const char *uri) +{ + QDict *rsp; + gchar *cmd; + + cmd =3D g_strdup_printf("{ 'execute': 'migrate'," + "'arguments': { 'uri': '%s' } }", + uri); + rsp =3D qtest_qmp(who, cmd); + g_free(cmd); + g_assert(qdict_haskey(rsp, "return")); + QDECREF(rsp); +} + +/* + * Events can get in the way of responses we are actually waiting for. + */ +static QDict *wait_command(QTestState *who, const char *command) +{ + const char *event_string; + QDict *response; + + response =3D qtest_qmp(who, command); + + while (qdict_haskey(response, "event")) { + /* OK, it was an event */ + event_string =3D qdict_get_str(response, "event"); + if (!strcmp(event_string, "STOP")) { + got_stop =3D true; + } + QDECREF(response); + response =3D qtest_qmp_receive(who); + } + return response; +} + +static void wait_for_migration_complete(QTestState *who) +{ + while (true) { + QDict *rsp, *rsp_return; + bool completed; + const char *status; + + rsp =3D wait_command(who, "{ 'execute': 'query-migrate' }"); + rsp_return =3D qdict_get_qdict(rsp, "return"); + status =3D qdict_get_str(rsp_return, "status"); + completed =3D strcmp(status, "completed") =3D=3D 0; + g_assert_cmpstr(status, !=3D, "failed"); + QDECREF(rsp); + if (completed) { + return; + } + usleep(1000); + } +} + +static void migration_start_qemu(QTestState **src_qemu, QTestState **dst_q= emu, + SocketAddress *src_tpm_addr, + SocketAddress *dst_tpm_addr, + const char *miguri) +{ + char *src_qemu_args, *dst_qemu_args; + + src_qemu_args =3D g_strdup_printf( + "-chardev socket,id=3Dchr,path=3D%s " + "-tpmdev emulator,id=3Ddev,chardev=3Dchr " + "-device tpm-crb,tpmdev=3Ddev ", + src_tpm_addr->u.q_unix.path); + + *src_qemu =3D qtest_init(src_qemu_args); + + dst_qemu_args =3D g_strdup_printf( + "-chardev socket,id=3Dchr,path=3D%s " + "-tpmdev emulator,id=3Ddev,chardev=3Dchr " + "-device tpm-crb,tpmdev=3Ddev " + "-incoming %s", + dst_tpm_addr->u.q_unix.path, + miguri); + + *dst_qemu =3D qtest_init(dst_qemu_args); + + free(src_qemu_args); + free(dst_qemu_args); +} +static void tpm_crb_swtpm_test(const void *data) +{ + char *args =3D NULL; + QTestState *s; + SocketAddress *addr =3D NULL; + gboolean succ; + GPid swtpm_pid; + GError *error =3D NULL; + const TestState *ts =3D data; + + succ =3D tpm_util_swtpm_start(ts->src_tpm_path, &swtpm_pid, &addr, &er= ror); + if (!succ) { + return; + } + + args =3D g_strdup_printf( + "-chardev socket,id=3Dchr,path=3D%s " + "-tpmdev emulator,id=3Ddev,chardev=3Dchr " + "-device tpm-crb,tpmdev=3Ddev", + addr->u.q_unix.path); + + s =3D qtest_start(args); + + tpm_util_startup(s, tpm_util_crb_transfer); + tpm_util_pcrextend(s, tpm_util_crb_transfer); + + unsigned char tpm_pcrread_resp[] =3D + "\x80\x01\x00\x00\x00\x3e\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00" + "\x00\x01\x00\x0b\x03\x00\x04\x00\x00\x00\x00\x01\x00\x20\xf6\x85" + "\x98\xe5\x86\x8d\xe6\x8b\x97\x29\x99\x60\xf2\x71\x7d\x17\x67\x89" + "\xa4\x2f\x9a\xae\xa8\xc7\xb7\xaa\x79\xa8\x62\x56\xc1\xde"; + tpm_util_pcrread(s, tpm_util_crb_transfer, tpm_pcrread_resp, + sizeof(tpm_pcrread_resp)); + + qtest_end(); + tpm_util_swtpm_kill(swtpm_pid); + + if (addr) { + g_unlink(addr->u.q_unix.path); + qapi_free_SocketAddress(addr); + } +} + +static void tpm_crb_swtpm_migration_test(const void *data) +{ + const TestState *ts =3D data; + gboolean succ; + GPid src_tpm_pid, dst_tpm_pid; + SocketAddress *src_tpm_addr =3D NULL, *dst_tpm_addr =3D NULL; + GError *error =3D NULL; + QTestState *src_qemu, *dst_qemu; + + succ =3D tpm_util_swtpm_start(ts->src_tpm_path, &src_tpm_pid, + &src_tpm_addr, &error); + g_assert_cmpint(succ, !=3D, false); + if (!succ) { + return; + } + + succ =3D tpm_util_swtpm_start(ts->dst_tpm_path, &dst_tpm_pid, + &dst_tpm_addr, &error); + g_assert_cmpint(succ, !=3D, false); + if (!succ) { + goto err_src_tpm_kill; + } + + migration_start_qemu(&src_qemu, &dst_qemu, src_tpm_addr, dst_tpm_addr, + ts->uri); + + tpm_util_startup(src_qemu, tpm_util_crb_transfer); + tpm_util_pcrextend(src_qemu, tpm_util_crb_transfer); + + unsigned char tpm_pcrread_resp[] =3D + "\x80\x01\x00\x00\x00\x3e\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00" + "\x00\x01\x00\x0b\x03\x00\x04\x00\x00\x00\x00\x01\x00\x20\xf6\x85" + "\x98\xe5\x86\x8d\xe6\x8b\x97\x29\x99\x60\xf2\x71\x7d\x17\x67\x89" + "\xa4\x2f\x9a\xae\xa8\xc7\xb7\xaa\x79\xa8\x62\x56\xc1\xde"; + tpm_util_pcrread(src_qemu, tpm_util_crb_transfer, tpm_pcrread_resp, + sizeof(tpm_pcrread_resp)); + + migrate(src_qemu, ts->uri); + wait_for_migration_complete(src_qemu); + + tpm_util_pcrread(dst_qemu, tpm_util_crb_transfer, tpm_pcrread_resp, + sizeof(tpm_pcrread_resp)); + + qtest_quit(dst_qemu); + qtest_quit(src_qemu); + + tpm_util_swtpm_kill(dst_tpm_pid); + if (dst_tpm_addr) { + g_unlink(dst_tpm_addr->u.q_unix.path); + qapi_free_SocketAddress(dst_tpm_addr); + } + +err_src_tpm_kill: + tpm_util_swtpm_kill(src_tpm_pid); + if (src_tpm_addr) { + g_unlink(src_tpm_addr->u.q_unix.path); + qapi_free_SocketAddress(src_tpm_addr); + } +} + +int main(int argc, char **argv) +{ + int ret; + TestState ts =3D { 0 }; + + ts.src_tpm_path =3D g_dir_make_tmp("qemu-tpm-crb-swtpm-test.XXXXXX", N= ULL); + ts.dst_tpm_path =3D g_dir_make_tmp("qemu-tpm-crb-swtpm-test.XXXXXX", N= ULL); + ts.uri =3D g_strdup_printf("unix:%s/migsocket", ts.src_tpm_path); + + module_call_init(MODULE_INIT_QOM); + g_test_init(&argc, &argv, NULL); + + qtest_add_data_func("/tpm/crb-swtpm/test", &ts, tpm_crb_swtpm_test); + qtest_add_data_func("/tpm/crb-swtpm-migration/test", &ts, + tpm_crb_swtpm_migration_test); + ret =3D g_test_run(); + + g_rmdir(ts.dst_tpm_path); + g_free(ts.dst_tpm_path); + g_rmdir(ts.src_tpm_path); + g_free(ts.src_tpm_path); + + return ret; +} --=20 2.5.5