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