target/ppc: implement vclrrb
[qemu/rayw.git] / backends / tpm / tpm_emulator.c
blob87d061e9bbd61cb572dfb0aa2e1bb68aac04edf4
1 /*
2 * Emulator TPM driver
4 * Copyright (c) 2017 Intel Corporation
5 * Author: Amarnath Valluri <amarnath.valluri@intel.com>
7 * Copyright (c) 2010 - 2013, 2018 IBM Corporation
8 * Authors:
9 * Stefan Berger <stefanb@us.ibm.com>
11 * Copyright (C) 2011 IAIK, Graz University of Technology
12 * Author: Andreas Niederl
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, see <http://www.gnu.org/licenses/>
29 #include "qemu/osdep.h"
30 #include "qemu/error-report.h"
31 #include "qemu/module.h"
32 #include "qemu/sockets.h"
33 #include "qemu/lockable.h"
34 #include "io/channel-socket.h"
35 #include "sysemu/tpm_backend.h"
36 #include "sysemu/tpm_util.h"
37 #include "tpm_int.h"
38 #include "tpm_ioctl.h"
39 #include "migration/blocker.h"
40 #include "migration/vmstate.h"
41 #include "qapi/error.h"
42 #include "qapi/clone-visitor.h"
43 #include "qapi/qapi-visit-tpm.h"
44 #include "chardev/char-fe.h"
45 #include "trace.h"
46 #include "qom/object.h"
48 #define TYPE_TPM_EMULATOR "tpm-emulator"
49 OBJECT_DECLARE_SIMPLE_TYPE(TPMEmulator, TPM_EMULATOR)
51 #define TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(S, cap) (((S)->caps & (cap)) == (cap))
53 /* data structures */
55 /* blobs from the TPM; part of VM state when migrating */
56 typedef struct TPMBlobBuffers {
57 uint32_t permanent_flags;
58 TPMSizedBuffer permanent;
60 uint32_t volatil_flags;
61 TPMSizedBuffer volatil;
63 uint32_t savestate_flags;
64 TPMSizedBuffer savestate;
65 } TPMBlobBuffers;
67 struct TPMEmulator {
68 TPMBackend parent;
70 TPMEmulatorOptions *options;
71 CharBackend ctrl_chr;
72 QIOChannel *data_ioc;
73 TPMVersion tpm_version;
74 ptm_cap caps; /* capabilities of the TPM */
75 uint8_t cur_locty_number; /* last set locality */
76 Error *migration_blocker;
78 QemuMutex mutex;
80 unsigned int established_flag:1;
81 unsigned int established_flag_cached:1;
83 TPMBlobBuffers state_blobs;
86 struct tpm_error {
87 uint32_t tpm_result;
88 const char *string;
91 static const struct tpm_error tpm_errors[] = {
92 /* TPM 1.2 error codes */
93 { TPM_BAD_PARAMETER , "a parameter is bad" },
94 { TPM_FAIL , "operation failed" },
95 { TPM_KEYNOTFOUND , "key could not be found" },
96 { TPM_BAD_PARAM_SIZE , "bad parameter size"},
97 { TPM_ENCRYPT_ERROR , "encryption error" },
98 { TPM_DECRYPT_ERROR , "decryption error" },
99 { TPM_BAD_KEY_PROPERTY, "bad key property" },
100 { TPM_BAD_MODE , "bad (encryption) mode" },
101 { TPM_BAD_VERSION , "bad version identifier" },
102 { TPM_BAD_LOCALITY , "bad locality" },
103 /* TPM 2 error codes */
104 { TPM_RC_FAILURE , "operation failed" },
105 { TPM_RC_LOCALITY , "bad locality" },
106 { TPM_RC_INSUFFICIENT, "insufficient amount of data" },
109 static const char *tpm_emulator_strerror(uint32_t tpm_result)
111 size_t i;
113 for (i = 0; i < ARRAY_SIZE(tpm_errors); i++) {
114 if (tpm_errors[i].tpm_result == tpm_result) {
115 return tpm_errors[i].string;
118 return "";
121 static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg,
122 size_t msg_len_in, size_t msg_len_out)
124 CharBackend *dev = &tpm->ctrl_chr;
125 uint32_t cmd_no = cpu_to_be32(cmd);
126 ssize_t n = sizeof(uint32_t) + msg_len_in;
127 uint8_t *buf = NULL;
129 WITH_QEMU_LOCK_GUARD(&tpm->mutex) {
130 buf = g_alloca(n);
131 memcpy(buf, &cmd_no, sizeof(cmd_no));
132 memcpy(buf + sizeof(cmd_no), msg, msg_len_in);
134 n = qemu_chr_fe_write_all(dev, buf, n);
135 if (n <= 0) {
136 return -1;
139 if (msg_len_out != 0) {
140 n = qemu_chr_fe_read_all(dev, msg, msg_len_out);
141 if (n <= 0) {
142 return -1;
147 return 0;
150 static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_emu,
151 const uint8_t *in, uint32_t in_len,
152 uint8_t *out, uint32_t out_len,
153 bool *selftest_done,
154 Error **errp)
156 ssize_t ret;
157 bool is_selftest = false;
159 if (selftest_done) {
160 *selftest_done = false;
161 is_selftest = tpm_util_is_selftest(in, in_len);
164 ret = qio_channel_write_all(tpm_emu->data_ioc, (char *)in, in_len, errp);
165 if (ret != 0) {
166 return -1;
169 ret = qio_channel_read_all(tpm_emu->data_ioc, (char *)out,
170 sizeof(struct tpm_resp_hdr), errp);
171 if (ret != 0) {
172 return -1;
175 ret = qio_channel_read_all(tpm_emu->data_ioc,
176 (char *)out + sizeof(struct tpm_resp_hdr),
177 tpm_cmd_get_size(out) - sizeof(struct tpm_resp_hdr), errp);
178 if (ret != 0) {
179 return -1;
182 if (is_selftest) {
183 *selftest_done = tpm_cmd_get_errcode(out) == 0;
186 return 0;
189 static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number,
190 Error **errp)
192 ptm_loc loc;
194 if (tpm_emu->cur_locty_number == locty_number) {
195 return 0;
198 trace_tpm_emulator_set_locality(locty_number);
200 memset(&loc, 0, sizeof(loc));
201 loc.u.req.loc = locty_number;
202 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_LOCALITY, &loc,
203 sizeof(loc), sizeof(loc)) < 0) {
204 error_setg(errp, "tpm-emulator: could not set locality : %s",
205 strerror(errno));
206 return -1;
209 loc.u.resp.tpm_result = be32_to_cpu(loc.u.resp.tpm_result);
210 if (loc.u.resp.tpm_result != 0) {
211 error_setg(errp, "tpm-emulator: TPM result for set locality : 0x%x",
212 loc.u.resp.tpm_result);
213 return -1;
216 tpm_emu->cur_locty_number = locty_number;
218 return 0;
221 static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
222 Error **errp)
224 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
226 trace_tpm_emulator_handle_request();
228 if (tpm_emulator_set_locality(tpm_emu, cmd->locty, errp) < 0 ||
229 tpm_emulator_unix_tx_bufs(tpm_emu, cmd->in, cmd->in_len,
230 cmd->out, cmd->out_len,
231 &cmd->selftest_done, errp) < 0) {
232 tpm_util_write_fatal_error_response(cmd->out, cmd->out_len);
236 static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
238 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY,
239 &tpm_emu->caps, 0, sizeof(tpm_emu->caps)) < 0) {
240 error_report("tpm-emulator: probing failed : %s", strerror(errno));
241 return -1;
244 tpm_emu->caps = be64_to_cpu(tpm_emu->caps);
246 trace_tpm_emulator_probe_caps(tpm_emu->caps);
248 return 0;
251 static int tpm_emulator_check_caps(TPMEmulator *tpm_emu)
253 ptm_cap caps = 0;
254 const char *tpm = NULL;
256 /* check for min. required capabilities */
257 switch (tpm_emu->tpm_version) {
258 case TPM_VERSION_1_2:
259 caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
260 PTM_CAP_SET_LOCALITY | PTM_CAP_SET_DATAFD | PTM_CAP_STOP |
261 PTM_CAP_SET_BUFFERSIZE;
262 tpm = "1.2";
263 break;
264 case TPM_VERSION_2_0:
265 caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
266 PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED |
267 PTM_CAP_SET_DATAFD | PTM_CAP_STOP | PTM_CAP_SET_BUFFERSIZE;
268 tpm = "2";
269 break;
270 case TPM_VERSION_UNSPEC:
271 error_report("tpm-emulator: TPM version has not been set");
272 return -1;
275 if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) {
276 error_report("tpm-emulator: TPM does not implement minimum set of "
277 "required capabilities for TPM %s (0x%x)", tpm, (int)caps);
278 return -1;
281 return 0;
284 static int tpm_emulator_stop_tpm(TPMBackend *tb)
286 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
287 ptm_res res;
289 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0, sizeof(res)) < 0) {
290 error_report("tpm-emulator: Could not stop TPM: %s",
291 strerror(errno));
292 return -1;
295 res = be32_to_cpu(res);
296 if (res) {
297 error_report("tpm-emulator: TPM result for CMD_STOP: 0x%x %s", res,
298 tpm_emulator_strerror(res));
299 return -1;
302 return 0;
305 static int tpm_emulator_set_buffer_size(TPMBackend *tb,
306 size_t wanted_size,
307 size_t *actual_size)
309 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
310 ptm_setbuffersize psbs;
312 if (tpm_emulator_stop_tpm(tb) < 0) {
313 return -1;
316 psbs.u.req.buffersize = cpu_to_be32(wanted_size);
318 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_BUFFERSIZE, &psbs,
319 sizeof(psbs.u.req), sizeof(psbs.u.resp)) < 0) {
320 error_report("tpm-emulator: Could not set buffer size: %s",
321 strerror(errno));
322 return -1;
325 psbs.u.resp.tpm_result = be32_to_cpu(psbs.u.resp.tpm_result);
326 if (psbs.u.resp.tpm_result != 0) {
327 error_report("tpm-emulator: TPM result for set buffer size : 0x%x %s",
328 psbs.u.resp.tpm_result,
329 tpm_emulator_strerror(psbs.u.resp.tpm_result));
330 return -1;
333 if (actual_size) {
334 *actual_size = be32_to_cpu(psbs.u.resp.buffersize);
337 trace_tpm_emulator_set_buffer_size(
338 be32_to_cpu(psbs.u.resp.buffersize),
339 be32_to_cpu(psbs.u.resp.minsize),
340 be32_to_cpu(psbs.u.resp.maxsize));
342 return 0;
345 static int tpm_emulator_startup_tpm_resume(TPMBackend *tb, size_t buffersize,
346 bool is_resume)
348 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
349 ptm_init init = {
350 .u.req.init_flags = 0,
352 ptm_res res;
354 trace_tpm_emulator_startup_tpm_resume(is_resume, buffersize);
356 if (buffersize != 0 &&
357 tpm_emulator_set_buffer_size(tb, buffersize, NULL) < 0) {
358 goto err_exit;
361 if (is_resume) {
362 init.u.req.init_flags |= cpu_to_be32(PTM_INIT_FLAG_DELETE_VOLATILE);
365 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_INIT, &init, sizeof(init),
366 sizeof(init)) < 0) {
367 error_report("tpm-emulator: could not send INIT: %s",
368 strerror(errno));
369 goto err_exit;
372 res = be32_to_cpu(init.u.resp.tpm_result);
373 if (res) {
374 error_report("tpm-emulator: TPM result for CMD_INIT: 0x%x %s", res,
375 tpm_emulator_strerror(res));
376 goto err_exit;
378 return 0;
380 err_exit:
381 return -1;
384 static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize)
386 return tpm_emulator_startup_tpm_resume(tb, buffersize, false);
389 static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb)
391 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
392 ptm_est est;
394 if (tpm_emu->established_flag_cached) {
395 return tpm_emu->established_flag;
398 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_TPMESTABLISHED, &est,
399 0, sizeof(est)) < 0) {
400 error_report("tpm-emulator: Could not get the TPM established flag: %s",
401 strerror(errno));
402 return false;
404 trace_tpm_emulator_get_tpm_established_flag(est.u.resp.bit);
406 tpm_emu->established_flag_cached = 1;
407 tpm_emu->established_flag = (est.u.resp.bit != 0);
409 return tpm_emu->established_flag;
412 static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
413 uint8_t locty)
415 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
416 ptm_reset_est reset_est;
417 ptm_res res;
419 /* only a TPM 2.0 will support this */
420 if (tpm_emu->tpm_version != TPM_VERSION_2_0) {
421 return 0;
424 reset_est.u.req.loc = tpm_emu->cur_locty_number;
425 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_RESET_TPMESTABLISHED,
426 &reset_est, sizeof(reset_est),
427 sizeof(reset_est)) < 0) {
428 error_report("tpm-emulator: Could not reset the establishment bit: %s",
429 strerror(errno));
430 return -1;
433 res = be32_to_cpu(reset_est.u.resp.tpm_result);
434 if (res) {
435 error_report(
436 "tpm-emulator: TPM result for rest established flag: 0x%x %s",
437 res, tpm_emulator_strerror(res));
438 return -1;
441 tpm_emu->established_flag_cached = 0;
443 return 0;
446 static void tpm_emulator_cancel_cmd(TPMBackend *tb)
448 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
449 ptm_res res;
451 if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, PTM_CAP_CANCEL_TPM_CMD)) {
452 trace_tpm_emulator_cancel_cmd_not_supt();
453 return;
456 /* FIXME: make the function non-blocking, or it may block a VCPU */
457 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_CANCEL_TPM_CMD, &res, 0,
458 sizeof(res)) < 0) {
459 error_report("tpm-emulator: Could not cancel command: %s",
460 strerror(errno));
461 } else if (res != 0) {
462 error_report("tpm-emulator: Failed to cancel TPM: 0x%x",
463 be32_to_cpu(res));
467 static TPMVersion tpm_emulator_get_tpm_version(TPMBackend *tb)
469 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
471 return tpm_emu->tpm_version;
474 static size_t tpm_emulator_get_buffer_size(TPMBackend *tb)
476 size_t actual_size;
478 if (tpm_emulator_set_buffer_size(tb, 0, &actual_size) < 0) {
479 return 4096;
482 return actual_size;
485 static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)
487 Error *err = NULL;
488 ptm_cap caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB |
489 PTM_CAP_STOP;
491 if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) {
492 error_setg(&tpm_emu->migration_blocker,
493 "Migration disabled: TPM emulator does not support "
494 "migration");
495 if (migrate_add_blocker(tpm_emu->migration_blocker, &err) < 0) {
496 error_report_err(err);
497 error_free(tpm_emu->migration_blocker);
498 tpm_emu->migration_blocker = NULL;
500 return -1;
504 return 0;
507 static int tpm_emulator_prepare_data_fd(TPMEmulator *tpm_emu)
509 ptm_res res;
510 Error *err = NULL;
511 int fds[2] = { -1, -1 };
513 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
514 error_report("tpm-emulator: Failed to create socketpair");
515 return -1;
518 qemu_chr_fe_set_msgfds(&tpm_emu->ctrl_chr, fds + 1, 1);
520 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_DATAFD, &res, 0,
521 sizeof(res)) < 0 || res != 0) {
522 error_report("tpm-emulator: Failed to send CMD_SET_DATAFD: %s",
523 strerror(errno));
524 goto err_exit;
527 tpm_emu->data_ioc = QIO_CHANNEL(qio_channel_socket_new_fd(fds[0], &err));
528 if (err) {
529 error_prepend(&err, "tpm-emulator: Failed to create io channel: ");
530 error_report_err(err);
531 goto err_exit;
534 closesocket(fds[1]);
536 return 0;
538 err_exit:
539 closesocket(fds[0]);
540 closesocket(fds[1]);
541 return -1;
544 static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts)
546 const char *value;
547 Error *err = NULL;
548 Chardev *dev;
550 value = qemu_opt_get(opts, "chardev");
551 if (!value) {
552 error_report("tpm-emulator: parameter 'chardev' is missing");
553 goto err;
556 dev = qemu_chr_find(value);
557 if (!dev) {
558 error_report("tpm-emulator: tpm chardev '%s' not found", value);
559 goto err;
562 if (!qemu_chr_fe_init(&tpm_emu->ctrl_chr, dev, &err)) {
563 error_prepend(&err, "tpm-emulator: No valid chardev found at '%s':",
564 value);
565 error_report_err(err);
566 goto err;
569 tpm_emu->options->chardev = g_strdup(value);
571 if (tpm_emulator_prepare_data_fd(tpm_emu) < 0) {
572 goto err;
575 /* FIXME: tpm_util_test_tpmdev() accepts only on socket fd, as it also used
576 * by passthrough driver, which not yet using GIOChannel.
578 if (tpm_util_test_tpmdev(QIO_CHANNEL_SOCKET(tpm_emu->data_ioc)->fd,
579 &tpm_emu->tpm_version)) {
580 error_report("'%s' is not emulating TPM device. Error: %s",
581 tpm_emu->options->chardev, strerror(errno));
582 goto err;
585 switch (tpm_emu->tpm_version) {
586 case TPM_VERSION_1_2:
587 trace_tpm_emulator_handle_device_opts_tpm12();
588 break;
589 case TPM_VERSION_2_0:
590 trace_tpm_emulator_handle_device_opts_tpm2();
591 break;
592 default:
593 trace_tpm_emulator_handle_device_opts_unspec();
596 if (tpm_emulator_probe_caps(tpm_emu) ||
597 tpm_emulator_check_caps(tpm_emu)) {
598 goto err;
601 return tpm_emulator_block_migration(tpm_emu);
603 err:
604 trace_tpm_emulator_handle_device_opts_startup_error();
606 return -1;
609 static TPMBackend *tpm_emulator_create(QemuOpts *opts)
611 TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR));
613 if (tpm_emulator_handle_device_opts(TPM_EMULATOR(tb), opts)) {
614 object_unref(OBJECT(tb));
615 return NULL;
618 return tb;
621 static TpmTypeOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)
623 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
624 TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
626 options->type = TPM_TYPE_EMULATOR;
627 options->u.emulator.data = QAPI_CLONE(TPMEmulatorOptions, tpm_emu->options);
629 return options;
632 static const QemuOptDesc tpm_emulator_cmdline_opts[] = {
633 TPM_STANDARD_CMDLINE_OPTS,
635 .name = "chardev",
636 .type = QEMU_OPT_STRING,
637 .help = "Character device to use for out-of-band control messages",
639 { /* end of list */ },
643 * Transfer a TPM state blob from the TPM into a provided buffer.
645 * @tpm_emu: TPMEmulator
646 * @type: the type of blob to transfer
647 * @tsb: the TPMSizeBuffer to fill with the blob
648 * @flags: the flags to return to the caller
650 static int tpm_emulator_get_state_blob(TPMEmulator *tpm_emu,
651 uint8_t type,
652 TPMSizedBuffer *tsb,
653 uint32_t *flags)
655 ptm_getstate pgs;
656 ptm_res res;
657 ssize_t n;
658 uint32_t totlength, length;
660 tpm_sized_buffer_reset(tsb);
662 pgs.u.req.state_flags = cpu_to_be32(PTM_STATE_FLAG_DECRYPTED);
663 pgs.u.req.type = cpu_to_be32(type);
664 pgs.u.req.offset = 0;
666 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_STATEBLOB,
667 &pgs, sizeof(pgs.u.req),
668 offsetof(ptm_getstate, u.resp.data)) < 0) {
669 error_report("tpm-emulator: could not get state blob type %d : %s",
670 type, strerror(errno));
671 return -1;
674 res = be32_to_cpu(pgs.u.resp.tpm_result);
675 if (res != 0 && (res & 0x800) == 0) {
676 error_report("tpm-emulator: Getting the stateblob (type %d) failed "
677 "with a TPM error 0x%x %s", type, res,
678 tpm_emulator_strerror(res));
679 return -1;
682 totlength = be32_to_cpu(pgs.u.resp.totlength);
683 length = be32_to_cpu(pgs.u.resp.length);
684 if (totlength != length) {
685 error_report("tpm-emulator: Expecting to read %u bytes "
686 "but would get %u", totlength, length);
687 return -1;
690 *flags = be32_to_cpu(pgs.u.resp.state_flags);
692 if (totlength > 0) {
693 tsb->buffer = g_try_malloc(totlength);
694 if (!tsb->buffer) {
695 error_report("tpm-emulator: Out of memory allocating %u bytes",
696 totlength);
697 return -1;
700 n = qemu_chr_fe_read_all(&tpm_emu->ctrl_chr, tsb->buffer, totlength);
701 if (n != totlength) {
702 error_report("tpm-emulator: Could not read stateblob (type %d); "
703 "expected %u bytes, got %zd",
704 type, totlength, n);
705 return -1;
708 tsb->size = totlength;
710 trace_tpm_emulator_get_state_blob(type, tsb->size, *flags);
712 return 0;
715 static int tpm_emulator_get_state_blobs(TPMEmulator *tpm_emu)
717 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
719 if (tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_PERMANENT,
720 &state_blobs->permanent,
721 &state_blobs->permanent_flags) < 0 ||
722 tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_VOLATILE,
723 &state_blobs->volatil,
724 &state_blobs->volatil_flags) < 0 ||
725 tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_SAVESTATE,
726 &state_blobs->savestate,
727 &state_blobs->savestate_flags) < 0) {
728 goto err_exit;
731 return 0;
733 err_exit:
734 tpm_sized_buffer_reset(&state_blobs->volatil);
735 tpm_sized_buffer_reset(&state_blobs->permanent);
736 tpm_sized_buffer_reset(&state_blobs->savestate);
738 return -1;
742 * Transfer a TPM state blob to the TPM emulator.
744 * @tpm_emu: TPMEmulator
745 * @type: the type of TPM state blob to transfer
746 * @tsb: TPMSizedBuffer containing the TPM state blob
747 * @flags: Flags describing the (encryption) state of the TPM state blob
749 static int tpm_emulator_set_state_blob(TPMEmulator *tpm_emu,
750 uint32_t type,
751 TPMSizedBuffer *tsb,
752 uint32_t flags)
754 ssize_t n;
755 ptm_setstate pss;
756 ptm_res tpm_result;
758 if (tsb->size == 0) {
759 return 0;
762 pss = (ptm_setstate) {
763 .u.req.state_flags = cpu_to_be32(flags),
764 .u.req.type = cpu_to_be32(type),
765 .u.req.length = cpu_to_be32(tsb->size),
768 /* write the header only */
769 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_STATEBLOB, &pss,
770 offsetof(ptm_setstate, u.req.data), 0) < 0) {
771 error_report("tpm-emulator: could not set state blob type %d : %s",
772 type, strerror(errno));
773 return -1;
776 /* now the body */
777 n = qemu_chr_fe_write_all(&tpm_emu->ctrl_chr, tsb->buffer, tsb->size);
778 if (n != tsb->size) {
779 error_report("tpm-emulator: Writing the stateblob (type %d) "
780 "failed; could not write %u bytes, but only %zd",
781 type, tsb->size, n);
782 return -1;
785 /* now get the result */
786 n = qemu_chr_fe_read_all(&tpm_emu->ctrl_chr,
787 (uint8_t *)&pss, sizeof(pss.u.resp));
788 if (n != sizeof(pss.u.resp)) {
789 error_report("tpm-emulator: Reading response from writing stateblob "
790 "(type %d) failed; expected %zu bytes, got %zd", type,
791 sizeof(pss.u.resp), n);
792 return -1;
795 tpm_result = be32_to_cpu(pss.u.resp.tpm_result);
796 if (tpm_result != 0) {
797 error_report("tpm-emulator: Setting the stateblob (type %d) failed "
798 "with a TPM error 0x%x %s", type, tpm_result,
799 tpm_emulator_strerror(tpm_result));
800 return -1;
803 trace_tpm_emulator_set_state_blob(type, tsb->size, flags);
805 return 0;
809 * Set all the TPM state blobs.
811 * Returns a negative errno code in case of error.
813 static int tpm_emulator_set_state_blobs(TPMBackend *tb)
815 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
816 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
818 trace_tpm_emulator_set_state_blobs();
820 if (tpm_emulator_stop_tpm(tb) < 0) {
821 trace_tpm_emulator_set_state_blobs_error("Could not stop TPM");
822 return -EIO;
825 if (tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_PERMANENT,
826 &state_blobs->permanent,
827 state_blobs->permanent_flags) < 0 ||
828 tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_VOLATILE,
829 &state_blobs->volatil,
830 state_blobs->volatil_flags) < 0 ||
831 tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_SAVESTATE,
832 &state_blobs->savestate,
833 state_blobs->savestate_flags) < 0) {
834 return -EIO;
837 trace_tpm_emulator_set_state_blobs_done();
839 return 0;
842 static int tpm_emulator_pre_save(void *opaque)
844 TPMBackend *tb = opaque;
845 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
847 trace_tpm_emulator_pre_save();
849 tpm_backend_finish_sync(tb);
851 /* get the state blobs from the TPM */
852 return tpm_emulator_get_state_blobs(tpm_emu);
856 * Load the TPM state blobs into the TPM.
858 * Returns negative errno codes in case of error.
860 static int tpm_emulator_post_load(void *opaque, int version_id)
862 TPMBackend *tb = opaque;
863 int ret;
865 ret = tpm_emulator_set_state_blobs(tb);
866 if (ret < 0) {
867 return ret;
870 if (tpm_emulator_startup_tpm_resume(tb, 0, true) < 0) {
871 return -EIO;
874 return 0;
877 static const VMStateDescription vmstate_tpm_emulator = {
878 .name = "tpm-emulator",
879 .version_id = 0,
880 .pre_save = tpm_emulator_pre_save,
881 .post_load = tpm_emulator_post_load,
882 .fields = (VMStateField[]) {
883 VMSTATE_UINT32(state_blobs.permanent_flags, TPMEmulator),
884 VMSTATE_UINT32(state_blobs.permanent.size, TPMEmulator),
885 VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.permanent.buffer,
886 TPMEmulator, 0, 0,
887 state_blobs.permanent.size),
889 VMSTATE_UINT32(state_blobs.volatil_flags, TPMEmulator),
890 VMSTATE_UINT32(state_blobs.volatil.size, TPMEmulator),
891 VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.volatil.buffer,
892 TPMEmulator, 0, 0,
893 state_blobs.volatil.size),
895 VMSTATE_UINT32(state_blobs.savestate_flags, TPMEmulator),
896 VMSTATE_UINT32(state_blobs.savestate.size, TPMEmulator),
897 VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.savestate.buffer,
898 TPMEmulator, 0, 0,
899 state_blobs.savestate.size),
901 VMSTATE_END_OF_LIST()
905 static void tpm_emulator_inst_init(Object *obj)
907 TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
909 trace_tpm_emulator_inst_init();
911 tpm_emu->options = g_new0(TPMEmulatorOptions, 1);
912 tpm_emu->cur_locty_number = ~0;
913 qemu_mutex_init(&tpm_emu->mutex);
915 vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY,
916 &vmstate_tpm_emulator, obj);
920 * Gracefully shut down the external TPM
922 static void tpm_emulator_shutdown(TPMEmulator *tpm_emu)
924 ptm_res res;
926 if (!tpm_emu->options->chardev) {
927 /* was never properly initialized */
928 return;
931 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SHUTDOWN, &res, 0, sizeof(res)) < 0) {
932 error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s",
933 strerror(errno));
934 } else if (res != 0) {
935 error_report("tpm-emulator: TPM result for shutdown: 0x%x %s",
936 be32_to_cpu(res), tpm_emulator_strerror(be32_to_cpu(res)));
940 static void tpm_emulator_inst_finalize(Object *obj)
942 TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
943 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
945 tpm_emulator_shutdown(tpm_emu);
947 object_unref(OBJECT(tpm_emu->data_ioc));
949 qemu_chr_fe_deinit(&tpm_emu->ctrl_chr, false);
951 qapi_free_TPMEmulatorOptions(tpm_emu->options);
953 if (tpm_emu->migration_blocker) {
954 migrate_del_blocker(tpm_emu->migration_blocker);
955 error_free(tpm_emu->migration_blocker);
958 tpm_sized_buffer_reset(&state_blobs->volatil);
959 tpm_sized_buffer_reset(&state_blobs->permanent);
960 tpm_sized_buffer_reset(&state_blobs->savestate);
962 qemu_mutex_destroy(&tpm_emu->mutex);
964 vmstate_unregister(NULL, &vmstate_tpm_emulator, obj);
967 static void tpm_emulator_class_init(ObjectClass *klass, void *data)
969 TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
971 tbc->type = TPM_TYPE_EMULATOR;
972 tbc->opts = tpm_emulator_cmdline_opts;
973 tbc->desc = "TPM emulator backend driver";
974 tbc->create = tpm_emulator_create;
975 tbc->startup_tpm = tpm_emulator_startup_tpm;
976 tbc->cancel_cmd = tpm_emulator_cancel_cmd;
977 tbc->get_tpm_established_flag = tpm_emulator_get_tpm_established_flag;
978 tbc->reset_tpm_established_flag = tpm_emulator_reset_tpm_established_flag;
979 tbc->get_tpm_version = tpm_emulator_get_tpm_version;
980 tbc->get_buffer_size = tpm_emulator_get_buffer_size;
981 tbc->get_tpm_options = tpm_emulator_get_tpm_options;
983 tbc->handle_request = tpm_emulator_handle_request;
986 static const TypeInfo tpm_emulator_info = {
987 .name = TYPE_TPM_EMULATOR,
988 .parent = TYPE_TPM_BACKEND,
989 .instance_size = sizeof(TPMEmulator),
990 .class_init = tpm_emulator_class_init,
991 .instance_init = tpm_emulator_inst_init,
992 .instance_finalize = tpm_emulator_inst_finalize,
995 static void tpm_emulator_register(void)
997 type_register_static(&tpm_emulator_info);
1000 type_init(tpm_emulator_register)