1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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"
47
48#define TYPE_TPM_EMULATOR "tpm-emulator"
49OBJECT_DECLARE_SIMPLE_TYPE(TPMEmulator, TPM_EMULATOR)
50
51#define TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(S, cap) (((S)->caps & (cap)) == (cap))
52
53
54
55
56typedef struct TPMBlobBuffers {
57 uint32_t permanent_flags;
58 TPMSizedBuffer permanent;
59
60 uint32_t volatil_flags;
61 TPMSizedBuffer volatil;
62
63 uint32_t savestate_flags;
64 TPMSizedBuffer savestate;
65} TPMBlobBuffers;
66
67struct TPMEmulator {
68 TPMBackend parent;
69
70 TPMEmulatorOptions *options;
71 CharBackend ctrl_chr;
72 QIOChannel *data_ioc;
73 TPMVersion tpm_version;
74 ptm_cap caps;
75 uint8_t cur_locty_number;
76 Error *migration_blocker;
77
78 QemuMutex mutex;
79
80 unsigned int established_flag:1;
81 unsigned int established_flag_cached:1;
82
83 TPMBlobBuffers state_blobs;
84};
85
86struct tpm_error {
87 uint32_t tpm_result;
88 const char *string;
89};
90
91static const struct tpm_error tpm_errors[] = {
92
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
104 { TPM_RC_FAILURE , "operation failed" },
105 { TPM_RC_LOCALITY , "bad locality" },
106 { TPM_RC_INSUFFICIENT, "insufficient amount of data" },
107};
108
109static const char *tpm_emulator_strerror(uint32_t tpm_result)
110{
111 size_t i;
112
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;
116 }
117 }
118 return "";
119}
120
121static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg,
122 size_t msg_len_in, size_t msg_len_out)
123{
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;
128
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);
133
134 n = qemu_chr_fe_write_all(dev, buf, n);
135 if (n <= 0) {
136 return -1;
137 }
138
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;
143 }
144 }
145 }
146
147 return 0;
148}
149
150static 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)
155{
156 ssize_t ret;
157 bool is_selftest = false;
158
159 if (selftest_done) {
160 *selftest_done = false;
161 is_selftest = tpm_util_is_selftest(in, in_len);
162 }
163
164 ret = qio_channel_write_all(tpm_emu->data_ioc, (char *)in, in_len, errp);
165 if (ret != 0) {
166 return -1;
167 }
168
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;
173 }
174
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;
180 }
181
182 if (is_selftest) {
183 *selftest_done = tpm_cmd_get_errcode(out) == 0;
184 }
185
186 return 0;
187}
188
189static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number,
190 Error **errp)
191{
192 ptm_loc loc;
193
194 if (tpm_emu->cur_locty_number == locty_number) {
195 return 0;
196 }
197
198 trace_tpm_emulator_set_locality(locty_number);
199
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;
207 }
208
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;
214 }
215
216 tpm_emu->cur_locty_number = locty_number;
217
218 return 0;
219}
220
221static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
222 Error **errp)
223{
224 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
225
226 trace_tpm_emulator_handle_request();
227
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);
233 }
234}
235
236static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
237{
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;
242 }
243
244 tpm_emu->caps = be64_to_cpu(tpm_emu->caps);
245
246 trace_tpm_emulator_probe_caps(tpm_emu->caps);
247
248 return 0;
249}
250
251static int tpm_emulator_check_caps(TPMEmulator *tpm_emu)
252{
253 ptm_cap caps = 0;
254 const char *tpm = NULL;
255
256
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;
273 }
274
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;
279 }
280
281 return 0;
282}
283
284static int tpm_emulator_stop_tpm(TPMBackend *tb)
285{
286 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
287 ptm_res res;
288
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;
293 }
294
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;
300 }
301
302 return 0;
303}
304
305static int tpm_emulator_set_buffer_size(TPMBackend *tb,
306 size_t wanted_size,
307 size_t *actual_size)
308{
309 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
310 ptm_setbuffersize psbs;
311
312 if (tpm_emulator_stop_tpm(tb) < 0) {
313 return -1;
314 }
315
316 psbs.u.req.buffersize = cpu_to_be32(wanted_size);
317
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;
323 }
324
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;
331 }
332
333 if (actual_size) {
334 *actual_size = be32_to_cpu(psbs.u.resp.buffersize);
335 }
336
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));
341
342 return 0;
343}
344
345static int tpm_emulator_startup_tpm_resume(TPMBackend *tb, size_t buffersize,
346 bool is_resume)
347{
348 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
349 ptm_init init = {
350 .u.req.init_flags = 0,
351 };
352 ptm_res res;
353
354 trace_tpm_emulator_startup_tpm_resume(is_resume, buffersize);
355
356 if (buffersize != 0 &&
357 tpm_emulator_set_buffer_size(tb, buffersize, NULL) < 0) {
358 goto err_exit;
359 }
360
361 if (is_resume) {
362 init.u.req.init_flags |= cpu_to_be32(PTM_INIT_FLAG_DELETE_VOLATILE);
363 }
364
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;
370 }
371
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;
377 }
378 return 0;
379
380err_exit:
381 return -1;
382}
383
384static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize)
385{
386 return tpm_emulator_startup_tpm_resume(tb, buffersize, false);
387}
388
389static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb)
390{
391 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
392 ptm_est est;
393
394 if (tpm_emu->established_flag_cached) {
395 return tpm_emu->established_flag;
396 }
397
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;
403 }
404 trace_tpm_emulator_get_tpm_established_flag(est.u.resp.bit);
405
406 tpm_emu->established_flag_cached = 1;
407 tpm_emu->established_flag = (est.u.resp.bit != 0);
408
409 return tpm_emu->established_flag;
410}
411
412static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
413 uint8_t locty)
414{
415 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
416 ptm_reset_est reset_est;
417 ptm_res res;
418
419
420 if (tpm_emu->tpm_version != TPM_VERSION_2_0) {
421 return 0;
422 }
423
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;
431 }
432
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;
439 }
440
441 tpm_emu->established_flag_cached = 0;
442
443 return 0;
444}
445
446static void tpm_emulator_cancel_cmd(TPMBackend *tb)
447{
448 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
449 ptm_res res;
450
451 if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, PTM_CAP_CANCEL_TPM_CMD)) {
452 trace_tpm_emulator_cancel_cmd_not_supt();
453 return;
454 }
455
456
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));
464 }
465}
466
467static TPMVersion tpm_emulator_get_tpm_version(TPMBackend *tb)
468{
469 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
470
471 return tpm_emu->tpm_version;
472}
473
474static size_t tpm_emulator_get_buffer_size(TPMBackend *tb)
475{
476 size_t actual_size;
477
478 if (tpm_emulator_set_buffer_size(tb, 0, &actual_size) < 0) {
479 return 4096;
480 }
481
482 return actual_size;
483}
484
485static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)
486{
487 Error *err = NULL;
488 ptm_cap caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB |
489 PTM_CAP_STOP;
490
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;
499
500 return -1;
501 }
502 }
503
504 return 0;
505}
506
507static int tpm_emulator_prepare_data_fd(TPMEmulator *tpm_emu)
508{
509 ptm_res res;
510 Error *err = NULL;
511 int fds[2] = { -1, -1 };
512
513 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
514 error_report("tpm-emulator: Failed to create socketpair");
515 return -1;
516 }
517
518 qemu_chr_fe_set_msgfds(&tpm_emu->ctrl_chr, fds + 1, 1);
519
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;
525 }
526
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;
532 }
533
534 closesocket(fds[1]);
535
536 return 0;
537
538err_exit:
539 closesocket(fds[0]);
540 closesocket(fds[1]);
541 return -1;
542}
543
544static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts)
545{
546 const char *value;
547 Error *err = NULL;
548 Chardev *dev;
549
550 value = qemu_opt_get(opts, "chardev");
551 if (!value) {
552 error_report("tpm-emulator: parameter 'chardev' is missing");
553 goto err;
554 }
555
556 dev = qemu_chr_find(value);
557 if (!dev) {
558 error_report("tpm-emulator: tpm chardev '%s' not found", value);
559 goto err;
560 }
561
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;
567 }
568
569 tpm_emu->options->chardev = g_strdup(value);
570
571 if (tpm_emulator_prepare_data_fd(tpm_emu) < 0) {
572 goto err;
573 }
574
575
576
577
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;
583 }
584
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();
594 }
595
596 if (tpm_emulator_probe_caps(tpm_emu) ||
597 tpm_emulator_check_caps(tpm_emu)) {
598 goto err;
599 }
600
601 return tpm_emulator_block_migration(tpm_emu);
602
603err:
604 trace_tpm_emulator_handle_device_opts_startup_error();
605
606 return -1;
607}
608
609static TPMBackend *tpm_emulator_create(QemuOpts *opts)
610{
611 TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR));
612
613 if (tpm_emulator_handle_device_opts(TPM_EMULATOR(tb), opts)) {
614 object_unref(OBJECT(tb));
615 return NULL;
616 }
617
618 return tb;
619}
620
621static TpmTypeOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)
622{
623 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
624 TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
625
626 options->type = TPM_TYPE_EMULATOR;
627 options->u.emulator.data = QAPI_CLONE(TPMEmulatorOptions, tpm_emu->options);
628
629 return options;
630}
631
632static const QemuOptDesc tpm_emulator_cmdline_opts[] = {
633 TPM_STANDARD_CMDLINE_OPTS,
634 {
635 .name = "chardev",
636 .type = QEMU_OPT_STRING,
637 .help = "Character device to use for out-of-band control messages",
638 },
639 { },
640};
641
642
643
644
645
646
647
648
649
650static int tpm_emulator_get_state_blob(TPMEmulator *tpm_emu,
651 uint8_t type,
652 TPMSizedBuffer *tsb,
653 uint32_t *flags)
654{
655 ptm_getstate pgs;
656 ptm_res res;
657 ssize_t n;
658 uint32_t totlength, length;
659
660 tpm_sized_buffer_reset(tsb);
661
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;
665
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;
672 }
673
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;
680 }
681
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;
688 }
689
690 *flags = be32_to_cpu(pgs.u.resp.state_flags);
691
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;
698 }
699
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;
706 }
707 }
708 tsb->size = totlength;
709
710 trace_tpm_emulator_get_state_blob(type, tsb->size, *flags);
711
712 return 0;
713}
714
715static int tpm_emulator_get_state_blobs(TPMEmulator *tpm_emu)
716{
717 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
718
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;
729 }
730
731 return 0;
732
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);
737
738 return -1;
739}
740
741
742
743
744
745
746
747
748
749static int tpm_emulator_set_state_blob(TPMEmulator *tpm_emu,
750 uint32_t type,
751 TPMSizedBuffer *tsb,
752 uint32_t flags)
753{
754 ssize_t n;
755 ptm_setstate pss;
756 ptm_res tpm_result;
757
758 if (tsb->size == 0) {
759 return 0;
760 }
761
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),
766 };
767
768
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;
774 }
775
776
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;
783 }
784
785
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;
793 }
794
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;
801 }
802
803 trace_tpm_emulator_set_state_blob(type, tsb->size, flags);
804
805 return 0;
806}
807
808
809
810
811
812
813static int tpm_emulator_set_state_blobs(TPMBackend *tb)
814{
815 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
816 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
817
818 trace_tpm_emulator_set_state_blobs();
819
820 if (tpm_emulator_stop_tpm(tb) < 0) {
821 trace_tpm_emulator_set_state_blobs_error("Could not stop TPM");
822 return -EIO;
823 }
824
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;
835 }
836
837 trace_tpm_emulator_set_state_blobs_done();
838
839 return 0;
840}
841
842static int tpm_emulator_pre_save(void *opaque)
843{
844 TPMBackend *tb = opaque;
845 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
846
847 trace_tpm_emulator_pre_save();
848
849 tpm_backend_finish_sync(tb);
850
851
852 return tpm_emulator_get_state_blobs(tpm_emu);
853}
854
855
856
857
858
859
860static int tpm_emulator_post_load(void *opaque, int version_id)
861{
862 TPMBackend *tb = opaque;
863 int ret;
864
865 ret = tpm_emulator_set_state_blobs(tb);
866 if (ret < 0) {
867 return ret;
868 }
869
870 if (tpm_emulator_startup_tpm_resume(tb, 0, true) < 0) {
871 return -EIO;
872 }
873
874 return 0;
875}
876
877static 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),
888
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),
894
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),
900
901 VMSTATE_END_OF_LIST()
902 }
903};
904
905static void tpm_emulator_inst_init(Object *obj)
906{
907 TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
908
909 trace_tpm_emulator_inst_init();
910
911 tpm_emu->options = g_new0(TPMEmulatorOptions, 1);
912 tpm_emu->cur_locty_number = ~0;
913 qemu_mutex_init(&tpm_emu->mutex);
914
915 vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY,
916 &vmstate_tpm_emulator, obj);
917}
918
919
920
921
922static void tpm_emulator_shutdown(TPMEmulator *tpm_emu)
923{
924 ptm_res res;
925
926 if (!tpm_emu->options->chardev) {
927
928 return;
929 }
930
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)));
937 }
938}
939
940static void tpm_emulator_inst_finalize(Object *obj)
941{
942 TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
943 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
944
945 tpm_emulator_shutdown(tpm_emu);
946
947 object_unref(OBJECT(tpm_emu->data_ioc));
948
949 qemu_chr_fe_deinit(&tpm_emu->ctrl_chr, false);
950
951 qapi_free_TPMEmulatorOptions(tpm_emu->options);
952
953 if (tpm_emu->migration_blocker) {
954 migrate_del_blocker(tpm_emu->migration_blocker);
955 error_free(tpm_emu->migration_blocker);
956 }
957
958 tpm_sized_buffer_reset(&state_blobs->volatil);
959 tpm_sized_buffer_reset(&state_blobs->permanent);
960 tpm_sized_buffer_reset(&state_blobs->savestate);
961
962 qemu_mutex_destroy(&tpm_emu->mutex);
963
964 vmstate_unregister(NULL, &vmstate_tpm_emulator, obj);
965}
966
967static void tpm_emulator_class_init(ObjectClass *klass, void *data)
968{
969 TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
970
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;
982
983 tbc->handle_request = tpm_emulator_handle_request;
984}
985
986static 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,
993};
994
995static void tpm_emulator_register(void)
996{
997 type_register_static(&tpm_emulator_info);
998}
999
1000type_init(tpm_emulator_register)
1001