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/qapi-visit-crypto.h"
  28#include "qapi/qmp/qdict.h"
  29#include "qapi/qobject-input-visitor.h"
  30#include "qapi/error.h"
  31#include "qemu/option.h"
  32#include "block/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(QCryptoBlockFormat format,
 152                            QDict *opts,
 153                            Error **errp)
 154{
 155    Visitor *v;
 156    QCryptoBlockOpenOptions *ret = NULL;
 157    Error *local_err = NULL;
 158
 159    ret = g_new0(QCryptoBlockOpenOptions, 1);
 160    ret->format = format;
 161
 162    v = qobject_input_visitor_new_keyval(QOBJECT(opts));
 163
 164    visit_start_struct(v, NULL, NULL, 0, &local_err);
 165    if (local_err) {
 166        goto out;
 167    }
 168
 169    switch (format) {
 170    case Q_CRYPTO_BLOCK_FORMAT_LUKS:
 171        visit_type_QCryptoBlockOptionsLUKS_members(
 172            v, &ret->u.luks, &local_err);
 173        break;
 174
 175    case Q_CRYPTO_BLOCK_FORMAT_QCOW:
 176        visit_type_QCryptoBlockOptionsQCow_members(
 177            v, &ret->u.qcow, &local_err);
 178        break;
 179
 180    default:
 181        error_setg(&local_err, "Unsupported block format %d", format);
 182        break;
 183    }
 184    if (!local_err) {
 185        visit_check_struct(v, &local_err);
 186    }
 187
 188    visit_end_struct(v, NULL);
 189
 190 out:
 191    if (local_err) {
 192        error_propagate(errp, local_err);
 193        qapi_free_QCryptoBlockOpenOptions(ret);
 194        ret = NULL;
 195    }
 196    visit_free(v);
 197    return ret;
 198}
 199
 200
 201QCryptoBlockCreateOptions *
 202block_crypto_create_opts_init(QCryptoBlockFormat format,
 203                              QDict *opts,
 204                              Error **errp)
 205{
 206    Visitor *v;
 207    QCryptoBlockCreateOptions *ret = NULL;
 208    Error *local_err = NULL;
 209
 210    ret = g_new0(QCryptoBlockCreateOptions, 1);
 211    ret->format = format;
 212
 213    v = qobject_input_visitor_new_keyval(QOBJECT(opts));
 214
 215    visit_start_struct(v, NULL, NULL, 0, &local_err);
 216    if (local_err) {
 217        goto out;
 218    }
 219
 220    switch (format) {
 221    case Q_CRYPTO_BLOCK_FORMAT_LUKS:
 222        visit_type_QCryptoBlockCreateOptionsLUKS_members(
 223            v, &ret->u.luks, &local_err);
 224        break;
 225
 226    case Q_CRYPTO_BLOCK_FORMAT_QCOW:
 227        visit_type_QCryptoBlockOptionsQCow_members(
 228            v, &ret->u.qcow, &local_err);
 229        break;
 230
 231    default:
 232        error_setg(&local_err, "Unsupported block format %d", format);
 233        break;
 234    }
 235    if (!local_err) {
 236        visit_check_struct(v, &local_err);
 237    }
 238
 239    visit_end_struct(v, NULL);
 240
 241 out:
 242    if (local_err) {
 243        error_propagate(errp, local_err);
 244        qapi_free_QCryptoBlockCreateOptions(ret);
 245        ret = NULL;
 246    }
 247    visit_free(v);
 248    return ret;
 249}
 250
 251
 252static int block_crypto_open_generic(QCryptoBlockFormat format,
 253                                     QemuOptsList *opts_spec,
 254                                     BlockDriverState *bs,
 255                                     QDict *options,
 256                                     int flags,
 257                                     Error **errp)
 258{
 259    BlockCrypto *crypto = bs->opaque;
 260    QemuOpts *opts = NULL;
 261    Error *local_err = NULL;
 262    int ret = -EINVAL;
 263    QCryptoBlockOpenOptions *open_opts = NULL;
 264    unsigned int cflags = 0;
 265    QDict *cryptoopts = NULL;
 266
 267    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
 268                               false, errp);
 269    if (!bs->file) {
 270        return -EINVAL;
 271    }
 272
 273    bs->supported_write_flags = BDRV_REQ_FUA &
 274        bs->file->bs->supported_write_flags;
 275
 276    opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort);
 277    qemu_opts_absorb_qdict(opts, options, &local_err);
 278    if (local_err) {
 279        error_propagate(errp, local_err);
 280        goto cleanup;
 281    }
 282
 283    cryptoopts = qemu_opts_to_qdict(opts, NULL);
 284
 285    open_opts = block_crypto_open_opts_init(format, cryptoopts, errp);
 286    if (!open_opts) {
 287        goto cleanup;
 288    }
 289
 290    if (flags & BDRV_O_NO_IO) {
 291        cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
 292    }
 293    crypto->block = qcrypto_block_open(open_opts, NULL,
 294                                       block_crypto_read_func,
 295                                       bs,
 296                                       cflags,
 297                                       errp);
 298
 299    if (!crypto->block) {
 300        ret = -EIO;
 301        goto cleanup;
 302    }
 303
 304    bs->encrypted = true;
 305
 306    ret = 0;
 307 cleanup:
 308    QDECREF(cryptoopts);
 309    qapi_free_QCryptoBlockOpenOptions(open_opts);
 310    return ret;
 311}
 312
 313
 314static int block_crypto_co_create_generic(BlockDriverState *bs,
 315                                          int64_t size,
 316                                          QCryptoBlockCreateOptions *opts,
 317                                          Error **errp)
 318{
 319    int ret;
 320    BlockBackend *blk;
 321    QCryptoBlock *crypto = NULL;
 322    struct BlockCryptoCreateData data;
 323
 324    blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
 325
 326    ret = blk_insert_bs(blk, bs, errp);
 327    if (ret < 0) {
 328        goto cleanup;
 329    }
 330
 331    data = (struct BlockCryptoCreateData) {
 332        .blk = blk,
 333        .size = size,
 334    };
 335
 336    crypto = qcrypto_block_create(opts, NULL,
 337                                  block_crypto_init_func,
 338                                  block_crypto_write_func,
 339                                  &data,
 340                                  errp);
 341
 342    if (!crypto) {
 343        ret = -EIO;
 344        goto cleanup;
 345    }
 346
 347    ret = 0;
 348 cleanup:
 349    qcrypto_block_free(crypto);
 350    blk_unref(blk);
 351    return ret;
 352}
 353
 354static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
 355                                 PreallocMode prealloc, Error **errp)
 356{
 357    BlockCrypto *crypto = bs->opaque;
 358    uint64_t payload_offset =
 359        qcrypto_block_get_payload_offset(crypto->block);
 360
 361    if (payload_offset > INT64_MAX - offset) {
 362        error_setg(errp, "The requested file size is too large");
 363        return -EFBIG;
 364    }
 365
 366    offset += payload_offset;
 367
 368    return bdrv_truncate(bs->file, offset, prealloc, errp);
 369}
 370
 371static void block_crypto_close(BlockDriverState *bs)
 372{
 373    BlockCrypto *crypto = bs->opaque;
 374    qcrypto_block_free(crypto->block);
 375}
 376
 377static int block_crypto_reopen_prepare(BDRVReopenState *state,
 378                                       BlockReopenQueue *queue, Error **errp)
 379{
 380    /* nothing needs checking */
 381    return 0;
 382}
 383
 384/*
 385 * 1 MB bounce buffer gives good performance / memory tradeoff
 386 * when using cache=none|directsync.
 387 */
 388#define BLOCK_CRYPTO_MAX_IO_SIZE (1024 * 1024)
 389
 390static coroutine_fn int
 391block_crypto_co_preadv(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);
 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 don't wish to expose cipher text
 411     * in qiov which 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_reset(&hd_qiov);
 425        qemu_iovec_add(&hd_qiov, cipher_data, cur_bytes);
 426
 427        ret = bdrv_co_preadv(bs->file, payload_offset + offset + bytes_done,
 428                             cur_bytes, &hd_qiov, 0);
 429        if (ret < 0) {
 430            goto cleanup;
 431        }
 432
 433        if (qcrypto_block_decrypt(crypto->block, offset + bytes_done,
 434                                  cipher_data, cur_bytes, NULL) < 0) {
 435            ret = -EIO;
 436            goto cleanup;
 437        }
 438
 439        qemu_iovec_from_buf(qiov, bytes_done, cipher_data, cur_bytes);
 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
 452
 453static coroutine_fn int
 454block_crypto_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
 455                        QEMUIOVector *qiov, int flags)
 456{
 457    BlockCrypto *crypto = bs->opaque;
 458    uint64_t cur_bytes; /* number of bytes in current iteration */
 459    uint64_t bytes_done = 0;
 460    uint8_t *cipher_data = NULL;
 461    QEMUIOVector hd_qiov;
 462    int ret = 0;
 463    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
 464    uint64_t payload_offset = qcrypto_block_get_payload_offset(crypto->block);
 465
 466    assert(!(flags & ~BDRV_REQ_FUA));
 467    assert(payload_offset < INT64_MAX);
 468    assert(QEMU_IS_ALIGNED(offset, sector_size));
 469    assert(QEMU_IS_ALIGNED(bytes, sector_size));
 470
 471    qemu_iovec_init(&hd_qiov, qiov->niov);
 472
 473    /* Bounce buffer because we're not permitted to touch
 474     * contents of qiov - it points to guest memory.
 475     */
 476    cipher_data =
 477        qemu_try_blockalign(bs->file->bs, MIN(BLOCK_CRYPTO_MAX_IO_SIZE,
 478                                              qiov->size));
 479    if (cipher_data == NULL) {
 480        ret = -ENOMEM;
 481        goto cleanup;
 482    }
 483
 484    while (bytes) {
 485        cur_bytes = MIN(bytes, BLOCK_CRYPTO_MAX_IO_SIZE);
 486
 487        qemu_iovec_to_buf(qiov, bytes_done, cipher_data, cur_bytes);
 488
 489        if (qcrypto_block_encrypt(crypto->block, offset + bytes_done,
 490                                  cipher_data, cur_bytes, NULL) < 0) {
 491            ret = -EIO;
 492            goto cleanup;
 493        }
 494
 495        qemu_iovec_reset(&hd_qiov);
 496        qemu_iovec_add(&hd_qiov, cipher_data, cur_bytes);
 497
 498        ret = bdrv_co_pwritev(bs->file, payload_offset + offset + bytes_done,
 499                              cur_bytes, &hd_qiov, flags);
 500        if (ret < 0) {
 501            goto cleanup;
 502        }
 503
 504        bytes -= cur_bytes;
 505        bytes_done += cur_bytes;
 506    }
 507
 508 cleanup:
 509    qemu_iovec_destroy(&hd_qiov);
 510    qemu_vfree(cipher_data);
 511
 512    return ret;
 513}
 514
 515static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp)
 516{
 517    BlockCrypto *crypto = bs->opaque;
 518    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
 519    bs->bl.request_alignment = sector_size; /* No sub-sector I/O */
 520}
 521
 522
 523static int64_t block_crypto_getlength(BlockDriverState *bs)
 524{
 525    BlockCrypto *crypto = bs->opaque;
 526    int64_t len = bdrv_getlength(bs->file->bs);
 527
 528    uint64_t offset = qcrypto_block_get_payload_offset(crypto->block);
 529    assert(offset < INT64_MAX);
 530
 531    if (offset > len) {
 532        return -EIO;
 533    }
 534
 535    len -= offset;
 536
 537    return len;
 538}
 539
 540
 541static int block_crypto_probe_luks(const uint8_t *buf,
 542                                   int buf_size,
 543                                   const char *filename) {
 544    return block_crypto_probe_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 545                                      buf, buf_size, filename);
 546}
 547
 548static int block_crypto_open_luks(BlockDriverState *bs,
 549                                  QDict *options,
 550                                  int flags,
 551                                  Error **errp)
 552{
 553    return block_crypto_open_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 554                                     &block_crypto_runtime_opts_luks,
 555                                     bs, options, flags, errp);
 556}
 557
 558static int coroutine_fn
 559block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
 560{
 561    BlockdevCreateOptionsLUKS *luks_opts;
 562    BlockDriverState *bs = NULL;
 563    QCryptoBlockCreateOptions create_opts;
 564    int ret;
 565
 566    assert(create_options->driver == BLOCKDEV_DRIVER_LUKS);
 567    luks_opts = &create_options->u.luks;
 568
 569    bs = bdrv_open_blockdev_ref(luks_opts->file, errp);
 570    if (bs == NULL) {
 571        return -EIO;
 572    }
 573
 574    create_opts = (QCryptoBlockCreateOptions) {
 575        .format = Q_CRYPTO_BLOCK_FORMAT_LUKS,
 576        .u.luks = *qapi_BlockdevCreateOptionsLUKS_base(luks_opts),
 577    };
 578
 579    ret = block_crypto_co_create_generic(bs, luks_opts->size, &create_opts,
 580                                         errp);
 581    if (ret < 0) {
 582        goto fail;
 583    }
 584
 585    ret = 0;
 586fail:
 587    bdrv_unref(bs);
 588    return ret;
 589}
 590
 591static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
 592                                                         QemuOpts *opts,
 593                                                         Error **errp)
 594{
 595    QCryptoBlockCreateOptions *create_opts = NULL;
 596    BlockDriverState *bs = NULL;
 597    QDict *cryptoopts;
 598    int64_t size;
 599    int ret;
 600
 601    /* Parse options */
 602    size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
 603
 604    cryptoopts = qemu_opts_to_qdict_filtered(opts, NULL,
 605                                             &block_crypto_create_opts_luks,
 606                                             true);
 607
 608    create_opts = block_crypto_create_opts_init(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 609                                                cryptoopts, errp);
 610    if (!create_opts) {
 611        ret = -EINVAL;
 612        goto fail;
 613    }
 614
 615    /* Create protocol layer */
 616    ret = bdrv_create_file(filename, opts, errp);
 617    if (ret < 0) {
 618        return ret;
 619    }
 620
 621    bs = bdrv_open(filename, NULL, NULL,
 622                   BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
 623    if (!bs) {
 624        ret = -EINVAL;
 625        goto fail;
 626    }
 627
 628    /* Create format layer */
 629    ret = block_crypto_co_create_generic(bs, size, create_opts, errp);
 630    if (ret < 0) {
 631        goto fail;
 632    }
 633
 634    ret = 0;
 635fail:
 636    bdrv_unref(bs);
 637    qapi_free_QCryptoBlockCreateOptions(create_opts);
 638    QDECREF(cryptoopts);
 639    return ret;
 640}
 641
 642static int block_crypto_get_info_luks(BlockDriverState *bs,
 643                                      BlockDriverInfo *bdi)
 644{
 645    BlockDriverInfo subbdi;
 646    int ret;
 647
 648    ret = bdrv_get_info(bs->file->bs, &subbdi);
 649    if (ret != 0) {
 650        return ret;
 651    }
 652
 653    bdi->unallocated_blocks_are_zero = false;
 654    bdi->cluster_size = subbdi.cluster_size;
 655
 656    return 0;
 657}
 658
 659static ImageInfoSpecific *
 660block_crypto_get_specific_info_luks(BlockDriverState *bs)
 661{
 662    BlockCrypto *crypto = bs->opaque;
 663    ImageInfoSpecific *spec_info;
 664    QCryptoBlockInfo *info;
 665
 666    info = qcrypto_block_get_info(crypto->block, NULL);
 667    if (!info) {
 668        return NULL;
 669    }
 670    if (info->format != Q_CRYPTO_BLOCK_FORMAT_LUKS) {
 671        qapi_free_QCryptoBlockInfo(info);
 672        return NULL;
 673    }
 674
 675    spec_info = g_new(ImageInfoSpecific, 1);
 676    spec_info->type = IMAGE_INFO_SPECIFIC_KIND_LUKS;
 677    spec_info->u.luks.data = g_new(QCryptoBlockInfoLUKS, 1);
 678    *spec_info->u.luks.data = info->u.luks;
 679
 680    /* Blank out pointers we've just stolen to avoid double free */
 681    memset(&info->u.luks, 0, sizeof(info->u.luks));
 682
 683    qapi_free_QCryptoBlockInfo(info);
 684
 685    return spec_info;
 686}
 687
 688BlockDriver bdrv_crypto_luks = {
 689    .format_name        = "luks",
 690    .instance_size      = sizeof(BlockCrypto),
 691    .bdrv_probe         = block_crypto_probe_luks,
 692    .bdrv_open          = block_crypto_open_luks,
 693    .bdrv_close         = block_crypto_close,
 694    .bdrv_child_perm    = bdrv_format_default_perms,
 695    .bdrv_co_create     = block_crypto_co_create_luks,
 696    .bdrv_co_create_opts = block_crypto_co_create_opts_luks,
 697    .bdrv_truncate      = block_crypto_truncate,
 698    .create_opts        = &block_crypto_create_opts_luks,
 699
 700    .bdrv_reopen_prepare = block_crypto_reopen_prepare,
 701    .bdrv_refresh_limits = block_crypto_refresh_limits,
 702    .bdrv_co_preadv     = block_crypto_co_preadv,
 703    .bdrv_co_pwritev    = block_crypto_co_pwritev,
 704    .bdrv_getlength     = block_crypto_getlength,
 705    .bdrv_get_info      = block_crypto_get_info_luks,
 706    .bdrv_get_specific_info = block_crypto_get_specific_info_luks,
 707};
 708
 709static void block_crypto_init(void)
 710{
 711    bdrv_register(&bdrv_crypto_luks);
 712}
 713
 714block_init(block_crypto_init);
 715