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