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/sockets.h"
32#include "io/channel-socket.h"
33#include "sysemu/tpm_backend.h"
34#include "tpm_int.h"
35#include "hw/hw.h"
36#include "tpm_util.h"
37#include "tpm_ioctl.h"
38#include "migration/blocker.h"
39#include "qapi/error.h"
40#include "qapi/clone-visitor.h"
41#include "qapi/qapi-visit-tpm.h"
42#include "chardev/char-fe.h"
43#include "trace.h"
44
45#define TYPE_TPM_EMULATOR "tpm-emulator"
46#define TPM_EMULATOR(obj) \
47 OBJECT_CHECK(TPMEmulator, (obj), TYPE_TPM_EMULATOR)
48
49#define TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(S, cap) (((S)->caps & (cap)) == (cap))
50
51
52
53
54typedef struct TPMBlobBuffers {
55 uint32_t permanent_flags;
56 TPMSizedBuffer permanent;
57
58 uint32_t volatil_flags;
59 TPMSizedBuffer volatil;
60
61 uint32_t savestate_flags;
62 TPMSizedBuffer savestate;
63} TPMBlobBuffers;
64
65typedef struct TPMEmulator {
66 TPMBackend parent;
67
68 TPMEmulatorOptions *options;
69 CharBackend ctrl_chr;
70 QIOChannel *data_ioc;
71 TPMVersion tpm_version;
72 ptm_cap caps;
73 uint8_t cur_locty_number;
74 Error *migration_blocker;
75
76 QemuMutex mutex;
77
78 unsigned int established_flag:1;
79 unsigned int established_flag_cached:1;
80
81 TPMBlobBuffers state_blobs;
82} TPMEmulator;
83
84struct tpm_error {
85 uint32_t tpm_result;
86 const char *string;
87};
88
89static const struct tpm_error tpm_errors[] = {
90
91 { TPM_BAD_PARAMETER , "a parameter is bad" },
92 { TPM_FAIL , "operation failed" },
93 { TPM_KEYNOTFOUND , "key could not be found" },
94 { TPM_BAD_PARAM_SIZE , "bad parameter size"},
95 { TPM_ENCRYPT_ERROR , "encryption error" },
96 { TPM_DECRYPT_ERROR , "decryption error" },
97 { TPM_BAD_KEY_PROPERTY, "bad key property" },
98 { TPM_BAD_MODE , "bad (encryption) mode" },
99 { TPM_BAD_VERSION , "bad version identifier" },
100 { TPM_BAD_LOCALITY , "bad locality" },
101
102 { TPM_RC_FAILURE , "operation failed" },
103 { TPM_RC_LOCALITY , "bad locality" },
104 { TPM_RC_INSUFFICIENT, "insufficient amount of data" },
105};
106
107static const char *tpm_emulator_strerror(uint32_t tpm_result)
108{
109 size_t i;
110
111 for (i = 0; i < ARRAY_SIZE(tpm_errors); i++) {
112 if (tpm_errors[i].tpm_result == tpm_result) {
113 return tpm_errors[i].string;
114 }
115 }
116 return "";
117}
118
119static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg,
120 size_t msg_len_in, size_t msg_len_out)
121{
122 CharBackend *dev = &tpm->ctrl_chr;
123 uint32_t cmd_no = cpu_to_be32(cmd);
124 ssize_t n = sizeof(uint32_t) + msg_len_in;
125 uint8_t *buf = NULL;
126 int ret = -1;
127
128 qemu_mutex_lock(&tpm->mutex);
129
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 goto end;
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 goto end;
143 }
144 }
145
146 ret = 0;
147
148end:
149 qemu_mutex_unlock(&tpm->mutex);
150 return ret;
151}
152
153static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_emu,
154 const uint8_t *in, uint32_t in_len,
155 uint8_t *out, uint32_t out_len,
156 bool *selftest_done,
157 Error **err)
158{
159 ssize_t ret;
160 bool is_selftest = false;
161
162 if (selftest_done) {
163 *selftest_done = false;
164 is_selftest = tpm_util_is_selftest(in, in_len);
165 }
166
167 ret = qio_channel_write_all(tpm_emu->data_ioc, (char *)in, in_len, err);
168 if (ret != 0) {
169 return -1;
170 }
171
172 ret = qio_channel_read_all(tpm_emu->data_ioc, (char *)out,
173 sizeof(struct tpm_resp_hdr), err);
174 if (ret != 0) {
175 return -1;
176 }
177
178 ret = qio_channel_read_all(tpm_emu->data_ioc,
179 (char *)out + sizeof(struct tpm_resp_hdr),
180 tpm_cmd_get_size(out) - sizeof(struct tpm_resp_hdr), err);
181 if (ret != 0) {
182 return -1;
183 }
184
185 if (is_selftest) {
186 *selftest_done = tpm_cmd_get_errcode(out) == 0;
187 }
188
189 return 0;
190}
191
192static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number,
193 Error **errp)
194{
195 ptm_loc loc;
196
197 if (tpm_emu->cur_locty_number == locty_number) {
198 return 0;
199 }
200
201 trace_tpm_emulator_set_locality(locty_number);
202
203 memset(&loc, 0, sizeof(loc));
204 loc.u.req.loc = locty_number;
205 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_LOCALITY, &loc,
206 sizeof(loc), sizeof(loc)) < 0) {
207 error_setg(errp, "tpm-emulator: could not set locality : %s",
208 strerror(errno));
209 return -1;
210 }
211
212 loc.u.resp.tpm_result = be32_to_cpu(loc.u.resp.tpm_result);
213 if (loc.u.resp.tpm_result != 0) {
214 error_setg(errp, "tpm-emulator: TPM result for set locality : 0x%x",
215 loc.u.resp.tpm_result);
216 return -1;
217 }
218
219 tpm_emu->cur_locty_number = locty_number;
220
221 return 0;
222}
223
224static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
225 Error **errp)
226{
227 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
228
229 trace_tpm_emulator_handle_request();
230
231 if (tpm_emulator_set_locality(tpm_emu, cmd->locty, errp) < 0 ||
232 tpm_emulator_unix_tx_bufs(tpm_emu, cmd->in, cmd->in_len,
233 cmd->out, cmd->out_len,
234 &cmd->selftest_done, errp) < 0) {
235 tpm_util_write_fatal_error_response(cmd->out, cmd->out_len);
236 }
237}
238
239static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
240{
241 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY,
242 &tpm_emu->caps, 0, sizeof(tpm_emu->caps)) < 0) {
243 error_report("tpm-emulator: probing failed : %s", strerror(errno));
244 return -1;
245 }
246
247 tpm_emu->caps = be64_to_cpu(tpm_emu->caps);
248
249 trace_tpm_emulator_probe_caps(tpm_emu->caps);
250
251 return 0;
252}
253
254static int tpm_emulator_check_caps(TPMEmulator *tpm_emu)
255{
256 ptm_cap caps = 0;
257 const char *tpm = NULL;
258
259
260 switch (tpm_emu->tpm_version) {
261 case TPM_VERSION_1_2:
262 caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
263 PTM_CAP_SET_LOCALITY | PTM_CAP_SET_DATAFD | PTM_CAP_STOP |
264 PTM_CAP_SET_BUFFERSIZE;
265 tpm = "1.2";
266 break;
267 case TPM_VERSION_2_0:
268 caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
269 PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED |
270 PTM_CAP_SET_DATAFD | PTM_CAP_STOP | PTM_CAP_SET_BUFFERSIZE;
271 tpm = "2";
272 break;
273 case TPM_VERSION_UNSPEC:
274 error_report("tpm-emulator: TPM version has not been set");
275 return -1;
276 }
277
278 if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) {
279 error_report("tpm-emulator: TPM does not implement minimum set of "
280 "required capabilities for TPM %s (0x%x)", tpm, (int)caps);
281 return -1;
282 }
283
284 return 0;
285}
286
287static int tpm_emulator_stop_tpm(TPMBackend *tb)
288{
289 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
290 ptm_res res;
291
292 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0, sizeof(res)) < 0) {
293 error_report("tpm-emulator: Could not stop TPM: %s",
294 strerror(errno));
295 return -1;
296 }
297
298 res = be32_to_cpu(res);
299 if (res) {
300 error_report("tpm-emulator: TPM result for CMD_STOP: 0x%x %s", res,
301 tpm_emulator_strerror(res));
302 return -1;
303 }
304
305 return 0;
306}
307
308static int tpm_emulator_set_buffer_size(TPMBackend *tb,
309 size_t wanted_size,
310 size_t *actual_size)
311{
312 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
313 ptm_setbuffersize psbs;
314
315 if (tpm_emulator_stop_tpm(tb) < 0) {
316 return -1;
317 }
318
319 psbs.u.req.buffersize = cpu_to_be32(wanted_size);
320
321 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_BUFFERSIZE, &psbs,
322 sizeof(psbs.u.req), sizeof(psbs.u.resp)) < 0) {
323 error_report("tpm-emulator: Could not set buffer size: %s",
324 strerror(errno));
325 return -1;
326 }
327
328 psbs.u.resp.tpm_result = be32_to_cpu(psbs.u.resp.tpm_result);
329 if (psbs.u.resp.tpm_result != 0) {
330 error_report("tpm-emulator: TPM result for set buffer size : 0x%x %s",
331 psbs.u.resp.tpm_result,
332 tpm_emulator_strerror(psbs.u.resp.tpm_result));
333 return -1;
334 }
335
336 if (actual_size) {
337 *actual_size = be32_to_cpu(psbs.u.resp.buffersize);
338 }
339
340 trace_tpm_emulator_set_buffer_size(
341 be32_to_cpu(psbs.u.resp.buffersize),
342 be32_to_cpu(psbs.u.resp.minsize),
343 be32_to_cpu(psbs.u.resp.maxsize));
344
345 return 0;
346}
347
348static int tpm_emulator_startup_tpm_resume(TPMBackend *tb, size_t buffersize,
349 bool is_resume)
350{
351 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
352 ptm_init init = {
353 .u.req.init_flags = 0,
354 };
355 ptm_res res;
356
357 trace_tpm_emulator_startup_tpm_resume(is_resume, buffersize);
358
359 if (buffersize != 0 &&
360 tpm_emulator_set_buffer_size(tb, buffersize, NULL) < 0) {
361 goto err_exit;
362 }
363
364 if (is_resume) {
365 init.u.req.init_flags |= cpu_to_be32(PTM_INIT_FLAG_DELETE_VOLATILE);
366 }
367
368 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_INIT, &init, sizeof(init),
369 sizeof(init)) < 0) {
370 error_report("tpm-emulator: could not send INIT: %s",
371 strerror(errno));
372 goto err_exit;
373 }
374
375 res = be32_to_cpu(init.u.resp.tpm_result);
376 if (res) {
377 error_report("tpm-emulator: TPM result for CMD_INIT: 0x%x %s", res,
378 tpm_emulator_strerror(res));
379 goto err_exit;
380 }
381 return 0;
382
383err_exit:
384 return -1;
385}
386
387static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize)
388{
389 return tpm_emulator_startup_tpm_resume(tb, buffersize, false);
390}
391
392static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb)
393{
394 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
395 ptm_est est;
396
397 if (tpm_emu->established_flag_cached) {
398 return tpm_emu->established_flag;
399 }
400
401 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_TPMESTABLISHED, &est,
402 0, sizeof(est)) < 0) {
403 error_report("tpm-emulator: Could not get the TPM established flag: %s",
404 strerror(errno));
405 return false;
406 }
407 trace_tpm_emulator_get_tpm_established_flag(est.u.resp.bit);
408
409 tpm_emu->established_flag_cached = 1;
410 tpm_emu->established_flag = (est.u.resp.bit != 0);
411
412 return tpm_emu->established_flag;
413}
414
415static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
416 uint8_t locty)
417{
418 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
419 ptm_reset_est reset_est;
420 ptm_res res;
421
422
423 if (tpm_emu->tpm_version != TPM_VERSION_2_0) {
424 return 0;
425 }
426
427 reset_est.u.req.loc = tpm_emu->cur_locty_number;
428 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_RESET_TPMESTABLISHED,
429 &reset_est, sizeof(reset_est),
430 sizeof(reset_est)) < 0) {
431 error_report("tpm-emulator: Could not reset the establishment bit: %s",
432 strerror(errno));
433 return -1;
434 }
435
436 res = be32_to_cpu(reset_est.u.resp.tpm_result);
437 if (res) {
438 error_report(
439 "tpm-emulator: TPM result for rest established flag: 0x%x %s",
440 res, tpm_emulator_strerror(res));
441 return -1;
442 }
443
444 tpm_emu->established_flag_cached = 0;
445
446 return 0;
447}
448
449static void tpm_emulator_cancel_cmd(TPMBackend *tb)
450{
451 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
452 ptm_res res;
453
454 if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, PTM_CAP_CANCEL_TPM_CMD)) {
455 trace_tpm_emulator_cancel_cmd_not_supt();
456 return;
457 }
458
459
460 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_CANCEL_TPM_CMD, &res, 0,
461 sizeof(res)) < 0) {
462 error_report("tpm-emulator: Could not cancel command: %s",
463 strerror(errno));
464 } else if (res != 0) {
465 error_report("tpm-emulator: Failed to cancel TPM: 0x%x",
466 be32_to_cpu(res));
467 }
468}
469
470static TPMVersion tpm_emulator_get_tpm_version(TPMBackend *tb)
471{
472 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
473
474 return tpm_emu->tpm_version;
475}
476
477static size_t tpm_emulator_get_buffer_size(TPMBackend *tb)
478{
479 size_t actual_size;
480
481 if (tpm_emulator_set_buffer_size(tb, 0, &actual_size) < 0) {
482 return 4096;
483 }
484
485 return actual_size;
486}
487
488static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)
489{
490 Error *err = NULL;
491 ptm_cap caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB |
492 PTM_CAP_STOP;
493
494 if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) {
495 error_setg(&tpm_emu->migration_blocker,
496 "Migration disabled: TPM emulator does not support "
497 "migration");
498 migrate_add_blocker(tpm_emu->migration_blocker, &err);
499 if (err) {
500 error_report_err(err);
501 error_free(tpm_emu->migration_blocker);
502 tpm_emu->migration_blocker = NULL;
503
504 return -1;
505 }
506 }
507
508 return 0;
509}
510
511static int tpm_emulator_prepare_data_fd(TPMEmulator *tpm_emu)
512{
513 ptm_res res;
514 Error *err = NULL;
515 int fds[2] = { -1, -1 };
516
517 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
518 error_report("tpm-emulator: Failed to create socketpair");
519 return -1;
520 }
521
522 qemu_chr_fe_set_msgfds(&tpm_emu->ctrl_chr, fds + 1, 1);
523
524 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_DATAFD, &res, 0,
525 sizeof(res)) < 0 || res != 0) {
526 error_report("tpm-emulator: Failed to send CMD_SET_DATAFD: %s",
527 strerror(errno));
528 goto err_exit;
529 }
530
531 tpm_emu->data_ioc = QIO_CHANNEL(qio_channel_socket_new_fd(fds[0], &err));
532 if (err) {
533 error_prepend(&err, "tpm-emulator: Failed to create io channel: ");
534 error_report_err(err);
535 goto err_exit;
536 }
537
538 closesocket(fds[1]);
539
540 return 0;
541
542err_exit:
543 closesocket(fds[0]);
544 closesocket(fds[1]);
545 return -1;
546}
547
548static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts)
549{
550 const char *value;
551
552 value = qemu_opt_get(opts, "chardev");
553 if (value) {
554 Error *err = NULL;
555 Chardev *dev = qemu_chr_find(value);
556
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
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, -1, &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_emulator_ctrlcmd(tpm_emu, CMD_SHUTDOWN, &res, 0, sizeof(res)) < 0) {
927 error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s",
928 strerror(errno));
929 } else if (res != 0) {
930 error_report("tpm-emulator: TPM result for shutdown: 0x%x %s",
931 be32_to_cpu(res), tpm_emulator_strerror(be32_to_cpu(res)));
932 }
933}
934
935static void tpm_emulator_inst_finalize(Object *obj)
936{
937 TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
938 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
939
940 tpm_emulator_shutdown(tpm_emu);
941
942 object_unref(OBJECT(tpm_emu->data_ioc));
943
944 qemu_chr_fe_deinit(&tpm_emu->ctrl_chr, false);
945
946 qapi_free_TPMEmulatorOptions(tpm_emu->options);
947
948 if (tpm_emu->migration_blocker) {
949 migrate_del_blocker(tpm_emu->migration_blocker);
950 error_free(tpm_emu->migration_blocker);
951 }
952
953 tpm_sized_buffer_reset(&state_blobs->volatil);
954 tpm_sized_buffer_reset(&state_blobs->permanent);
955 tpm_sized_buffer_reset(&state_blobs->savestate);
956
957 qemu_mutex_destroy(&tpm_emu->mutex);
958
959 vmstate_unregister(NULL, &vmstate_tpm_emulator, obj);
960}
961
962static void tpm_emulator_class_init(ObjectClass *klass, void *data)
963{
964 TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
965
966 tbc->type = TPM_TYPE_EMULATOR;
967 tbc->opts = tpm_emulator_cmdline_opts;
968 tbc->desc = "TPM emulator backend driver";
969 tbc->create = tpm_emulator_create;
970 tbc->startup_tpm = tpm_emulator_startup_tpm;
971 tbc->cancel_cmd = tpm_emulator_cancel_cmd;
972 tbc->get_tpm_established_flag = tpm_emulator_get_tpm_established_flag;
973 tbc->reset_tpm_established_flag = tpm_emulator_reset_tpm_established_flag;
974 tbc->get_tpm_version = tpm_emulator_get_tpm_version;
975 tbc->get_buffer_size = tpm_emulator_get_buffer_size;
976 tbc->get_tpm_options = tpm_emulator_get_tpm_options;
977
978 tbc->handle_request = tpm_emulator_handle_request;
979}
980
981static const TypeInfo tpm_emulator_info = {
982 .name = TYPE_TPM_EMULATOR,
983 .parent = TYPE_TPM_BACKEND,
984 .instance_size = sizeof(TPMEmulator),
985 .class_init = tpm_emulator_class_init,
986 .instance_init = tpm_emulator_inst_init,
987 .instance_finalize = tpm_emulator_inst_finalize,
988};
989
990static void tpm_emulator_register(void)
991{
992 type_register_static(&tpm_emulator_info);
993}
994
995type_init(tpm_emulator_register)
996