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 migrate_add_blocker(tpm_emu->migration_blocker, &err);
496 if (err) {
497 error_report_err(err);
498 error_free(tpm_emu->migration_blocker);
499 tpm_emu->migration_blocker = NULL;
500
501 return -1;
502 }
503 }
504
505 return 0;
506}
507
508static int tpm_emulator_prepare_data_fd(TPMEmulator *tpm_emu)
509{
510 ptm_res res;
511 Error *err = NULL;
512 int fds[2] = { -1, -1 };
513
514 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
515 error_report("tpm-emulator: Failed to create socketpair");
516 return -1;
517 }
518
519 qemu_chr_fe_set_msgfds(&tpm_emu->ctrl_chr, fds + 1, 1);
520
521 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_DATAFD, &res, 0,
522 sizeof(res)) < 0 || res != 0) {
523 error_report("tpm-emulator: Failed to send CMD_SET_DATAFD: %s",
524 strerror(errno));
525 goto err_exit;
526 }
527
528 tpm_emu->data_ioc = QIO_CHANNEL(qio_channel_socket_new_fd(fds[0], &err));
529 if (err) {
530 error_prepend(&err, "tpm-emulator: Failed to create io channel: ");
531 error_report_err(err);
532 goto err_exit;
533 }
534
535 closesocket(fds[1]);
536
537 return 0;
538
539err_exit:
540 closesocket(fds[0]);
541 closesocket(fds[1]);
542 return -1;
543}
544
545static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts)
546{
547 const char *value;
548 Error *err = NULL;
549 Chardev *dev;
550
551 value = qemu_opt_get(opts, "chardev");
552 if (!value) {
553 error_report("tpm-emulator: parameter 'chardev' is missing");
554 goto err;
555 }
556
557 dev = qemu_chr_find(value);
558 if (!dev) {
559 error_report("tpm-emulator: tpm chardev '%s' not found", value);
560 goto err;
561 }
562
563 if (!qemu_chr_fe_init(&tpm_emu->ctrl_chr, dev, &err)) {
564 error_prepend(&err, "tpm-emulator: No valid chardev found at '%s':",
565 value);
566 error_report_err(err);
567 goto err;
568 }
569
570 tpm_emu->options->chardev = g_strdup(value);
571
572 if (tpm_emulator_prepare_data_fd(tpm_emu) < 0) {
573 goto err;
574 }
575
576
577
578
579 if (tpm_util_test_tpmdev(QIO_CHANNEL_SOCKET(tpm_emu->data_ioc)->fd,
580 &tpm_emu->tpm_version)) {
581 error_report("'%s' is not emulating TPM device. Error: %s",
582 tpm_emu->options->chardev, strerror(errno));
583 goto err;
584 }
585
586 switch (tpm_emu->tpm_version) {
587 case TPM_VERSION_1_2:
588 trace_tpm_emulator_handle_device_opts_tpm12();
589 break;
590 case TPM_VERSION_2_0:
591 trace_tpm_emulator_handle_device_opts_tpm2();
592 break;
593 default:
594 trace_tpm_emulator_handle_device_opts_unspec();
595 }
596
597 if (tpm_emulator_probe_caps(tpm_emu) ||
598 tpm_emulator_check_caps(tpm_emu)) {
599 goto err;
600 }
601
602 return tpm_emulator_block_migration(tpm_emu);
603
604err:
605 trace_tpm_emulator_handle_device_opts_startup_error();
606
607 return -1;
608}
609
610static TPMBackend *tpm_emulator_create(QemuOpts *opts)
611{
612 TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR));
613
614 if (tpm_emulator_handle_device_opts(TPM_EMULATOR(tb), opts)) {
615 object_unref(OBJECT(tb));
616 return NULL;
617 }
618
619 return tb;
620}
621
622static TpmTypeOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)
623{
624 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
625 TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
626
627 options->type = TPM_TYPE_OPTIONS_KIND_EMULATOR;
628 options->u.emulator.data = QAPI_CLONE(TPMEmulatorOptions, tpm_emu->options);
629
630 return options;
631}
632
633static const QemuOptDesc tpm_emulator_cmdline_opts[] = {
634 TPM_STANDARD_CMDLINE_OPTS,
635 {
636 .name = "chardev",
637 .type = QEMU_OPT_STRING,
638 .help = "Character device to use for out-of-band control messages",
639 },
640 { },
641};
642
643
644
645
646
647
648
649
650
651static int tpm_emulator_get_state_blob(TPMEmulator *tpm_emu,
652 uint8_t type,
653 TPMSizedBuffer *tsb,
654 uint32_t *flags)
655{
656 ptm_getstate pgs;
657 ptm_res res;
658 ssize_t n;
659 uint32_t totlength, length;
660
661 tpm_sized_buffer_reset(tsb);
662
663 pgs.u.req.state_flags = cpu_to_be32(PTM_STATE_FLAG_DECRYPTED);
664 pgs.u.req.type = cpu_to_be32(type);
665 pgs.u.req.offset = 0;
666
667 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_STATEBLOB,
668 &pgs, sizeof(pgs.u.req),
669 offsetof(ptm_getstate, u.resp.data)) < 0) {
670 error_report("tpm-emulator: could not get state blob type %d : %s",
671 type, strerror(errno));
672 return -1;
673 }
674
675 res = be32_to_cpu(pgs.u.resp.tpm_result);
676 if (res != 0 && (res & 0x800) == 0) {
677 error_report("tpm-emulator: Getting the stateblob (type %d) failed "
678 "with a TPM error 0x%x %s", type, res,
679 tpm_emulator_strerror(res));
680 return -1;
681 }
682
683 totlength = be32_to_cpu(pgs.u.resp.totlength);
684 length = be32_to_cpu(pgs.u.resp.length);
685 if (totlength != length) {
686 error_report("tpm-emulator: Expecting to read %u bytes "
687 "but would get %u", totlength, length);
688 return -1;
689 }
690
691 *flags = be32_to_cpu(pgs.u.resp.state_flags);
692
693 if (totlength > 0) {
694 tsb->buffer = g_try_malloc(totlength);
695 if (!tsb->buffer) {
696 error_report("tpm-emulator: Out of memory allocating %u bytes",
697 totlength);
698 return -1;
699 }
700
701 n = qemu_chr_fe_read_all(&tpm_emu->ctrl_chr, tsb->buffer, totlength);
702 if (n != totlength) {
703 error_report("tpm-emulator: Could not read stateblob (type %d); "
704 "expected %u bytes, got %zd",
705 type, totlength, n);
706 return -1;
707 }
708 }
709 tsb->size = totlength;
710
711 trace_tpm_emulator_get_state_blob(type, tsb->size, *flags);
712
713 return 0;
714}
715
716static int tpm_emulator_get_state_blobs(TPMEmulator *tpm_emu)
717{
718 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
719
720 if (tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_PERMANENT,
721 &state_blobs->permanent,
722 &state_blobs->permanent_flags) < 0 ||
723 tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_VOLATILE,
724 &state_blobs->volatil,
725 &state_blobs->volatil_flags) < 0 ||
726 tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_SAVESTATE,
727 &state_blobs->savestate,
728 &state_blobs->savestate_flags) < 0) {
729 goto err_exit;
730 }
731
732 return 0;
733
734 err_exit:
735 tpm_sized_buffer_reset(&state_blobs->volatil);
736 tpm_sized_buffer_reset(&state_blobs->permanent);
737 tpm_sized_buffer_reset(&state_blobs->savestate);
738
739 return -1;
740}
741
742
743
744
745
746
747
748
749
750static int tpm_emulator_set_state_blob(TPMEmulator *tpm_emu,
751 uint32_t type,
752 TPMSizedBuffer *tsb,
753 uint32_t flags)
754{
755 ssize_t n;
756 ptm_setstate pss;
757 ptm_res tpm_result;
758
759 if (tsb->size == 0) {
760 return 0;
761 }
762
763 pss = (ptm_setstate) {
764 .u.req.state_flags = cpu_to_be32(flags),
765 .u.req.type = cpu_to_be32(type),
766 .u.req.length = cpu_to_be32(tsb->size),
767 };
768
769
770 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_STATEBLOB, &pss,
771 offsetof(ptm_setstate, u.req.data), 0) < 0) {
772 error_report("tpm-emulator: could not set state blob type %d : %s",
773 type, strerror(errno));
774 return -1;
775 }
776
777
778 n = qemu_chr_fe_write_all(&tpm_emu->ctrl_chr, tsb->buffer, tsb->size);
779 if (n != tsb->size) {
780 error_report("tpm-emulator: Writing the stateblob (type %d) "
781 "failed; could not write %u bytes, but only %zd",
782 type, tsb->size, n);
783 return -1;
784 }
785
786
787 n = qemu_chr_fe_read_all(&tpm_emu->ctrl_chr,
788 (uint8_t *)&pss, sizeof(pss.u.resp));
789 if (n != sizeof(pss.u.resp)) {
790 error_report("tpm-emulator: Reading response from writing stateblob "
791 "(type %d) failed; expected %zu bytes, got %zd", type,
792 sizeof(pss.u.resp), n);
793 return -1;
794 }
795
796 tpm_result = be32_to_cpu(pss.u.resp.tpm_result);
797 if (tpm_result != 0) {
798 error_report("tpm-emulator: Setting the stateblob (type %d) failed "
799 "with a TPM error 0x%x %s", type, tpm_result,
800 tpm_emulator_strerror(tpm_result));
801 return -1;
802 }
803
804 trace_tpm_emulator_set_state_blob(type, tsb->size, flags);
805
806 return 0;
807}
808
809
810
811
812
813
814static int tpm_emulator_set_state_blobs(TPMBackend *tb)
815{
816 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
817 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
818
819 trace_tpm_emulator_set_state_blobs();
820
821 if (tpm_emulator_stop_tpm(tb) < 0) {
822 trace_tpm_emulator_set_state_blobs_error("Could not stop TPM");
823 return -EIO;
824 }
825
826 if (tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_PERMANENT,
827 &state_blobs->permanent,
828 state_blobs->permanent_flags) < 0 ||
829 tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_VOLATILE,
830 &state_blobs->volatil,
831 state_blobs->volatil_flags) < 0 ||
832 tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_SAVESTATE,
833 &state_blobs->savestate,
834 state_blobs->savestate_flags) < 0) {
835 return -EIO;
836 }
837
838 trace_tpm_emulator_set_state_blobs_done();
839
840 return 0;
841}
842
843static int tpm_emulator_pre_save(void *opaque)
844{
845 TPMBackend *tb = opaque;
846 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
847
848 trace_tpm_emulator_pre_save();
849
850 tpm_backend_finish_sync(tb);
851
852
853 return tpm_emulator_get_state_blobs(tpm_emu);
854}
855
856
857
858
859
860
861static int tpm_emulator_post_load(void *opaque, int version_id)
862{
863 TPMBackend *tb = opaque;
864 int ret;
865
866 ret = tpm_emulator_set_state_blobs(tb);
867 if (ret < 0) {
868 return ret;
869 }
870
871 if (tpm_emulator_startup_tpm_resume(tb, 0, true) < 0) {
872 return -EIO;
873 }
874
875 return 0;
876}
877
878static const VMStateDescription vmstate_tpm_emulator = {
879 .name = "tpm-emulator",
880 .version_id = 0,
881 .pre_save = tpm_emulator_pre_save,
882 .post_load = tpm_emulator_post_load,
883 .fields = (VMStateField[]) {
884 VMSTATE_UINT32(state_blobs.permanent_flags, TPMEmulator),
885 VMSTATE_UINT32(state_blobs.permanent.size, TPMEmulator),
886 VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.permanent.buffer,
887 TPMEmulator, 0, 0,
888 state_blobs.permanent.size),
889
890 VMSTATE_UINT32(state_blobs.volatil_flags, TPMEmulator),
891 VMSTATE_UINT32(state_blobs.volatil.size, TPMEmulator),
892 VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.volatil.buffer,
893 TPMEmulator, 0, 0,
894 state_blobs.volatil.size),
895
896 VMSTATE_UINT32(state_blobs.savestate_flags, TPMEmulator),
897 VMSTATE_UINT32(state_blobs.savestate.size, TPMEmulator),
898 VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.savestate.buffer,
899 TPMEmulator, 0, 0,
900 state_blobs.savestate.size),
901
902 VMSTATE_END_OF_LIST()
903 }
904};
905
906static void tpm_emulator_inst_init(Object *obj)
907{
908 TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
909
910 trace_tpm_emulator_inst_init();
911
912 tpm_emu->options = g_new0(TPMEmulatorOptions, 1);
913 tpm_emu->cur_locty_number = ~0;
914 qemu_mutex_init(&tpm_emu->mutex);
915
916 vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY,
917 &vmstate_tpm_emulator, obj);
918}
919
920
921
922
923static void tpm_emulator_shutdown(TPMEmulator *tpm_emu)
924{
925 ptm_res res;
926
927 if (!tpm_emu->options->chardev) {
928
929 return;
930 }
931
932 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SHUTDOWN, &res, 0, sizeof(res)) < 0) {
933 error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s",
934 strerror(errno));
935 } else if (res != 0) {
936 error_report("tpm-emulator: TPM result for shutdown: 0x%x %s",
937 be32_to_cpu(res), tpm_emulator_strerror(be32_to_cpu(res)));
938 }
939}
940
941static void tpm_emulator_inst_finalize(Object *obj)
942{
943 TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
944 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
945
946 tpm_emulator_shutdown(tpm_emu);
947
948 object_unref(OBJECT(tpm_emu->data_ioc));
949
950 qemu_chr_fe_deinit(&tpm_emu->ctrl_chr, false);
951
952 qapi_free_TPMEmulatorOptions(tpm_emu->options);
953
954 if (tpm_emu->migration_blocker) {
955 migrate_del_blocker(tpm_emu->migration_blocker);
956 error_free(tpm_emu->migration_blocker);
957 }
958
959 tpm_sized_buffer_reset(&state_blobs->volatil);
960 tpm_sized_buffer_reset(&state_blobs->permanent);
961 tpm_sized_buffer_reset(&state_blobs->savestate);
962
963 qemu_mutex_destroy(&tpm_emu->mutex);
964
965 vmstate_unregister(NULL, &vmstate_tpm_emulator, obj);
966}
967
968static void tpm_emulator_class_init(ObjectClass *klass, void *data)
969{
970 TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
971
972 tbc->type = TPM_TYPE_EMULATOR;
973 tbc->opts = tpm_emulator_cmdline_opts;
974 tbc->desc = "TPM emulator backend driver";
975 tbc->create = tpm_emulator_create;
976 tbc->startup_tpm = tpm_emulator_startup_tpm;
977 tbc->cancel_cmd = tpm_emulator_cancel_cmd;
978 tbc->get_tpm_established_flag = tpm_emulator_get_tpm_established_flag;
979 tbc->reset_tpm_established_flag = tpm_emulator_reset_tpm_established_flag;
980 tbc->get_tpm_version = tpm_emulator_get_tpm_version;
981 tbc->get_buffer_size = tpm_emulator_get_buffer_size;
982 tbc->get_tpm_options = tpm_emulator_get_tpm_options;
983
984 tbc->handle_request = tpm_emulator_handle_request;
985}
986
987static const TypeInfo tpm_emulator_info = {
988 .name = TYPE_TPM_EMULATOR,
989 .parent = TYPE_TPM_BACKEND,
990 .instance_size = sizeof(TPMEmulator),
991 .class_init = tpm_emulator_class_init,
992 .instance_init = tpm_emulator_inst_init,
993 .instance_finalize = tpm_emulator_inst_finalize,
994};
995
996static void tpm_emulator_register(void)
997{
998 type_register_static(&tpm_emulator_info);
999}
1000
1001type_init(tpm_emulator_register)
1002