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