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 "block/qdict.h"
  25#include "sysemu/block-backend.h"
  26#include "crypto/block.h"
  27#include "qapi/opts-visitor.h"
  28#include "qapi/qapi-visit-crypto.h"
  29#include "qapi/qobject-input-visitor.h"
  30#include "qapi/error.h"
  31#include "qemu/module.h"
  32#include "qemu/option.h"
  33#include "crypto.h"
  34
  35typedef struct BlockCrypto BlockCrypto;
  36
  37struct BlockCrypto {
  38    QCryptoBlock *block;
  39};
  40
  41
  42static int block_crypto_probe_generic(QCryptoBlockFormat format,
  43                                      const uint8_t *buf,
  44                                      int buf_size,
  45                                      const char *filename)
  46{
  47    if (qcrypto_block_has_format(format, buf, buf_size)) {
  48        return 100;
  49    } else {
  50        return 0;
  51    }
  52}
  53
  54
  55static ssize_t block_crypto_read_func(QCryptoBlock *block,
  56                                      size_t offset,
  57                                      uint8_t *buf,
  58                                      size_t buflen,
  59                                      void *opaque,
  60                                      Error **errp)
  61{
  62    BlockDriverState *bs = opaque;
  63    ssize_t ret;
  64
  65    ret = bdrv_pread(bs->file, offset, buf, buflen);
  66    if (ret < 0) {
  67        error_setg_errno(errp, -ret, "Could not read encryption header");
  68        return ret;
  69    }
  70    return ret;
  71}
  72
  73
  74struct BlockCryptoCreateData {
  75    BlockBackend *blk;
  76    uint64_t size;
  77};
  78
  79
  80static ssize_t block_crypto_write_func(QCryptoBlock *block,
  81                                       size_t offset,
  82                                       const uint8_t *buf,
  83                                       size_t buflen,
  84                                       void *opaque,
  85                                       Error **errp)
  86{
  87    struct BlockCryptoCreateData *data = opaque;
  88    ssize_t ret;
  89
  90    ret = blk_pwrite(data->blk, offset, buf, buflen, 0);
  91    if (ret < 0) {
  92        error_setg_errno(errp, -ret, "Could not write encryption header");
  93        return ret;
  94    }
  95    return ret;
  96}
  97
  98
  99static ssize_t block_crypto_init_func(QCryptoBlock *block,
 100                                      size_t headerlen,
 101                                      void *opaque,
 102                                      Error **errp)
 103{
 104    struct BlockCryptoCreateData *data = opaque;
 105
 106    if (data->size > INT64_MAX || headerlen > INT64_MAX - data->size) {
 107        error_setg(errp, "The requested file size is too large");
 108        return -EFBIG;
 109    }
 110
 111    /* User provided size should reflect amount of space made
 112     * available to the guest, so we must take account of that
 113     * which will be used by the crypto header
 114     */
 115    return blk_truncate(data->blk, data->size + headerlen, PREALLOC_MODE_OFF,
 116                        errp);
 117}
 118
 119
 120static QemuOptsList block_crypto_runtime_opts_luks = {
 121    .name = "crypto",
 122    .head = QTAILQ_HEAD_INITIALIZER(block_crypto_runtime_opts_luks.head),
 123    .desc = {
 124        BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(""),
 125        { /* end of list */ }
 126    },
 127};
 128
 129
 130static QemuOptsList block_crypto_create_opts_luks = {
 131    .name = "crypto",
 132    .head = QTAILQ_HEAD_INITIALIZER(block_crypto_create_opts_luks.head),
 133    .desc = {
 134        {
 135            .name = BLOCK_OPT_SIZE,
 136            .type = QEMU_OPT_SIZE,
 137            .help = "Virtual disk size"
 138        },
 139        BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(""),
 140        BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG(""),
 141        BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE(""),
 142        BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG(""),
 143        BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(""),
 144        BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(""),
 145        BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""),
 146        { /* end of list */ }
 147    },
 148};
 149
 150
 151QCryptoBlockOpenOptions *
 152block_crypto_open_opts_init(QDict *opts, Error **errp)
 153{
 154    Visitor *v;
 155    QCryptoBlockOpenOptions *ret;
 156
 157    v = qobject_input_visitor_new_flat_confused(opts, errp);
 158    if (!v) {
 159        return NULL;
 160    }
 161
 162    visit_type_QCryptoBlockOpenOptions(v, NULL, &ret, errp);
 163
 164    visit_free(v);
 165    return ret;
 166}
 167
 168
 169QCryptoBlockCreateOptions *
 170block_crypto_create_opts_init(QDict *opts, Error **errp)
 171{
 172    Visitor *v;
 173    QCryptoBlockCreateOptions *ret;
 174
 175    v = qobject_input_visitor_new_flat_confused(opts, errp);
 176    if (!v) {
 177        return NULL;
 178    }
 179
 180    visit_type_QCryptoBlockCreateOptions(v, NULL, &ret, errp);
 181
 182    visit_free(v);
 183    return ret;
 184}
 185
 186
 187static int block_crypto_open_generic(QCryptoBlockFormat format,
 188                                     QemuOptsList *opts_spec,
 189                                     BlockDriverState *bs,
 190                                     QDict *options,
 191                                     int flags,
 192                                     Error **errp)
 193{
 194    BlockCrypto *crypto = bs->opaque;
 195    QemuOpts *opts = NULL;
 196    Error *local_err = NULL;
 197    int ret = -EINVAL;
 198    QCryptoBlockOpenOptions *open_opts = NULL;
 199    unsigned int cflags = 0;
 200    QDict *cryptoopts = NULL;
 201
 202    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
 203                               false, errp);
 204    if (!bs->file) {
 205        return -EINVAL;
 206    }
 207
 208    bs->supported_write_flags = BDRV_REQ_FUA &
 209        bs->file->bs->supported_write_flags;
 210
 211    opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort);
 212    qemu_opts_absorb_qdict(opts, options, &local_err);
 213    if (local_err) {
 214        error_propagate(errp, local_err);
 215        goto cleanup;
 216    }
 217
 218    cryptoopts = qemu_opts_to_qdict(opts, NULL);
 219    qdict_put_str(cryptoopts, "format", QCryptoBlockFormat_str(format));
 220
 221    open_opts = block_crypto_open_opts_init(cryptoopts, errp);
 222    if (!open_opts) {
 223        goto cleanup;
 224    }
 225
 226    if (flags & BDRV_O_NO_IO) {
 227        cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
 228    }
 229    crypto->block = qcrypto_block_open(open_opts, NULL,
 230                                       block_crypto_read_func,
 231                                       bs,
 232                                       cflags,
 233                                       1,
 234                                       errp);
 235
 236    if (!crypto->block) {
 237        ret = -EIO;
 238        goto cleanup;
 239    }
 240
 241    bs->encrypted = true;
 242
 243    ret = 0;
 244 cleanup:
 245    qobject_unref(cryptoopts);
 246    qapi_free_QCryptoBlockOpenOptions(open_opts);
 247    return ret;
 248}
 249
 250
 251static int block_crypto_co_create_generic(BlockDriverState *bs,
 252                                          int64_t size,
 253                                          QCryptoBlockCreateOptions *opts,
 254                                          Error **errp)
 255{
 256    int ret;
 257    BlockBackend *blk;
 258    QCryptoBlock *crypto = NULL;
 259    struct BlockCryptoCreateData data;
 260
 261    blk = blk_new(bdrv_get_aio_context(bs),
 262                  BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
 263
 264    ret = blk_insert_bs(blk, bs, errp);
 265    if (ret < 0) {
 266        goto cleanup;
 267    }
 268
 269    data = (struct BlockCryptoCreateData) {
 270        .blk = blk,
 271        .size = size,
 272    };
 273
 274    crypto = qcrypto_block_create(opts, NULL,
 275                                  block_crypto_init_func,
 276                                  block_crypto_write_func,
 277                                  &data,
 278                                  errp);
 279
 280    if (!crypto) {
 281        ret = -EIO;
 282        goto cleanup;
 283    }
 284
 285    ret = 0;
 286 cleanup:
 287    qcrypto_block_free(crypto);
 288    blk_unref(blk);
 289    return ret;
 290}
 291
 292static int coroutine_fn
 293block_crypto_co_truncate(BlockDriverState *bs, int64_t offset,
 294                         PreallocMode prealloc, Error **errp)
 295{
 296    BlockCrypto *crypto = bs->opaque;
 297    uint64_t payload_offset =
 298        qcrypto_block_get_payload_offset(crypto->block);
 299
 300    if (payload_offset > INT64_MAX - offset) {
 301        error_setg(errp, "The requested file size is too large");
 302        return -EFBIG;
 303    }
 304
 305    offset += payload_offset;
 306
 307    return bdrv_co_truncate(bs->file, offset, prealloc, errp);
 308}
 309
 310static void block_crypto_close(BlockDriverState *bs)
 311{
 312    BlockCrypto *crypto = bs->opaque;
 313    qcrypto_block_free(crypto->block);
 314}
 315
 316static int block_crypto_reopen_prepare(BDRVReopenState *state,
 317                                       BlockReopenQueue *queue, Error **errp)
 318{
 319    /* nothing needs checking */
 320    return 0;
 321}
 322
 323/*
 324 * 1 MB bounce buffer gives good performance / memory tradeoff
 325 * when using cache=none|directsync.
 326 */
 327#define BLOCK_CRYPTO_MAX_IO_SIZE (1024 * 1024)
 328
 329static coroutine_fn int
 330block_crypto_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
 331                       QEMUIOVector *qiov, int flags)
 332{
 333    BlockCrypto *crypto = bs->opaque;
 334    uint64_t cur_bytes; /* number of bytes in current iteration */
 335    uint64_t bytes_done = 0;
 336    uint8_t *cipher_data = NULL;
 337    QEMUIOVector hd_qiov;
 338    int ret = 0;
 339    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
 340    uint64_t payload_offset = qcrypto_block_get_payload_offset(crypto->block);
 341
 342    assert(!flags);
 343    assert(payload_offset < INT64_MAX);
 344    assert(QEMU_IS_ALIGNED(offset, sector_size));
 345    assert(QEMU_IS_ALIGNED(bytes, sector_size));
 346
 347    qemu_iovec_init(&hd_qiov, qiov->niov);
 348
 349    /* Bounce buffer because we don't wish to expose cipher text
 350     * in qiov which points to guest memory.
 351     */
 352    cipher_data =
 353        qemu_try_blockalign(bs->file->bs, MIN(BLOCK_CRYPTO_MAX_IO_SIZE,
 354                                              qiov->size));
 355    if (cipher_data == NULL) {
 356        ret = -ENOMEM;
 357        goto cleanup;
 358    }
 359
 360    while (bytes) {
 361        cur_bytes = MIN(bytes, BLOCK_CRYPTO_MAX_IO_SIZE);
 362
 363        qemu_iovec_reset(&hd_qiov);
 364        qemu_iovec_add(&hd_qiov, cipher_data, cur_bytes);
 365
 366        ret = bdrv_co_preadv(bs->file, payload_offset + offset + bytes_done,
 367                             cur_bytes, &hd_qiov, 0);
 368        if (ret < 0) {
 369            goto cleanup;
 370        }
 371
 372        if (qcrypto_block_decrypt(crypto->block, offset + bytes_done,
 373                                  cipher_data, cur_bytes, NULL) < 0) {
 374            ret = -EIO;
 375            goto cleanup;
 376        }
 377
 378        qemu_iovec_from_buf(qiov, bytes_done, cipher_data, cur_bytes);
 379
 380        bytes -= cur_bytes;
 381        bytes_done += cur_bytes;
 382    }
 383
 384 cleanup:
 385    qemu_iovec_destroy(&hd_qiov);
 386    qemu_vfree(cipher_data);
 387
 388    return ret;
 389}
 390
 391
 392static coroutine_fn int
 393block_crypto_co_pwritev(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 & ~BDRV_REQ_FUA));
 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're not permitted to touch
 413     * contents of qiov - it 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_to_buf(qiov, bytes_done, cipher_data, cur_bytes);
 427
 428        if (qcrypto_block_encrypt(crypto->block, offset + bytes_done,
 429                                  cipher_data, cur_bytes, NULL) < 0) {
 430            ret = -EIO;
 431            goto cleanup;
 432        }
 433
 434        qemu_iovec_reset(&hd_qiov);
 435        qemu_iovec_add(&hd_qiov, cipher_data, cur_bytes);
 436
 437        ret = bdrv_co_pwritev(bs->file, payload_offset + offset + bytes_done,
 438                              cur_bytes, &hd_qiov, flags);
 439        if (ret < 0) {
 440            goto cleanup;
 441        }
 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
 454static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp)
 455{
 456    BlockCrypto *crypto = bs->opaque;
 457    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
 458    bs->bl.request_alignment = sector_size; /* No sub-sector I/O */
 459}
 460
 461
 462static int64_t block_crypto_getlength(BlockDriverState *bs)
 463{
 464    BlockCrypto *crypto = bs->opaque;
 465    int64_t len = bdrv_getlength(bs->file->bs);
 466
 467    uint64_t offset = qcrypto_block_get_payload_offset(crypto->block);
 468    assert(offset < INT64_MAX);
 469
 470    if (offset > len) {
 471        return -EIO;
 472    }
 473
 474    len -= offset;
 475
 476    return len;
 477}
 478
 479
 480static int block_crypto_probe_luks(const uint8_t *buf,
 481                                   int buf_size,
 482                                   const char *filename) {
 483    return block_crypto_probe_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 484                                      buf, buf_size, filename);
 485}
 486
 487static int block_crypto_open_luks(BlockDriverState *bs,
 488                                  QDict *options,
 489                                  int flags,
 490                                  Error **errp)
 491{
 492    return block_crypto_open_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 493                                     &block_crypto_runtime_opts_luks,
 494                                     bs, options, flags, errp);
 495}
 496
 497static int coroutine_fn
 498block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
 499{
 500    BlockdevCreateOptionsLUKS *luks_opts;
 501    BlockDriverState *bs = NULL;
 502    QCryptoBlockCreateOptions create_opts;
 503    int ret;
 504
 505    assert(create_options->driver == BLOCKDEV_DRIVER_LUKS);
 506    luks_opts = &create_options->u.luks;
 507
 508    bs = bdrv_open_blockdev_ref(luks_opts->file, errp);
 509    if (bs == NULL) {
 510        return -EIO;
 511    }
 512
 513    create_opts = (QCryptoBlockCreateOptions) {
 514        .format = Q_CRYPTO_BLOCK_FORMAT_LUKS,
 515        .u.luks = *qapi_BlockdevCreateOptionsLUKS_base(luks_opts),
 516    };
 517
 518    ret = block_crypto_co_create_generic(bs, luks_opts->size, &create_opts,
 519                                         errp);
 520    if (ret < 0) {
 521        goto fail;
 522    }
 523
 524    ret = 0;
 525fail:
 526    bdrv_unref(bs);
 527    return ret;
 528}
 529
 530static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
 531                                                         QemuOpts *opts,
 532                                                         Error **errp)
 533{
 534    QCryptoBlockCreateOptions *create_opts = NULL;
 535    BlockDriverState *bs = NULL;
 536    QDict *cryptoopts;
 537    int64_t size;
 538    int ret;
 539
 540    /* Parse options */
 541    size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
 542
 543    cryptoopts = qemu_opts_to_qdict_filtered(opts, NULL,
 544                                             &block_crypto_create_opts_luks,
 545                                             true);
 546
 547    qdict_put_str(cryptoopts, "format", "luks");
 548    create_opts = block_crypto_create_opts_init(cryptoopts, errp);
 549    if (!create_opts) {
 550        ret = -EINVAL;
 551        goto fail;
 552    }
 553
 554    /* Create protocol layer */
 555    ret = bdrv_create_file(filename, opts, errp);
 556    if (ret < 0) {
 557        goto fail;
 558    }
 559
 560    bs = bdrv_open(filename, NULL, NULL,
 561                   BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
 562    if (!bs) {
 563        ret = -EINVAL;
 564        goto fail;
 565    }
 566
 567    /* Create format layer */
 568    ret = block_crypto_co_create_generic(bs, size, create_opts, errp);
 569    if (ret < 0) {
 570        goto fail;
 571    }
 572
 573    ret = 0;
 574fail:
 575    bdrv_unref(bs);
 576    qapi_free_QCryptoBlockCreateOptions(create_opts);
 577    qobject_unref(cryptoopts);
 578    return ret;
 579}
 580
 581static int block_crypto_get_info_luks(BlockDriverState *bs,
 582                                      BlockDriverInfo *bdi)
 583{
 584    BlockDriverInfo subbdi;
 585    int ret;
 586
 587    ret = bdrv_get_info(bs->file->bs, &subbdi);
 588    if (ret != 0) {
 589        return ret;
 590    }
 591
 592    bdi->unallocated_blocks_are_zero = false;
 593    bdi->cluster_size = subbdi.cluster_size;
 594
 595    return 0;
 596}
 597
 598static ImageInfoSpecific *
 599block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp)
 600{
 601    BlockCrypto *crypto = bs->opaque;
 602    ImageInfoSpecific *spec_info;
 603    QCryptoBlockInfo *info;
 604
 605    info = qcrypto_block_get_info(crypto->block, errp);
 606    if (!info) {
 607        return NULL;
 608    }
 609    assert(info->format == Q_CRYPTO_BLOCK_FORMAT_LUKS);
 610
 611    spec_info = g_new(ImageInfoSpecific, 1);
 612    spec_info->type = IMAGE_INFO_SPECIFIC_KIND_LUKS;
 613    spec_info->u.luks.data = g_new(QCryptoBlockInfoLUKS, 1);
 614    *spec_info->u.luks.data = info->u.luks;
 615
 616    /* Blank out pointers we've just stolen to avoid double free */
 617    memset(&info->u.luks, 0, sizeof(info->u.luks));
 618
 619    qapi_free_QCryptoBlockInfo(info);
 620
 621    return spec_info;
 622}
 623
 624static const char *const block_crypto_strong_runtime_opts[] = {
 625    BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
 626
 627    NULL
 628};
 629
 630static BlockDriver bdrv_crypto_luks = {
 631    .format_name        = "luks",
 632    .instance_size      = sizeof(BlockCrypto),
 633    .bdrv_probe         = block_crypto_probe_luks,
 634    .bdrv_open          = block_crypto_open_luks,
 635    .bdrv_close         = block_crypto_close,
 636    /* This driver doesn't modify LUKS metadata except when creating image.
 637     * Allow share-rw=on as a special case. */
 638    .bdrv_child_perm    = bdrv_filter_default_perms,
 639    .bdrv_co_create     = block_crypto_co_create_luks,
 640    .bdrv_co_create_opts = block_crypto_co_create_opts_luks,
 641    .bdrv_co_truncate   = block_crypto_co_truncate,
 642    .create_opts        = &block_crypto_create_opts_luks,
 643
 644    .bdrv_reopen_prepare = block_crypto_reopen_prepare,
 645    .bdrv_refresh_limits = block_crypto_refresh_limits,
 646    .bdrv_co_preadv     = block_crypto_co_preadv,
 647    .bdrv_co_pwritev    = block_crypto_co_pwritev,
 648    .bdrv_getlength     = block_crypto_getlength,
 649    .bdrv_get_info      = block_crypto_get_info_luks,
 650    .bdrv_get_specific_info = block_crypto_get_specific_info_luks,
 651
 652    .strong_runtime_opts = block_crypto_strong_runtime_opts,
 653};
 654
 655static void block_crypto_init(void)
 656{
 657    bdrv_register(&bdrv_crypto_luks);
 658}
 659
 660block_init(block_crypto_init);
 661