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                                       errp);
 233
 234    if (!crypto->block) {
 235        ret = -EIO;
 236        goto cleanup;
 237    }
 238
 239    bs->encrypted = true;
 240
 241    ret = 0;
 242 cleanup:
 243    qobject_unref(cryptoopts);
 244    qapi_free_QCryptoBlockOpenOptions(open_opts);
 245    return ret;
 246}
 247
 248
 249static int block_crypto_co_create_generic(BlockDriverState *bs,
 250                                          int64_t size,
 251                                          QCryptoBlockCreateOptions *opts,
 252                                          Error **errp)
 253{
 254    int ret;
 255    BlockBackend *blk;
 256    QCryptoBlock *crypto = NULL;
 257    struct BlockCryptoCreateData data;
 258
 259    blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
 260
 261    ret = blk_insert_bs(blk, bs, errp);
 262    if (ret < 0) {
 263        goto cleanup;
 264    }
 265
 266    data = (struct BlockCryptoCreateData) {
 267        .blk = blk,
 268        .size = size,
 269    };
 270
 271    crypto = qcrypto_block_create(opts, NULL,
 272                                  block_crypto_init_func,
 273                                  block_crypto_write_func,
 274                                  &data,
 275                                  errp);
 276
 277    if (!crypto) {
 278        ret = -EIO;
 279        goto cleanup;
 280    }
 281
 282    ret = 0;
 283 cleanup:
 284    qcrypto_block_free(crypto);
 285    blk_unref(blk);
 286    return ret;
 287}
 288
 289static int coroutine_fn
 290block_crypto_co_truncate(BlockDriverState *bs, int64_t offset,
 291                         PreallocMode prealloc, Error **errp)
 292{
 293    BlockCrypto *crypto = bs->opaque;
 294    uint64_t payload_offset =
 295        qcrypto_block_get_payload_offset(crypto->block);
 296
 297    if (payload_offset > INT64_MAX - offset) {
 298        error_setg(errp, "The requested file size is too large");
 299        return -EFBIG;
 300    }
 301
 302    offset += payload_offset;
 303
 304    return bdrv_co_truncate(bs->file, offset, prealloc, errp);
 305}
 306
 307static void block_crypto_close(BlockDriverState *bs)
 308{
 309    BlockCrypto *crypto = bs->opaque;
 310    qcrypto_block_free(crypto->block);
 311}
 312
 313static int block_crypto_reopen_prepare(BDRVReopenState *state,
 314                                       BlockReopenQueue *queue, Error **errp)
 315{
 316    /* nothing needs checking */
 317    return 0;
 318}
 319
 320/*
 321 * 1 MB bounce buffer gives good performance / memory tradeoff
 322 * when using cache=none|directsync.
 323 */
 324#define BLOCK_CRYPTO_MAX_IO_SIZE (1024 * 1024)
 325
 326static coroutine_fn int
 327block_crypto_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
 328                       QEMUIOVector *qiov, int flags)
 329{
 330    BlockCrypto *crypto = bs->opaque;
 331    uint64_t cur_bytes; /* number of bytes in current iteration */
 332    uint64_t bytes_done = 0;
 333    uint8_t *cipher_data = NULL;
 334    QEMUIOVector hd_qiov;
 335    int ret = 0;
 336    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
 337    uint64_t payload_offset = qcrypto_block_get_payload_offset(crypto->block);
 338
 339    assert(!flags);
 340    assert(payload_offset < INT64_MAX);
 341    assert(QEMU_IS_ALIGNED(offset, sector_size));
 342    assert(QEMU_IS_ALIGNED(bytes, sector_size));
 343
 344    qemu_iovec_init(&hd_qiov, qiov->niov);
 345
 346    /* Bounce buffer because we don't wish to expose cipher text
 347     * in qiov which points to guest memory.
 348     */
 349    cipher_data =
 350        qemu_try_blockalign(bs->file->bs, MIN(BLOCK_CRYPTO_MAX_IO_SIZE,
 351                                              qiov->size));
 352    if (cipher_data == NULL) {
 353        ret = -ENOMEM;
 354        goto cleanup;
 355    }
 356
 357    while (bytes) {
 358        cur_bytes = MIN(bytes, BLOCK_CRYPTO_MAX_IO_SIZE);
 359
 360        qemu_iovec_reset(&hd_qiov);
 361        qemu_iovec_add(&hd_qiov, cipher_data, cur_bytes);
 362
 363        ret = bdrv_co_preadv(bs->file, payload_offset + offset + bytes_done,
 364                             cur_bytes, &hd_qiov, 0);
 365        if (ret < 0) {
 366            goto cleanup;
 367        }
 368
 369        if (qcrypto_block_decrypt(crypto->block, offset + bytes_done,
 370                                  cipher_data, cur_bytes, NULL) < 0) {
 371            ret = -EIO;
 372            goto cleanup;
 373        }
 374
 375        qemu_iovec_from_buf(qiov, bytes_done, cipher_data, cur_bytes);
 376
 377        bytes -= cur_bytes;
 378        bytes_done += cur_bytes;
 379    }
 380
 381 cleanup:
 382    qemu_iovec_destroy(&hd_qiov);
 383    qemu_vfree(cipher_data);
 384
 385    return ret;
 386}
 387
 388
 389static coroutine_fn int
 390block_crypto_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
 391                        QEMUIOVector *qiov, int flags)
 392{
 393    BlockCrypto *crypto = bs->opaque;
 394    uint64_t cur_bytes; /* number of bytes in current iteration */
 395    uint64_t bytes_done = 0;
 396    uint8_t *cipher_data = NULL;
 397    QEMUIOVector hd_qiov;
 398    int ret = 0;
 399    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
 400    uint64_t payload_offset = qcrypto_block_get_payload_offset(crypto->block);
 401
 402    assert(!(flags & ~BDRV_REQ_FUA));
 403    assert(payload_offset < INT64_MAX);
 404    assert(QEMU_IS_ALIGNED(offset, sector_size));
 405    assert(QEMU_IS_ALIGNED(bytes, sector_size));
 406
 407    qemu_iovec_init(&hd_qiov, qiov->niov);
 408
 409    /* Bounce buffer because we're not permitted to touch
 410     * contents of qiov - it points to guest memory.
 411     */
 412    cipher_data =
 413        qemu_try_blockalign(bs->file->bs, MIN(BLOCK_CRYPTO_MAX_IO_SIZE,
 414                                              qiov->size));
 415    if (cipher_data == NULL) {
 416        ret = -ENOMEM;
 417        goto cleanup;
 418    }
 419
 420    while (bytes) {
 421        cur_bytes = MIN(bytes, BLOCK_CRYPTO_MAX_IO_SIZE);
 422
 423        qemu_iovec_to_buf(qiov, bytes_done, cipher_data, cur_bytes);
 424
 425        if (qcrypto_block_encrypt(crypto->block, offset + bytes_done,
 426                                  cipher_data, cur_bytes, NULL) < 0) {
 427            ret = -EIO;
 428            goto cleanup;
 429        }
 430
 431        qemu_iovec_reset(&hd_qiov);
 432        qemu_iovec_add(&hd_qiov, cipher_data, cur_bytes);
 433
 434        ret = bdrv_co_pwritev(bs->file, payload_offset + offset + bytes_done,
 435                              cur_bytes, &hd_qiov, flags);
 436        if (ret < 0) {
 437            goto cleanup;
 438        }
 439
 440        bytes -= cur_bytes;
 441        bytes_done += cur_bytes;
 442    }
 443
 444 cleanup:
 445    qemu_iovec_destroy(&hd_qiov);
 446    qemu_vfree(cipher_data);
 447
 448    return ret;
 449}
 450
 451static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp)
 452{
 453    BlockCrypto *crypto = bs->opaque;
 454    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
 455    bs->bl.request_alignment = sector_size; /* No sub-sector I/O */
 456}
 457
 458
 459static int64_t block_crypto_getlength(BlockDriverState *bs)
 460{
 461    BlockCrypto *crypto = bs->opaque;
 462    int64_t len = bdrv_getlength(bs->file->bs);
 463
 464    uint64_t offset = qcrypto_block_get_payload_offset(crypto->block);
 465    assert(offset < INT64_MAX);
 466
 467    if (offset > len) {
 468        return -EIO;
 469    }
 470
 471    len -= offset;
 472
 473    return len;
 474}
 475
 476
 477static int block_crypto_probe_luks(const uint8_t *buf,
 478                                   int buf_size,
 479                                   const char *filename) {
 480    return block_crypto_probe_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 481                                      buf, buf_size, filename);
 482}
 483
 484static int block_crypto_open_luks(BlockDriverState *bs,
 485                                  QDict *options,
 486                                  int flags,
 487                                  Error **errp)
 488{
 489    return block_crypto_open_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 490                                     &block_crypto_runtime_opts_luks,
 491                                     bs, options, flags, errp);
 492}
 493
 494static int coroutine_fn
 495block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
 496{
 497    BlockdevCreateOptionsLUKS *luks_opts;
 498    BlockDriverState *bs = NULL;
 499    QCryptoBlockCreateOptions create_opts;
 500    int ret;
 501
 502    assert(create_options->driver == BLOCKDEV_DRIVER_LUKS);
 503    luks_opts = &create_options->u.luks;
 504
 505    bs = bdrv_open_blockdev_ref(luks_opts->file, errp);
 506    if (bs == NULL) {
 507        return -EIO;
 508    }
 509
 510    create_opts = (QCryptoBlockCreateOptions) {
 511        .format = Q_CRYPTO_BLOCK_FORMAT_LUKS,
 512        .u.luks = *qapi_BlockdevCreateOptionsLUKS_base(luks_opts),
 513    };
 514
 515    ret = block_crypto_co_create_generic(bs, luks_opts->size, &create_opts,
 516                                         errp);
 517    if (ret < 0) {
 518        goto fail;
 519    }
 520
 521    ret = 0;
 522fail:
 523    bdrv_unref(bs);
 524    return ret;
 525}
 526
 527static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
 528                                                         QemuOpts *opts,
 529                                                         Error **errp)
 530{
 531    QCryptoBlockCreateOptions *create_opts = NULL;
 532    BlockDriverState *bs = NULL;
 533    QDict *cryptoopts;
 534    int64_t size;
 535    int ret;
 536
 537    /* Parse options */
 538    size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
 539
 540    cryptoopts = qemu_opts_to_qdict_filtered(opts, NULL,
 541                                             &block_crypto_create_opts_luks,
 542                                             true);
 543
 544    qdict_put_str(cryptoopts, "format", "luks");
 545    create_opts = block_crypto_create_opts_init(cryptoopts, errp);
 546    if (!create_opts) {
 547        ret = -EINVAL;
 548        goto fail;
 549    }
 550
 551    /* Create protocol layer */
 552    ret = bdrv_create_file(filename, opts, errp);
 553    if (ret < 0) {
 554        goto fail;
 555    }
 556
 557    bs = bdrv_open(filename, NULL, NULL,
 558                   BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
 559    if (!bs) {
 560        ret = -EINVAL;
 561        goto fail;
 562    }
 563
 564    /* Create format layer */
 565    ret = block_crypto_co_create_generic(bs, size, create_opts, errp);
 566    if (ret < 0) {
 567        goto fail;
 568    }
 569
 570    ret = 0;
 571fail:
 572    bdrv_unref(bs);
 573    qapi_free_QCryptoBlockCreateOptions(create_opts);
 574    qobject_unref(cryptoopts);
 575    return ret;
 576}
 577
 578static int block_crypto_get_info_luks(BlockDriverState *bs,
 579                                      BlockDriverInfo *bdi)
 580{
 581    BlockDriverInfo subbdi;
 582    int ret;
 583
 584    ret = bdrv_get_info(bs->file->bs, &subbdi);
 585    if (ret != 0) {
 586        return ret;
 587    }
 588
 589    bdi->unallocated_blocks_are_zero = false;
 590    bdi->cluster_size = subbdi.cluster_size;
 591
 592    return 0;
 593}
 594
 595static ImageInfoSpecific *
 596block_crypto_get_specific_info_luks(BlockDriverState *bs)
 597{
 598    BlockCrypto *crypto = bs->opaque;
 599    ImageInfoSpecific *spec_info;
 600    QCryptoBlockInfo *info;
 601
 602    info = qcrypto_block_get_info(crypto->block, NULL);
 603    if (!info) {
 604        return NULL;
 605    }
 606    if (info->format != Q_CRYPTO_BLOCK_FORMAT_LUKS) {
 607        qapi_free_QCryptoBlockInfo(info);
 608        return NULL;
 609    }
 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
 624BlockDriver bdrv_crypto_luks = {
 625    .format_name        = "luks",
 626    .instance_size      = sizeof(BlockCrypto),
 627    .bdrv_probe         = block_crypto_probe_luks,
 628    .bdrv_open          = block_crypto_open_luks,
 629    .bdrv_close         = block_crypto_close,
 630    /* This driver doesn't modify LUKS metadata except when creating image.
 631     * Allow share-rw=on as a special case. */
 632    .bdrv_child_perm    = bdrv_filter_default_perms,
 633    .bdrv_co_create     = block_crypto_co_create_luks,
 634    .bdrv_co_create_opts = block_crypto_co_create_opts_luks,
 635    .bdrv_co_truncate   = block_crypto_co_truncate,
 636    .create_opts        = &block_crypto_create_opts_luks,
 637
 638    .bdrv_reopen_prepare = block_crypto_reopen_prepare,
 639    .bdrv_refresh_limits = block_crypto_refresh_limits,
 640    .bdrv_co_preadv     = block_crypto_co_preadv,
 641    .bdrv_co_pwritev    = block_crypto_co_pwritev,
 642    .bdrv_getlength     = block_crypto_getlength,
 643    .bdrv_get_info      = block_crypto_get_info_luks,
 644    .bdrv_get_specific_info = block_crypto_get_specific_info_luks,
 645};
 646
 647static void block_crypto_init(void)
 648{
 649    bdrv_register(&bdrv_crypto_luks);
 650}
 651
 652block_init(block_crypto_init);
 653