]> Git Repo - qemu.git/blame - hw/tpm/tpm_emulator.c
Include migration/vmstate.h less
[qemu.git] / hw / tpm / tpm_emulator.c
CommitLineData
f4ede81e
AV
1/*
2 * Emulator TPM driver
3 *
4 * Copyright (c) 2017 Intel Corporation
5 * Author: Amarnath Valluri <[email protected]>
6 *
38ab74e7 7 * Copyright (c) 2010 - 2013, 2018 IBM Corporation
f4ede81e
AV
8 * Authors:
9 * Stefan Berger <[email protected]>
10 *
11 * Copyright (C) 2011 IAIK, Graz University of Technology
12 * Author: Andreas Niederl
13 *
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 of the License, or (at your option) any later version.
18 *
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.
23 *
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/>
26 *
27 */
28
29#include "qemu/osdep.h"
30#include "qemu/error-report.h"
0b8fa32f 31#include "qemu/module.h"
f4ede81e
AV
32#include "qemu/sockets.h"
33#include "io/channel-socket.h"
34#include "sysemu/tpm_backend.h"
35#include "tpm_int.h"
36#include "hw/hw.h"
f4ede81e
AV
37#include "tpm_util.h"
38#include "tpm_ioctl.h"
39#include "migration/blocker.h"
d6454270 40#include "migration/vmstate.h"
f4ede81e
AV
41#include "qapi/error.h"
42#include "qapi/clone-visitor.h"
9af23989 43#include "qapi/qapi-visit-tpm.h"
f4ede81e 44#include "chardev/char-fe.h"
9d9dcd96 45#include "trace.h"
f4ede81e
AV
46
47#define TYPE_TPM_EMULATOR "tpm-emulator"
48#define TPM_EMULATOR(obj) \
49 OBJECT_CHECK(TPMEmulator, (obj), TYPE_TPM_EMULATOR)
50
51#define TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(S, cap) (((S)->caps & (cap)) == (cap))
52
f4ede81e 53/* data structures */
38ab74e7
SB
54
55/* blobs from the TPM; part of VM state when migrating */
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
f4ede81e
AV
67typedef struct TPMEmulator {
68 TPMBackend parent;
69
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;
17b1af77
MAL
77
78 QemuMutex mutex;
0b4c7c65
SB
79
80 unsigned int established_flag:1;
81 unsigned int established_flag_cached:1;
38ab74e7
SB
82
83 TPMBlobBuffers state_blobs;
f4ede81e
AV
84} TPMEmulator;
85
7e095e84
SB
86struct tpm_error {
87 uint32_t tpm_result;
88 const char *string;
89};
90
91static 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" },
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}
f4ede81e 120
17b1af77 121static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg,
f4ede81e
AV
122 size_t msg_len_in, size_t msg_len_out)
123{
17b1af77 124 CharBackend *dev = &tpm->ctrl_chr;
f4ede81e
AV
125 uint32_t cmd_no = cpu_to_be32(cmd);
126 ssize_t n = sizeof(uint32_t) + msg_len_in;
127 uint8_t *buf = NULL;
17b1af77
MAL
128 int ret = -1;
129
130 qemu_mutex_lock(&tpm->mutex);
f4ede81e
AV
131
132 buf = g_alloca(n);
133 memcpy(buf, &cmd_no, sizeof(cmd_no));
134 memcpy(buf + sizeof(cmd_no), msg, msg_len_in);
135
136 n = qemu_chr_fe_write_all(dev, buf, n);
137 if (n <= 0) {
17b1af77 138 goto end;
f4ede81e
AV
139 }
140
141 if (msg_len_out != 0) {
142 n = qemu_chr_fe_read_all(dev, msg, msg_len_out);
143 if (n <= 0) {
17b1af77 144 goto end;
f4ede81e
AV
145 }
146 }
147
17b1af77
MAL
148 ret = 0;
149
150end:
151 qemu_mutex_unlock(&tpm->mutex);
152 return ret;
f4ede81e
AV
153}
154
155static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_emu,
156 const uint8_t *in, uint32_t in_len,
157 uint8_t *out, uint32_t out_len,
158 bool *selftest_done,
159 Error **err)
160{
161 ssize_t ret;
162 bool is_selftest = false;
f4ede81e
AV
163
164 if (selftest_done) {
165 *selftest_done = false;
166 is_selftest = tpm_util_is_selftest(in, in_len);
167 }
168
169 ret = qio_channel_write_all(tpm_emu->data_ioc, (char *)in, in_len, err);
170 if (ret != 0) {
171 return -1;
172 }
173
cc1b6c55
MAL
174 ret = qio_channel_read_all(tpm_emu->data_ioc, (char *)out,
175 sizeof(struct tpm_resp_hdr), err);
f4ede81e
AV
176 if (ret != 0) {
177 return -1;
178 }
179
cc1b6c55
MAL
180 ret = qio_channel_read_all(tpm_emu->data_ioc,
181 (char *)out + sizeof(struct tpm_resp_hdr),
182 tpm_cmd_get_size(out) - sizeof(struct tpm_resp_hdr), err);
f4ede81e
AV
183 if (ret != 0) {
184 return -1;
185 }
186
187 if (is_selftest) {
cc1b6c55 188 *selftest_done = tpm_cmd_get_errcode(out) == 0;
f4ede81e
AV
189 }
190
191 return 0;
192}
193
c106ede9
MAL
194static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number,
195 Error **errp)
f4ede81e
AV
196{
197 ptm_loc loc;
198
f4ede81e
AV
199 if (tpm_emu->cur_locty_number == locty_number) {
200 return 0;
201 }
202
9d9dcd96
SB
203 trace_tpm_emulator_set_locality(locty_number);
204
eff1fe9f 205 memset(&loc, 0, sizeof(loc));
f4ede81e 206 loc.u.req.loc = locty_number;
17b1af77 207 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_LOCALITY, &loc,
f4ede81e 208 sizeof(loc), sizeof(loc)) < 0) {
c106ede9
MAL
209 error_setg(errp, "tpm-emulator: could not set locality : %s",
210 strerror(errno));
f4ede81e
AV
211 return -1;
212 }
213
214 loc.u.resp.tpm_result = be32_to_cpu(loc.u.resp.tpm_result);
215 if (loc.u.resp.tpm_result != 0) {
c106ede9
MAL
216 error_setg(errp, "tpm-emulator: TPM result for set locality : 0x%x",
217 loc.u.resp.tpm_result);
f4ede81e
AV
218 return -1;
219 }
220
221 tpm_emu->cur_locty_number = locty_number;
222
223 return 0;
224}
225
6a8a2354
MAL
226static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
227 Error **errp)
f4ede81e
AV
228{
229 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
f4ede81e 230
9d9dcd96 231 trace_tpm_emulator_handle_request();
905e78ba 232
6a8a2354
MAL
233 if (tpm_emulator_set_locality(tpm_emu, cmd->locty, errp) < 0 ||
234 tpm_emulator_unix_tx_bufs(tpm_emu, cmd->in, cmd->in_len,
0e43b7e6 235 cmd->out, cmd->out_len,
6a8a2354
MAL
236 &cmd->selftest_done, errp) < 0) {
237 tpm_util_write_fatal_error_response(cmd->out, cmd->out_len);
0e43b7e6 238 }
f4ede81e
AV
239}
240
241static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
242{
17b1af77
MAL
243 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY,
244 &tpm_emu->caps, 0, sizeof(tpm_emu->caps)) < 0) {
f4ede81e
AV
245 error_report("tpm-emulator: probing failed : %s", strerror(errno));
246 return -1;
247 }
248
249 tpm_emu->caps = be64_to_cpu(tpm_emu->caps);
250
9d9dcd96 251 trace_tpm_emulator_probe_caps(tpm_emu->caps);
f4ede81e
AV
252
253 return 0;
254}
255
256static int tpm_emulator_check_caps(TPMEmulator *tpm_emu)
257{
258 ptm_cap caps = 0;
259 const char *tpm = NULL;
260
261 /* check for min. required capabilities */
262 switch (tpm_emu->tpm_version) {
263 case TPM_VERSION_1_2:
264 caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
9375c44f
SB
265 PTM_CAP_SET_LOCALITY | PTM_CAP_SET_DATAFD | PTM_CAP_STOP |
266 PTM_CAP_SET_BUFFERSIZE;
f4ede81e
AV
267 tpm = "1.2";
268 break;
269 case TPM_VERSION_2_0:
270 caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
271 PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED |
9375c44f 272 PTM_CAP_SET_DATAFD | PTM_CAP_STOP | PTM_CAP_SET_BUFFERSIZE;
f4ede81e
AV
273 tpm = "2";
274 break;
275 case TPM_VERSION_UNSPEC:
276 error_report("tpm-emulator: TPM version has not been set");
277 return -1;
278 }
279
280 if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) {
281 error_report("tpm-emulator: TPM does not implement minimum set of "
282 "required capabilities for TPM %s (0x%x)", tpm, (int)caps);
283 return -1;
284 }
285
286 return 0;
287}
288
9375c44f
SB
289static int tpm_emulator_stop_tpm(TPMBackend *tb)
290{
291 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
292 ptm_res res;
293
294 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0, sizeof(res)) < 0) {
295 error_report("tpm-emulator: Could not stop TPM: %s",
296 strerror(errno));
297 return -1;
298 }
299
300 res = be32_to_cpu(res);
301 if (res) {
7e095e84
SB
302 error_report("tpm-emulator: TPM result for CMD_STOP: 0x%x %s", res,
303 tpm_emulator_strerror(res));
9375c44f
SB
304 return -1;
305 }
306
307 return 0;
308}
309
310static int tpm_emulator_set_buffer_size(TPMBackend *tb,
311 size_t wanted_size,
312 size_t *actual_size)
313{
314 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
315 ptm_setbuffersize psbs;
316
317 if (tpm_emulator_stop_tpm(tb) < 0) {
318 return -1;
319 }
320
321 psbs.u.req.buffersize = cpu_to_be32(wanted_size);
322
323 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_BUFFERSIZE, &psbs,
324 sizeof(psbs.u.req), sizeof(psbs.u.resp)) < 0) {
325 error_report("tpm-emulator: Could not set buffer size: %s",
326 strerror(errno));
327 return -1;
328 }
329
330 psbs.u.resp.tpm_result = be32_to_cpu(psbs.u.resp.tpm_result);
331 if (psbs.u.resp.tpm_result != 0) {
7e095e84
SB
332 error_report("tpm-emulator: TPM result for set buffer size : 0x%x %s",
333 psbs.u.resp.tpm_result,
334 tpm_emulator_strerror(psbs.u.resp.tpm_result));
9375c44f
SB
335 return -1;
336 }
337
338 if (actual_size) {
339 *actual_size = be32_to_cpu(psbs.u.resp.buffersize);
340 }
341
9d9dcd96 342 trace_tpm_emulator_set_buffer_size(
9375c44f
SB
343 be32_to_cpu(psbs.u.resp.buffersize),
344 be32_to_cpu(psbs.u.resp.minsize),
345 be32_to_cpu(psbs.u.resp.maxsize));
346
347 return 0;
348}
349
38ab74e7
SB
350static int tpm_emulator_startup_tpm_resume(TPMBackend *tb, size_t buffersize,
351 bool is_resume)
f4ede81e
AV
352{
353 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
30270587
SB
354 ptm_init init = {
355 .u.req.init_flags = 0,
356 };
f4ede81e
AV
357 ptm_res res;
358
38ab74e7
SB
359 trace_tpm_emulator_startup_tpm_resume(is_resume, buffersize);
360
9375c44f
SB
361 if (buffersize != 0 &&
362 tpm_emulator_set_buffer_size(tb, buffersize, NULL) < 0) {
363 goto err_exit;
364 }
365
38ab74e7
SB
366 if (is_resume) {
367 init.u.req.init_flags |= cpu_to_be32(PTM_INIT_FLAG_DELETE_VOLATILE);
368 }
369
17b1af77
MAL
370 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_INIT, &init, sizeof(init),
371 sizeof(init)) < 0) {
f4ede81e
AV
372 error_report("tpm-emulator: could not send INIT: %s",
373 strerror(errno));
374 goto err_exit;
375 }
376
377 res = be32_to_cpu(init.u.resp.tpm_result);
378 if (res) {
7e095e84
SB
379 error_report("tpm-emulator: TPM result for CMD_INIT: 0x%x %s", res,
380 tpm_emulator_strerror(res));
f4ede81e
AV
381 goto err_exit;
382 }
383 return 0;
384
385err_exit:
386 return -1;
387}
388
38ab74e7
SB
389static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize)
390{
391 return tpm_emulator_startup_tpm_resume(tb, buffersize, false);
392}
393
f4ede81e
AV
394static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb)
395{
396 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
397 ptm_est est;
398
0b4c7c65
SB
399 if (tpm_emu->established_flag_cached) {
400 return tpm_emu->established_flag;
401 }
402
17b1af77 403 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_TPMESTABLISHED, &est,
f4ede81e
AV
404 0, sizeof(est)) < 0) {
405 error_report("tpm-emulator: Could not get the TPM established flag: %s",
406 strerror(errno));
407 return false;
408 }
9d9dcd96 409 trace_tpm_emulator_get_tpm_established_flag(est.u.resp.bit);
0b4c7c65
SB
410
411 tpm_emu->established_flag_cached = 1;
412 tpm_emu->established_flag = (est.u.resp.bit != 0);
f4ede81e 413
0b4c7c65 414 return tpm_emu->established_flag;
f4ede81e
AV
415}
416
417static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
418 uint8_t locty)
419{
420 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
421 ptm_reset_est reset_est;
422 ptm_res res;
423
424 /* only a TPM 2.0 will support this */
425 if (tpm_emu->tpm_version != TPM_VERSION_2_0) {
426 return 0;
427 }
428
429 reset_est.u.req.loc = tpm_emu->cur_locty_number;
17b1af77 430 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_RESET_TPMESTABLISHED,
f4ede81e
AV
431 &reset_est, sizeof(reset_est),
432 sizeof(reset_est)) < 0) {
433 error_report("tpm-emulator: Could not reset the establishment bit: %s",
434 strerror(errno));
435 return -1;
436 }
437
438 res = be32_to_cpu(reset_est.u.resp.tpm_result);
439 if (res) {
7e095e84
SB
440 error_report(
441 "tpm-emulator: TPM result for rest established flag: 0x%x %s",
442 res, tpm_emulator_strerror(res));
f4ede81e
AV
443 return -1;
444 }
445
0b4c7c65
SB
446 tpm_emu->established_flag_cached = 0;
447
f4ede81e
AV
448 return 0;
449}
450
451static void tpm_emulator_cancel_cmd(TPMBackend *tb)
452{
453 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
454 ptm_res res;
455
456 if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, PTM_CAP_CANCEL_TPM_CMD)) {
9d9dcd96 457 trace_tpm_emulator_cancel_cmd_not_supt();
f4ede81e
AV
458 return;
459 }
460
3d011411 461 /* FIXME: make the function non-blocking, or it may block a VCPU */
17b1af77 462 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_CANCEL_TPM_CMD, &res, 0,
f4ede81e
AV
463 sizeof(res)) < 0) {
464 error_report("tpm-emulator: Could not cancel command: %s",
465 strerror(errno));
466 } else if (res != 0) {
467 error_report("tpm-emulator: Failed to cancel TPM: 0x%x",
468 be32_to_cpu(res));
469 }
470}
471
472static TPMVersion tpm_emulator_get_tpm_version(TPMBackend *tb)
473{
474 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
475
476 return tpm_emu->tpm_version;
477}
478
b21e6aaf
SB
479static size_t tpm_emulator_get_buffer_size(TPMBackend *tb)
480{
9375c44f
SB
481 size_t actual_size;
482
483 if (tpm_emulator_set_buffer_size(tb, 0, &actual_size) < 0) {
484 return 4096;
485 }
486
487 return actual_size;
b21e6aaf
SB
488}
489
f4ede81e
AV
490static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)
491{
492 Error *err = NULL;
38ab74e7
SB
493 ptm_cap caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB |
494 PTM_CAP_STOP;
f4ede81e 495
38ab74e7
SB
496 if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) {
497 error_setg(&tpm_emu->migration_blocker,
498 "Migration disabled: TPM emulator does not support "
499 "migration");
500 migrate_add_blocker(tpm_emu->migration_blocker, &err);
501 if (err) {
502 error_report_err(err);
503 error_free(tpm_emu->migration_blocker);
504 tpm_emu->migration_blocker = NULL;
f4ede81e 505
38ab74e7
SB
506 return -1;
507 }
f4ede81e
AV
508 }
509
510 return 0;
511}
512
513static int tpm_emulator_prepare_data_fd(TPMEmulator *tpm_emu)
514{
515 ptm_res res;
516 Error *err = NULL;
517 int fds[2] = { -1, -1 };
518
519 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
520 error_report("tpm-emulator: Failed to create socketpair");
521 return -1;
522 }
523
524 qemu_chr_fe_set_msgfds(&tpm_emu->ctrl_chr, fds + 1, 1);
525
17b1af77
MAL
526 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_DATAFD, &res, 0,
527 sizeof(res)) < 0 || res != 0) {
f4ede81e
AV
528 error_report("tpm-emulator: Failed to send CMD_SET_DATAFD: %s",
529 strerror(errno));
530 goto err_exit;
531 }
532
533 tpm_emu->data_ioc = QIO_CHANNEL(qio_channel_socket_new_fd(fds[0], &err));
534 if (err) {
535 error_prepend(&err, "tpm-emulator: Failed to create io channel: ");
536 error_report_err(err);
537 goto err_exit;
538 }
539
540 closesocket(fds[1]);
541
542 return 0;
543
544err_exit:
545 closesocket(fds[0]);
546 closesocket(fds[1]);
547 return -1;
548}
549
550static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts)
551{
552 const char *value;
553
554 value = qemu_opt_get(opts, "chardev");
555 if (value) {
556 Error *err = NULL;
557 Chardev *dev = qemu_chr_find(value);
558
559 if (!dev) {
560 error_report("tpm-emulator: tpm chardev '%s' not found.", value);
561 goto err;
562 }
563
564 if (!qemu_chr_fe_init(&tpm_emu->ctrl_chr, dev, &err)) {
565 error_prepend(&err, "tpm-emulator: No valid chardev found at '%s':",
566 value);
567 error_report_err(err);
568 goto err;
569 }
570
571 tpm_emu->options->chardev = g_strdup(value);
572 }
573
574 if (tpm_emulator_prepare_data_fd(tpm_emu) < 0) {
575 goto err;
576 }
577
578 /* FIXME: tpm_util_test_tpmdev() accepts only on socket fd, as it also used
579 * by passthrough driver, which not yet using GIOChannel.
580 */
581 if (tpm_util_test_tpmdev(QIO_CHANNEL_SOCKET(tpm_emu->data_ioc)->fd,
582 &tpm_emu->tpm_version)) {
583 error_report("'%s' is not emulating TPM device. Error: %s",
584 tpm_emu->options->chardev, strerror(errno));
585 goto err;
586 }
587
9d9dcd96
SB
588 switch (tpm_emu->tpm_version) {
589 case TPM_VERSION_1_2:
590 trace_tpm_emulator_handle_device_opts_tpm12();
591 break;
592 case TPM_VERSION_2_0:
593 trace_tpm_emulator_handle_device_opts_tpm2();
594 break;
595 default:
596 trace_tpm_emulator_handle_device_opts_unspec();
597 }
f4ede81e
AV
598
599 if (tpm_emulator_probe_caps(tpm_emu) ||
600 tpm_emulator_check_caps(tpm_emu)) {
601 goto err;
602 }
603
604 return tpm_emulator_block_migration(tpm_emu);
605
606err:
9d9dcd96
SB
607 trace_tpm_emulator_handle_device_opts_startup_error();
608
f4ede81e
AV
609 return -1;
610}
611
9f7c0ef2 612static TPMBackend *tpm_emulator_create(QemuOpts *opts)
f4ede81e
AV
613{
614 TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR));
615
f4ede81e 616 if (tpm_emulator_handle_device_opts(TPM_EMULATOR(tb), opts)) {
9f7c0ef2
MAL
617 object_unref(OBJECT(tb));
618 return NULL;
f4ede81e
AV
619 }
620
621 return tb;
f4ede81e
AV
622}
623
624static TpmTypeOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)
625{
626 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
627 TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
628
629 options->type = TPM_TYPE_OPTIONS_KIND_EMULATOR;
630 options->u.emulator.data = QAPI_CLONE(TPMEmulatorOptions, tpm_emu->options);
631
632 return options;
633}
634
635static const QemuOptDesc tpm_emulator_cmdline_opts[] = {
636 TPM_STANDARD_CMDLINE_OPTS,
637 {
638 .name = "chardev",
639 .type = QEMU_OPT_STRING,
640 .help = "Character device to use for out-of-band control messages",
641 },
642 { /* end of list */ },
643};
644
38ab74e7
SB
645/*
646 * Transfer a TPM state blob from the TPM into a provided buffer.
647 *
648 * @tpm_emu: TPMEmulator
649 * @type: the type of blob to transfer
650 * @tsb: the TPMSizeBuffer to fill with the blob
651 * @flags: the flags to return to the caller
652 */
653static int tpm_emulator_get_state_blob(TPMEmulator *tpm_emu,
654 uint8_t type,
655 TPMSizedBuffer *tsb,
656 uint32_t *flags)
657{
658 ptm_getstate pgs;
659 ptm_res res;
660 ssize_t n;
661 uint32_t totlength, length;
662
663 tpm_sized_buffer_reset(tsb);
664
665 pgs.u.req.state_flags = cpu_to_be32(PTM_STATE_FLAG_DECRYPTED);
666 pgs.u.req.type = cpu_to_be32(type);
667 pgs.u.req.offset = 0;
668
669 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_STATEBLOB,
670 &pgs, sizeof(pgs.u.req),
671 offsetof(ptm_getstate, u.resp.data)) < 0) {
672 error_report("tpm-emulator: could not get state blob type %d : %s",
673 type, strerror(errno));
674 return -1;
675 }
676
677 res = be32_to_cpu(pgs.u.resp.tpm_result);
678 if (res != 0 && (res & 0x800) == 0) {
679 error_report("tpm-emulator: Getting the stateblob (type %d) failed "
7e095e84
SB
680 "with a TPM error 0x%x %s", type, res,
681 tpm_emulator_strerror(res));
38ab74e7
SB
682 return -1;
683 }
684
685 totlength = be32_to_cpu(pgs.u.resp.totlength);
686 length = be32_to_cpu(pgs.u.resp.length);
687 if (totlength != length) {
688 error_report("tpm-emulator: Expecting to read %u bytes "
689 "but would get %u", totlength, length);
690 return -1;
691 }
692
693 *flags = be32_to_cpu(pgs.u.resp.state_flags);
694
695 if (totlength > 0) {
696 tsb->buffer = g_try_malloc(totlength);
697 if (!tsb->buffer) {
698 error_report("tpm-emulator: Out of memory allocating %u bytes",
699 totlength);
700 return -1;
701 }
702
703 n = qemu_chr_fe_read_all(&tpm_emu->ctrl_chr, tsb->buffer, totlength);
704 if (n != totlength) {
705 error_report("tpm-emulator: Could not read stateblob (type %d); "
706 "expected %u bytes, got %zd",
707 type, totlength, n);
708 return -1;
709 }
710 }
711 tsb->size = totlength;
712
713 trace_tpm_emulator_get_state_blob(type, tsb->size, *flags);
714
715 return 0;
716}
717
718static int tpm_emulator_get_state_blobs(TPMEmulator *tpm_emu)
719{
720 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
721
722 if (tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_PERMANENT,
723 &state_blobs->permanent,
724 &state_blobs->permanent_flags) < 0 ||
725 tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_VOLATILE,
726 &state_blobs->volatil,
727 &state_blobs->volatil_flags) < 0 ||
728 tpm_emulator_get_state_blob(tpm_emu, PTM_BLOB_TYPE_SAVESTATE,
729 &state_blobs->savestate,
730 &state_blobs->savestate_flags) < 0) {
731 goto err_exit;
732 }
733
734 return 0;
735
736 err_exit:
737 tpm_sized_buffer_reset(&state_blobs->volatil);
738 tpm_sized_buffer_reset(&state_blobs->permanent);
739 tpm_sized_buffer_reset(&state_blobs->savestate);
740
741 return -1;
742}
743
744/*
745 * Transfer a TPM state blob to the TPM emulator.
746 *
747 * @tpm_emu: TPMEmulator
748 * @type: the type of TPM state blob to transfer
749 * @tsb: TPMSizedBuffer containing the TPM state blob
750 * @flags: Flags describing the (encryption) state of the TPM state blob
751 */
752static int tpm_emulator_set_state_blob(TPMEmulator *tpm_emu,
753 uint32_t type,
754 TPMSizedBuffer *tsb,
755 uint32_t flags)
756{
757 ssize_t n;
758 ptm_setstate pss;
759 ptm_res tpm_result;
760
761 if (tsb->size == 0) {
762 return 0;
763 }
764
765 pss = (ptm_setstate) {
766 .u.req.state_flags = cpu_to_be32(flags),
767 .u.req.type = cpu_to_be32(type),
768 .u.req.length = cpu_to_be32(tsb->size),
769 };
770
771 /* write the header only */
772 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_STATEBLOB, &pss,
773 offsetof(ptm_setstate, u.req.data), 0) < 0) {
774 error_report("tpm-emulator: could not set state blob type %d : %s",
775 type, strerror(errno));
776 return -1;
777 }
778
779 /* now the body */
780 n = qemu_chr_fe_write_all(&tpm_emu->ctrl_chr, tsb->buffer, tsb->size);
781 if (n != tsb->size) {
782 error_report("tpm-emulator: Writing the stateblob (type %d) "
783 "failed; could not write %u bytes, but only %zd",
784 type, tsb->size, n);
785 return -1;
786 }
787
788 /* now get the result */
789 n = qemu_chr_fe_read_all(&tpm_emu->ctrl_chr,
790 (uint8_t *)&pss, sizeof(pss.u.resp));
791 if (n != sizeof(pss.u.resp)) {
792 error_report("tpm-emulator: Reading response from writing stateblob "
793 "(type %d) failed; expected %zu bytes, got %zd", type,
794 sizeof(pss.u.resp), n);
795 return -1;
796 }
797
798 tpm_result = be32_to_cpu(pss.u.resp.tpm_result);
799 if (tpm_result != 0) {
800 error_report("tpm-emulator: Setting the stateblob (type %d) failed "
7e095e84
SB
801 "with a TPM error 0x%x %s", type, tpm_result,
802 tpm_emulator_strerror(tpm_result));
38ab74e7
SB
803 return -1;
804 }
805
806 trace_tpm_emulator_set_state_blob(type, tsb->size, flags);
807
808 return 0;
809}
810
811/*
812 * Set all the TPM state blobs.
813 *
814 * Returns a negative errno code in case of error.
815 */
816static int tpm_emulator_set_state_blobs(TPMBackend *tb)
817{
818 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
819 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
820
821 trace_tpm_emulator_set_state_blobs();
822
823 if (tpm_emulator_stop_tpm(tb) < 0) {
824 trace_tpm_emulator_set_state_blobs_error("Could not stop TPM");
825 return -EIO;
826 }
827
828 if (tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_PERMANENT,
829 &state_blobs->permanent,
830 state_blobs->permanent_flags) < 0 ||
831 tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_VOLATILE,
832 &state_blobs->volatil,
833 state_blobs->volatil_flags) < 0 ||
834 tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_SAVESTATE,
835 &state_blobs->savestate,
836 state_blobs->savestate_flags) < 0) {
837 return -EIO;
838 }
839
840 trace_tpm_emulator_set_state_blobs_done();
841
842 return 0;
843}
844
845static int tpm_emulator_pre_save(void *opaque)
846{
847 TPMBackend *tb = opaque;
848 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
849
850 trace_tpm_emulator_pre_save();
851
852 tpm_backend_finish_sync(tb);
853
854 /* get the state blobs from the TPM */
855 return tpm_emulator_get_state_blobs(tpm_emu);
856}
857
858/*
859 * Load the TPM state blobs into the TPM.
860 *
861 * Returns negative errno codes in case of error.
862 */
863static int tpm_emulator_post_load(void *opaque, int version_id)
864{
865 TPMBackend *tb = opaque;
866 int ret;
867
868 ret = tpm_emulator_set_state_blobs(tb);
869 if (ret < 0) {
870 return ret;
871 }
872
873 if (tpm_emulator_startup_tpm_resume(tb, 0, true) < 0) {
874 return -EIO;
875 }
876
877 return 0;
878}
879
880static const VMStateDescription vmstate_tpm_emulator = {
881 .name = "tpm-emulator",
882 .version_id = 0,
883 .pre_save = tpm_emulator_pre_save,
884 .post_load = tpm_emulator_post_load,
885 .fields = (VMStateField[]) {
886 VMSTATE_UINT32(state_blobs.permanent_flags, TPMEmulator),
887 VMSTATE_UINT32(state_blobs.permanent.size, TPMEmulator),
888 VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.permanent.buffer,
889 TPMEmulator, 0, 0,
890 state_blobs.permanent.size),
891
892 VMSTATE_UINT32(state_blobs.volatil_flags, TPMEmulator),
893 VMSTATE_UINT32(state_blobs.volatil.size, TPMEmulator),
894 VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.volatil.buffer,
895 TPMEmulator, 0, 0,
896 state_blobs.volatil.size),
897
898 VMSTATE_UINT32(state_blobs.savestate_flags, TPMEmulator),
899 VMSTATE_UINT32(state_blobs.savestate.size, TPMEmulator),
900 VMSTATE_VBUFFER_ALLOC_UINT32(state_blobs.savestate.buffer,
901 TPMEmulator, 0, 0,
902 state_blobs.savestate.size),
903
904 VMSTATE_END_OF_LIST()
905 }
906};
907
f4ede81e
AV
908static void tpm_emulator_inst_init(Object *obj)
909{
910 TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
911
9d9dcd96
SB
912 trace_tpm_emulator_inst_init();
913
f4ede81e
AV
914 tpm_emu->options = g_new0(TPMEmulatorOptions, 1);
915 tpm_emu->cur_locty_number = ~0;
17b1af77 916 qemu_mutex_init(&tpm_emu->mutex);
38ab74e7
SB
917
918 vmstate_register(NULL, -1, &vmstate_tpm_emulator, obj);
f4ede81e
AV
919}
920
921/*
922 * Gracefully shut down the external TPM
923 */
924static void tpm_emulator_shutdown(TPMEmulator *tpm_emu)
925{
926 ptm_res res;
927
17b1af77 928 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SHUTDOWN, &res, 0, sizeof(res)) < 0) {
f4ede81e
AV
929 error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s",
930 strerror(errno));
931 } else if (res != 0) {
7e095e84
SB
932 error_report("tpm-emulator: TPM result for shutdown: 0x%x %s",
933 be32_to_cpu(res), tpm_emulator_strerror(be32_to_cpu(res)));
f4ede81e
AV
934 }
935}
936
937static void tpm_emulator_inst_finalize(Object *obj)
938{
939 TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
38ab74e7 940 TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
f4ede81e
AV
941
942 tpm_emulator_shutdown(tpm_emu);
943
944 object_unref(OBJECT(tpm_emu->data_ioc));
945
946 qemu_chr_fe_deinit(&tpm_emu->ctrl_chr, false);
947
948 qapi_free_TPMEmulatorOptions(tpm_emu->options);
949
950 if (tpm_emu->migration_blocker) {
951 migrate_del_blocker(tpm_emu->migration_blocker);
952 error_free(tpm_emu->migration_blocker);
953 }
17b1af77 954
38ab74e7
SB
955 tpm_sized_buffer_reset(&state_blobs->volatil);
956 tpm_sized_buffer_reset(&state_blobs->permanent);
957 tpm_sized_buffer_reset(&state_blobs->savestate);
958
17b1af77 959 qemu_mutex_destroy(&tpm_emu->mutex);
38ab74e7
SB
960
961 vmstate_unregister(NULL, &vmstate_tpm_emulator, obj);
f4ede81e
AV
962}
963
964static void tpm_emulator_class_init(ObjectClass *klass, void *data)
965{
966 TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
d31076ba
MAL
967
968 tbc->type = TPM_TYPE_EMULATOR;
969 tbc->opts = tpm_emulator_cmdline_opts;
970 tbc->desc = "TPM emulator backend driver";
971 tbc->create = tpm_emulator_create;
972 tbc->startup_tpm = tpm_emulator_startup_tpm;
973 tbc->cancel_cmd = tpm_emulator_cancel_cmd;
974 tbc->get_tpm_established_flag = tpm_emulator_get_tpm_established_flag;
975 tbc->reset_tpm_established_flag = tpm_emulator_reset_tpm_established_flag;
976 tbc->get_tpm_version = tpm_emulator_get_tpm_version;
b21e6aaf 977 tbc->get_buffer_size = tpm_emulator_get_buffer_size;
d31076ba
MAL
978 tbc->get_tpm_options = tpm_emulator_get_tpm_options;
979
f4ede81e
AV
980 tbc->handle_request = tpm_emulator_handle_request;
981}
982
983static const TypeInfo tpm_emulator_info = {
984 .name = TYPE_TPM_EMULATOR,
985 .parent = TYPE_TPM_BACKEND,
986 .instance_size = sizeof(TPMEmulator),
987 .class_init = tpm_emulator_class_init,
988 .instance_init = tpm_emulator_inst_init,
989 .instance_finalize = tpm_emulator_inst_finalize,
990};
991
992static void tpm_emulator_register(void)
993{
994 type_register_static(&tpm_emulator_info);
f4ede81e
AV
995}
996
997type_init(tpm_emulator_register)
This page took 0.293837 seconds and 4 git commands to generate.