qemu/block/crypto.c
<<
>>
Prefs
   1/*
   2 * QEMU block full disk encryption
   3 *
   4 * Copyright (c) 2015-2016 Red Hat, Inc.
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 *
  19 */
  20
  21#include "qemu/osdep.h"
  22
  23#include "block/block_int.h"
  24#include "sysemu/block-backend.h"
  25#include "crypto/block.h"
  26#include "qapi/opts-visitor.h"
  27#include "qapi/qobject-input-visitor.h"
  28#include "qapi-visit.h"
  29#include "qapi/error.h"
  30#include "block/crypto.h"
  31
  32typedef struct BlockCrypto BlockCrypto;
  33
  34struct BlockCrypto {
  35    QCryptoBlock *block;
  36};
  37
  38
  39static int block_crypto_probe_generic(QCryptoBlockFormat format,
  40                                      const uint8_t *buf,
  41                                      int buf_size,
  42                                      const char *filename)
  43{
  44    if (qcrypto_block_has_format(format, buf, buf_size)) {
  45        return 100;
  46    } else {
  47        return 0;
  48    }
  49}
  50
  51
  52static ssize_t block_crypto_read_func(QCryptoBlock *block,
  53                                      size_t offset,
  54                                      uint8_t *buf,
  55                                      size_t buflen,
  56                                      void *opaque,
  57                                      Error **errp)
  58{
  59    BlockDriverState *bs = opaque;
  60    ssize_t ret;
  61
  62    ret = bdrv_pread(bs->file, offset, buf, buflen);
  63    if (ret < 0) {
  64        error_setg_errno(errp, -ret, "Could not read encryption header");
  65        return ret;
  66    }
  67    return ret;
  68}
  69
  70
  71struct BlockCryptoCreateData {
  72    const char *filename;
  73    QemuOpts *opts;
  74    BlockBackend *blk;
  75    uint64_t size;
  76};
  77
  78
  79static ssize_t block_crypto_write_func(QCryptoBlock *block,
  80                                       size_t offset,
  81                                       const uint8_t *buf,
  82                                       size_t buflen,
  83                                       void *opaque,
  84                                       Error **errp)
  85{
  86    struct BlockCryptoCreateData *data = opaque;
  87    ssize_t ret;
  88
  89    ret = blk_pwrite(data->blk, offset, buf, buflen, 0);
  90    if (ret < 0) {
  91        error_setg_errno(errp, -ret, "Could not write encryption header");
  92        return ret;
  93    }
  94    return ret;
  95}
  96
  97
  98static ssize_t block_crypto_init_func(QCryptoBlock *block,
  99                                      size_t headerlen,
 100                                      void *opaque,
 101                                      Error **errp)
 102{
 103    struct BlockCryptoCreateData *data = opaque;
 104    int ret;
 105
 106    /* User provided size should reflect amount of space made
 107     * available to the guest, so we must take account of that
 108     * which will be used by the crypto header
 109     */
 110    data->size += headerlen;
 111
 112    qemu_opt_set_number(data->opts, BLOCK_OPT_SIZE, data->size, &error_abort);
 113    ret = bdrv_create_file(data->filename, data->opts, errp);
 114    if (ret < 0) {
 115        return -1;
 116    }
 117
 118    data->blk = blk_new_open(data->filename, NULL, NULL,
 119                             BDRV_O_RDWR | BDRV_O_PROTOCOL, errp);
 120    if (!data->blk) {
 121        return -1;
 122    }
 123
 124    return 0;
 125}
 126
 127
 128static QemuOptsList block_crypto_runtime_opts_luks = {
 129    .name = "crypto",
 130    .head = QTAILQ_HEAD_INITIALIZER(block_crypto_runtime_opts_luks.head),
 131    .desc = {
 132        BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(""),
 133        { /* end of list */ }
 134    },
 135};
 136
 137
 138static QemuOptsList block_crypto_create_opts_luks = {
 139    .name = "crypto",
 140    .head = QTAILQ_HEAD_INITIALIZER(block_crypto_create_opts_luks.head),
 141    .desc = {
 142        {
 143            .name = BLOCK_OPT_SIZE,
 144            .type = QEMU_OPT_SIZE,
 145            .help = "Virtual disk size"
 146        },
 147        BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(""),
 148        BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG(""),
 149        BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE(""),
 150        BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG(""),
 151        BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(""),
 152        BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(""),
 153        BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""),
 154        { /* end of list */ }
 155    },
 156};
 157
 158
 159QCryptoBlockOpenOptions *
 160block_crypto_open_opts_init(QCryptoBlockFormat format,
 161                            QDict *opts,
 162                            Error **errp)
 163{
 164    Visitor *v;
 165    QCryptoBlockOpenOptions *ret = NULL;
 166    Error *local_err = NULL;
 167
 168    ret = g_new0(QCryptoBlockOpenOptions, 1);
 169    ret->format = format;
 170
 171    v = qobject_input_visitor_new_keyval(QOBJECT(opts));
 172
 173    visit_start_struct(v, NULL, NULL, 0, &local_err);
 174    if (local_err) {
 175        goto out;
 176    }
 177
 178    switch (format) {
 179    case Q_CRYPTO_BLOCK_FORMAT_LUKS:
 180        visit_type_QCryptoBlockOptionsLUKS_members(
 181            v, &ret->u.luks, &local_err);
 182        break;
 183
 184    case Q_CRYPTO_BLOCK_FORMAT_QCOW:
 185        visit_type_QCryptoBlockOptionsQCow_members(
 186            v, &ret->u.qcow, &local_err);
 187        break;
 188
 189    default:
 190        error_setg(&local_err, "Unsupported block format %d", format);
 191        break;
 192    }
 193    if (!local_err) {
 194        visit_check_struct(v, &local_err);
 195    }
 196
 197    visit_end_struct(v, NULL);
 198
 199 out:
 200    if (local_err) {
 201        error_propagate(errp, local_err);
 202        qapi_free_QCryptoBlockOpenOptions(ret);
 203        ret = NULL;
 204    }
 205    visit_free(v);
 206    return ret;
 207}
 208
 209
 210QCryptoBlockCreateOptions *
 211block_crypto_create_opts_init(QCryptoBlockFormat format,
 212                              QDict *opts,
 213                              Error **errp)
 214{
 215    Visitor *v;
 216    QCryptoBlockCreateOptions *ret = NULL;
 217    Error *local_err = NULL;
 218
 219    ret = g_new0(QCryptoBlockCreateOptions, 1);
 220    ret->format = format;
 221
 222    v = qobject_input_visitor_new_keyval(QOBJECT(opts));
 223
 224    visit_start_struct(v, NULL, NULL, 0, &local_err);
 225    if (local_err) {
 226        goto out;
 227    }
 228
 229    switch (format) {
 230    case Q_CRYPTO_BLOCK_FORMAT_LUKS:
 231        visit_type_QCryptoBlockCreateOptionsLUKS_members(
 232            v, &ret->u.luks, &local_err);
 233        break;
 234
 235    case Q_CRYPTO_BLOCK_FORMAT_QCOW:
 236        visit_type_QCryptoBlockOptionsQCow_members(
 237            v, &ret->u.qcow, &local_err);
 238        break;
 239
 240    default:
 241        error_setg(&local_err, "Unsupported block format %d", format);
 242        break;
 243    }
 244    if (!local_err) {
 245        visit_check_struct(v, &local_err);
 246    }
 247
 248    visit_end_struct(v, NULL);
 249
 250 out:
 251    if (local_err) {
 252        error_propagate(errp, local_err);
 253        qapi_free_QCryptoBlockCreateOptions(ret);
 254        ret = NULL;
 255    }
 256    visit_free(v);
 257    return ret;
 258}
 259
 260
 261static int block_crypto_open_generic(QCryptoBlockFormat format,
 262                                     QemuOptsList *opts_spec,
 263                                     BlockDriverState *bs,
 264                                     QDict *options,
 265                                     int flags,
 266                                     Error **errp)
 267{
 268    BlockCrypto *crypto = bs->opaque;
 269    QemuOpts *opts = NULL;
 270    Error *local_err = NULL;
 271    int ret = -EINVAL;
 272    QCryptoBlockOpenOptions *open_opts = NULL;
 273    unsigned int cflags = 0;
 274    QDict *cryptoopts = NULL;
 275
 276    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
 277                               false, errp);
 278    if (!bs->file) {
 279        return -EINVAL;
 280    }
 281
 282    bs->supported_write_flags = BDRV_REQ_FUA &
 283        bs->file->bs->supported_write_flags;
 284
 285    opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort);
 286    qemu_opts_absorb_qdict(opts, options, &local_err);
 287    if (local_err) {
 288        error_propagate(errp, local_err);
 289        goto cleanup;
 290    }
 291
 292    cryptoopts = qemu_opts_to_qdict(opts, NULL);
 293
 294    open_opts = block_crypto_open_opts_init(format, cryptoopts, errp);
 295    if (!open_opts) {
 296        goto cleanup;
 297    }
 298
 299    if (flags & BDRV_O_NO_IO) {
 300        cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
 301    }
 302    crypto->block = qcrypto_block_open(open_opts, NULL,
 303                                       block_crypto_read_func,
 304                                       bs,
 305                                       cflags,
 306                                       errp);
 307
 308    if (!crypto->block) {
 309        ret = -EIO;
 310        goto cleanup;
 311    }
 312
 313    bs->encrypted = true;
 314
 315    ret = 0;
 316 cleanup:
 317    QDECREF(cryptoopts);
 318    qapi_free_QCryptoBlockOpenOptions(open_opts);
 319    return ret;
 320}
 321
 322
 323static int block_crypto_create_generic(QCryptoBlockFormat format,
 324                                       const char *filename,
 325                                       QemuOpts *opts,
 326                                       Error **errp)
 327{
 328    int ret = -EINVAL;
 329    QCryptoBlockCreateOptions *create_opts = NULL;
 330    QCryptoBlock *crypto = NULL;
 331    struct BlockCryptoCreateData data = {
 332        .size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
 333                         BDRV_SECTOR_SIZE),
 334        .opts = opts,
 335        .filename = filename,
 336    };
 337    QDict *cryptoopts;
 338
 339    cryptoopts = qemu_opts_to_qdict(opts, NULL);
 340
 341    create_opts = block_crypto_create_opts_init(format, cryptoopts, errp);
 342    if (!create_opts) {
 343        return -1;
 344    }
 345
 346    crypto = qcrypto_block_create(create_opts, NULL,
 347                                  block_crypto_init_func,
 348                                  block_crypto_write_func,
 349                                  &data,
 350                                  errp);
 351
 352    if (!crypto) {
 353        ret = -EIO;
 354        goto cleanup;
 355    }
 356
 357    ret = 0;
 358 cleanup:
 359    QDECREF(cryptoopts);
 360    qcrypto_block_free(crypto);
 361    blk_unref(data.blk);
 362    qapi_free_QCryptoBlockCreateOptions(create_opts);
 363    return ret;
 364}
 365
 366static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
 367                                 PreallocMode prealloc, Error **errp)
 368{
 369    BlockCrypto *crypto = bs->opaque;
 370    uint64_t payload_offset =
 371        qcrypto_block_get_payload_offset(crypto->block);
 372    assert(payload_offset < (INT64_MAX - offset));
 373
 374    offset += payload_offset;
 375
 376    return bdrv_truncate(bs->file, offset, prealloc, errp);
 377}
 378
 379static void block_crypto_close(BlockDriverState *bs)
 380{
 381    BlockCrypto *crypto = bs->opaque;
 382    qcrypto_block_free(crypto->block);
 383}
 384
 385
 386/*
 387 * 1 MB bounce buffer gives good performance / memory tradeoff
 388 * when using cache=none|directsync.
 389 */
 390#define BLOCK_CRYPTO_MAX_IO_SIZE (1024 * 1024)
 391
 392static coroutine_fn int
 393block_crypto_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
 394                       QEMUIOVector *qiov, int flags)
 395{
 396    BlockCrypto *crypto = bs->opaque;
 397    uint64_t cur_bytes; /* number of bytes in current iteration */
 398    uint64_t bytes_done = 0;
 399    uint8_t *cipher_data = NULL;
 400    QEMUIOVector hd_qiov;
 401    int ret = 0;
 402    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
 403    uint64_t payload_offset = qcrypto_block_get_payload_offset(crypto->block);
 404
 405    assert(!flags);
 406    assert(payload_offset < INT64_MAX);
 407    assert(QEMU_IS_ALIGNED(offset, sector_size));
 408    assert(QEMU_IS_ALIGNED(bytes, sector_size));
 409
 410    qemu_iovec_init(&hd_qiov, qiov->niov);
 411
 412    /* Bounce buffer because we don't wish to expose cipher text
 413     * in qiov which points to guest memory.
 414     */
 415    cipher_data =
 416        qemu_try_blockalign(bs->file->bs, MIN(BLOCK_CRYPTO_MAX_IO_SIZE,
 417                                              qiov->size));
 418    if (cipher_data == NULL) {
 419        ret = -ENOMEM;
 420        goto cleanup;
 421    }
 422
 423    while (bytes) {
 424        cur_bytes = MIN(bytes, BLOCK_CRYPTO_MAX_IO_SIZE);
 425
 426        qemu_iovec_reset(&hd_qiov);
 427        qemu_iovec_add(&hd_qiov, cipher_data, cur_bytes);
 428
 429        ret = bdrv_co_preadv(bs->file, payload_offset + offset + bytes_done,
 430                             cur_bytes, &hd_qiov, 0);
 431        if (ret < 0) {
 432            goto cleanup;
 433        }
 434
 435        if (qcrypto_block_decrypt(crypto->block, offset + bytes_done,
 436                                  cipher_data, cur_bytes, NULL) < 0) {
 437            ret = -EIO;
 438            goto cleanup;
 439        }
 440
 441        qemu_iovec_from_buf(qiov, bytes_done, cipher_data, cur_bytes);
 442
 443        bytes -= cur_bytes;
 444        bytes_done += cur_bytes;
 445    }
 446
 447 cleanup:
 448    qemu_iovec_destroy(&hd_qiov);
 449    qemu_vfree(cipher_data);
 450
 451    return ret;
 452}
 453
 454
 455static coroutine_fn int
 456block_crypto_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
 457                        QEMUIOVector *qiov, int flags)
 458{
 459    BlockCrypto *crypto = bs->opaque;
 460    uint64_t cur_bytes; /* number of bytes in current iteration */
 461    uint64_t bytes_done = 0;
 462    uint8_t *cipher_data = NULL;
 463    QEMUIOVector hd_qiov;
 464    int ret = 0;
 465    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
 466    uint64_t payload_offset = qcrypto_block_get_payload_offset(crypto->block);
 467
 468    assert(!(flags & ~BDRV_REQ_FUA));
 469    assert(payload_offset < INT64_MAX);
 470    assert(QEMU_IS_ALIGNED(offset, sector_size));
 471    assert(QEMU_IS_ALIGNED(bytes, sector_size));
 472
 473    qemu_iovec_init(&hd_qiov, qiov->niov);
 474
 475    /* Bounce buffer because we're not permitted to touch
 476     * contents of qiov - it points to guest memory.
 477     */
 478    cipher_data =
 479        qemu_try_blockalign(bs->file->bs, MIN(BLOCK_CRYPTO_MAX_IO_SIZE,
 480                                              qiov->size));
 481    if (cipher_data == NULL) {
 482        ret = -ENOMEM;
 483        goto cleanup;
 484    }
 485
 486    while (bytes) {
 487        cur_bytes = MIN(bytes, BLOCK_CRYPTO_MAX_IO_SIZE);
 488
 489        qemu_iovec_to_buf(qiov, bytes_done, cipher_data, cur_bytes);
 490
 491        if (qcrypto_block_encrypt(crypto->block, offset + bytes_done,
 492                                  cipher_data, cur_bytes, NULL) < 0) {
 493            ret = -EIO;
 494            goto cleanup;
 495        }
 496
 497        qemu_iovec_reset(&hd_qiov);
 498        qemu_iovec_add(&hd_qiov, cipher_data, cur_bytes);
 499
 500        ret = bdrv_co_pwritev(bs->file, payload_offset + offset + bytes_done,
 501                              cur_bytes, &hd_qiov, flags);
 502        if (ret < 0) {
 503            goto cleanup;
 504        }
 505
 506        bytes -= cur_bytes;
 507        bytes_done += cur_bytes;
 508    }
 509
 510 cleanup:
 511    qemu_iovec_destroy(&hd_qiov);
 512    qemu_vfree(cipher_data);
 513
 514    return ret;
 515}
 516
 517static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp)
 518{
 519    BlockCrypto *crypto = bs->opaque;
 520    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
 521    bs->bl.request_alignment = sector_size; /* No sub-sector I/O */
 522}
 523
 524
 525static int64_t block_crypto_getlength(BlockDriverState *bs)
 526{
 527    BlockCrypto *crypto = bs->opaque;
 528    int64_t len = bdrv_getlength(bs->file->bs);
 529
 530    uint64_t offset = qcrypto_block_get_payload_offset(crypto->block);
 531    assert(offset < INT64_MAX);
 532    assert(offset < len);
 533
 534    len -= offset;
 535
 536    return len;
 537}
 538
 539
 540static int block_crypto_probe_luks(const uint8_t *buf,
 541                                   int buf_size,
 542                                   const char *filename) {
 543    return block_crypto_probe_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 544                                      buf, buf_size, filename);
 545}
 546
 547static int block_crypto_open_luks(BlockDriverState *bs,
 548                                  QDict *options,
 549                                  int flags,
 550                                  Error **errp)
 551{
 552    return block_crypto_open_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 553                                     &block_crypto_runtime_opts_luks,
 554                                     bs, options, flags, errp);
 555}
 556
 557static int block_crypto_create_luks(const char *filename,
 558                                    QemuOpts *opts,
 559                                    Error **errp)
 560{
 561    return block_crypto_create_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 562                                       filename, opts, errp);
 563}
 564
 565static int block_crypto_get_info_luks(BlockDriverState *bs,
 566                                      BlockDriverInfo *bdi)
 567{
 568    BlockDriverInfo subbdi;
 569    int ret;
 570
 571    ret = bdrv_get_info(bs->file->bs, &subbdi);
 572    if (ret != 0) {
 573        return ret;
 574    }
 575
 576    bdi->unallocated_blocks_are_zero = false;
 577    bdi->can_write_zeroes_with_unmap = false;
 578    bdi->cluster_size = subbdi.cluster_size;
 579
 580    return 0;
 581}
 582
 583static ImageInfoSpecific *
 584block_crypto_get_specific_info_luks(BlockDriverState *bs)
 585{
 586    BlockCrypto *crypto = bs->opaque;
 587    ImageInfoSpecific *spec_info;
 588    QCryptoBlockInfo *info;
 589
 590    info = qcrypto_block_get_info(crypto->block, NULL);
 591    if (!info) {
 592        return NULL;
 593    }
 594    if (info->format != Q_CRYPTO_BLOCK_FORMAT_LUKS) {
 595        qapi_free_QCryptoBlockInfo(info);
 596        return NULL;
 597    }
 598
 599    spec_info = g_new(ImageInfoSpecific, 1);
 600    spec_info->type = IMAGE_INFO_SPECIFIC_KIND_LUKS;
 601    spec_info->u.luks.data = g_new(QCryptoBlockInfoLUKS, 1);
 602    *spec_info->u.luks.data = info->u.luks;
 603
 604    /* Blank out pointers we've just stolen to avoid double free */
 605    memset(&info->u.luks, 0, sizeof(info->u.luks));
 606
 607    qapi_free_QCryptoBlockInfo(info);
 608
 609    return spec_info;
 610}
 611
 612BlockDriver bdrv_crypto_luks = {
 613    .format_name        = "luks",
 614    .instance_size      = sizeof(BlockCrypto),
 615    .bdrv_probe         = block_crypto_probe_luks,
 616    .bdrv_open          = block_crypto_open_luks,
 617    .bdrv_close         = block_crypto_close,
 618    .bdrv_child_perm    = bdrv_format_default_perms,
 619    .bdrv_create        = block_crypto_create_luks,
 620    .bdrv_truncate      = block_crypto_truncate,
 621    .create_opts        = &block_crypto_create_opts_luks,
 622
 623    .bdrv_refresh_limits = block_crypto_refresh_limits,
 624    .bdrv_co_preadv     = block_crypto_co_preadv,
 625    .bdrv_co_pwritev    = block_crypto_co_pwritev,
 626    .bdrv_getlength     = block_crypto_getlength,
 627    .bdrv_get_info      = block_crypto_get_info_luks,
 628    .bdrv_get_specific_info = block_crypto_get_specific_info_luks,
 629};
 630
 631static void block_crypto_init(void)
 632{
 633    bdrv_register(&bdrv_crypto_luks);
 634}
 635
 636block_init(block_crypto_init);
 637