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    opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort);
 283    qemu_opts_absorb_qdict(opts, options, &local_err);
 284    if (local_err) {
 285        error_propagate(errp, local_err);
 286        goto cleanup;
 287    }
 288
 289    cryptoopts = qemu_opts_to_qdict(opts, NULL);
 290
 291    open_opts = block_crypto_open_opts_init(format, cryptoopts, errp);
 292    if (!open_opts) {
 293        goto cleanup;
 294    }
 295
 296    if (flags & BDRV_O_NO_IO) {
 297        cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
 298    }
 299    crypto->block = qcrypto_block_open(open_opts, NULL,
 300                                       block_crypto_read_func,
 301                                       bs,
 302                                       cflags,
 303                                       errp);
 304
 305    if (!crypto->block) {
 306        ret = -EIO;
 307        goto cleanup;
 308    }
 309
 310    bs->encrypted = true;
 311
 312    ret = 0;
 313 cleanup:
 314    QDECREF(cryptoopts);
 315    qapi_free_QCryptoBlockOpenOptions(open_opts);
 316    return ret;
 317}
 318
 319
 320static int block_crypto_create_generic(QCryptoBlockFormat format,
 321                                       const char *filename,
 322                                       QemuOpts *opts,
 323                                       Error **errp)
 324{
 325    int ret = -EINVAL;
 326    QCryptoBlockCreateOptions *create_opts = NULL;
 327    QCryptoBlock *crypto = NULL;
 328    struct BlockCryptoCreateData data = {
 329        .size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
 330                         BDRV_SECTOR_SIZE),
 331        .opts = opts,
 332        .filename = filename,
 333    };
 334    QDict *cryptoopts;
 335
 336    cryptoopts = qemu_opts_to_qdict(opts, NULL);
 337
 338    create_opts = block_crypto_create_opts_init(format, cryptoopts, errp);
 339    if (!create_opts) {
 340        return -1;
 341    }
 342
 343    crypto = qcrypto_block_create(create_opts, NULL,
 344                                  block_crypto_init_func,
 345                                  block_crypto_write_func,
 346                                  &data,
 347                                  errp);
 348
 349    if (!crypto) {
 350        ret = -EIO;
 351        goto cleanup;
 352    }
 353
 354    ret = 0;
 355 cleanup:
 356    QDECREF(cryptoopts);
 357    qcrypto_block_free(crypto);
 358    blk_unref(data.blk);
 359    qapi_free_QCryptoBlockCreateOptions(create_opts);
 360    return ret;
 361}
 362
 363static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
 364                                 PreallocMode prealloc, Error **errp)
 365{
 366    BlockCrypto *crypto = bs->opaque;
 367    size_t payload_offset =
 368        qcrypto_block_get_payload_offset(crypto->block);
 369
 370    offset += payload_offset;
 371
 372    return bdrv_truncate(bs->file, offset, prealloc, errp);
 373}
 374
 375static void block_crypto_close(BlockDriverState *bs)
 376{
 377    BlockCrypto *crypto = bs->opaque;
 378    qcrypto_block_free(crypto->block);
 379}
 380
 381
 382#define BLOCK_CRYPTO_MAX_SECTORS 32
 383
 384static coroutine_fn int
 385block_crypto_co_readv(BlockDriverState *bs, int64_t sector_num,
 386                      int remaining_sectors, QEMUIOVector *qiov)
 387{
 388    BlockCrypto *crypto = bs->opaque;
 389    int cur_nr_sectors; /* number of sectors in current iteration */
 390    uint64_t bytes_done = 0;
 391    uint8_t *cipher_data = NULL;
 392    QEMUIOVector hd_qiov;
 393    int ret = 0;
 394    size_t payload_offset =
 395        qcrypto_block_get_payload_offset(crypto->block) / 512;
 396
 397    qemu_iovec_init(&hd_qiov, qiov->niov);
 398
 399    /* Bounce buffer so we have a linear mem region for
 400     * entire sector. XXX optimize so we avoid bounce
 401     * buffer in case that qiov->niov == 1
 402     */
 403    cipher_data =
 404        qemu_try_blockalign(bs->file->bs, MIN(BLOCK_CRYPTO_MAX_SECTORS * 512,
 405                                              qiov->size));
 406    if (cipher_data == NULL) {
 407        ret = -ENOMEM;
 408        goto cleanup;
 409    }
 410
 411    while (remaining_sectors) {
 412        cur_nr_sectors = remaining_sectors;
 413
 414        if (cur_nr_sectors > BLOCK_CRYPTO_MAX_SECTORS) {
 415            cur_nr_sectors = BLOCK_CRYPTO_MAX_SECTORS;
 416        }
 417
 418        qemu_iovec_reset(&hd_qiov);
 419        qemu_iovec_add(&hd_qiov, cipher_data, cur_nr_sectors * 512);
 420
 421        ret = bdrv_co_readv(bs->file,
 422                            payload_offset + sector_num,
 423                            cur_nr_sectors, &hd_qiov);
 424        if (ret < 0) {
 425            goto cleanup;
 426        }
 427
 428        if (qcrypto_block_decrypt(crypto->block,
 429                                  sector_num,
 430                                  cipher_data, cur_nr_sectors * 512,
 431                                  NULL) < 0) {
 432            ret = -EIO;
 433            goto cleanup;
 434        }
 435
 436        qemu_iovec_from_buf(qiov, bytes_done,
 437                            cipher_data, cur_nr_sectors * 512);
 438
 439        remaining_sectors -= cur_nr_sectors;
 440        sector_num += cur_nr_sectors;
 441        bytes_done += cur_nr_sectors * 512;
 442    }
 443
 444 cleanup:
 445    qemu_iovec_destroy(&hd_qiov);
 446    qemu_vfree(cipher_data);
 447
 448    return ret;
 449}
 450
 451
 452static coroutine_fn int
 453block_crypto_co_writev(BlockDriverState *bs, int64_t sector_num,
 454                       int remaining_sectors, QEMUIOVector *qiov)
 455{
 456    BlockCrypto *crypto = bs->opaque;
 457    int cur_nr_sectors; /* number of sectors in current iteration */
 458    uint64_t bytes_done = 0;
 459    uint8_t *cipher_data = NULL;
 460    QEMUIOVector hd_qiov;
 461    int ret = 0;
 462    size_t payload_offset =
 463        qcrypto_block_get_payload_offset(crypto->block) / 512;
 464
 465    qemu_iovec_init(&hd_qiov, qiov->niov);
 466
 467    /* Bounce buffer so we have a linear mem region for
 468     * entire sector. XXX optimize so we avoid bounce
 469     * buffer in case that qiov->niov == 1
 470     */
 471    cipher_data =
 472        qemu_try_blockalign(bs->file->bs, MIN(BLOCK_CRYPTO_MAX_SECTORS * 512,
 473                                              qiov->size));
 474    if (cipher_data == NULL) {
 475        ret = -ENOMEM;
 476        goto cleanup;
 477    }
 478
 479    while (remaining_sectors) {
 480        cur_nr_sectors = remaining_sectors;
 481
 482        if (cur_nr_sectors > BLOCK_CRYPTO_MAX_SECTORS) {
 483            cur_nr_sectors = BLOCK_CRYPTO_MAX_SECTORS;
 484        }
 485
 486        qemu_iovec_to_buf(qiov, bytes_done,
 487                          cipher_data, cur_nr_sectors * 512);
 488
 489        if (qcrypto_block_encrypt(crypto->block,
 490                                  sector_num,
 491                                  cipher_data, cur_nr_sectors * 512,
 492                                  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_nr_sectors * 512);
 499
 500        ret = bdrv_co_writev(bs->file,
 501                             payload_offset + sector_num,
 502                             cur_nr_sectors, &hd_qiov);
 503        if (ret < 0) {
 504            goto cleanup;
 505        }
 506
 507        remaining_sectors -= cur_nr_sectors;
 508        sector_num += cur_nr_sectors;
 509        bytes_done += cur_nr_sectors * 512;
 510    }
 511
 512 cleanup:
 513    qemu_iovec_destroy(&hd_qiov);
 514    qemu_vfree(cipher_data);
 515
 516    return ret;
 517}
 518
 519
 520static int64_t block_crypto_getlength(BlockDriverState *bs)
 521{
 522    BlockCrypto *crypto = bs->opaque;
 523    int64_t len = bdrv_getlength(bs->file->bs);
 524
 525    ssize_t offset = qcrypto_block_get_payload_offset(crypto->block);
 526
 527    len -= offset;
 528
 529    return len;
 530}
 531
 532
 533static int block_crypto_probe_luks(const uint8_t *buf,
 534                                   int buf_size,
 535                                   const char *filename) {
 536    return block_crypto_probe_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 537                                      buf, buf_size, filename);
 538}
 539
 540static int block_crypto_open_luks(BlockDriverState *bs,
 541                                  QDict *options,
 542                                  int flags,
 543                                  Error **errp)
 544{
 545    return block_crypto_open_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 546                                     &block_crypto_runtime_opts_luks,
 547                                     bs, options, flags, errp);
 548}
 549
 550static int block_crypto_create_luks(const char *filename,
 551                                    QemuOpts *opts,
 552                                    Error **errp)
 553{
 554    return block_crypto_create_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
 555                                       filename, opts, errp);
 556}
 557
 558static int block_crypto_get_info_luks(BlockDriverState *bs,
 559                                      BlockDriverInfo *bdi)
 560{
 561    BlockDriverInfo subbdi;
 562    int ret;
 563
 564    ret = bdrv_get_info(bs->file->bs, &subbdi);
 565    if (ret != 0) {
 566        return ret;
 567    }
 568
 569    bdi->unallocated_blocks_are_zero = false;
 570    bdi->can_write_zeroes_with_unmap = false;
 571    bdi->cluster_size = subbdi.cluster_size;
 572
 573    return 0;
 574}
 575
 576static ImageInfoSpecific *
 577block_crypto_get_specific_info_luks(BlockDriverState *bs)
 578{
 579    BlockCrypto *crypto = bs->opaque;
 580    ImageInfoSpecific *spec_info;
 581    QCryptoBlockInfo *info;
 582
 583    info = qcrypto_block_get_info(crypto->block, NULL);
 584    if (!info) {
 585        return NULL;
 586    }
 587    if (info->format != Q_CRYPTO_BLOCK_FORMAT_LUKS) {
 588        qapi_free_QCryptoBlockInfo(info);
 589        return NULL;
 590    }
 591
 592    spec_info = g_new(ImageInfoSpecific, 1);
 593    spec_info->type = IMAGE_INFO_SPECIFIC_KIND_LUKS;
 594    spec_info->u.luks.data = g_new(QCryptoBlockInfoLUKS, 1);
 595    *spec_info->u.luks.data = info->u.luks;
 596
 597    /* Blank out pointers we've just stolen to avoid double free */
 598    memset(&info->u.luks, 0, sizeof(info->u.luks));
 599
 600    qapi_free_QCryptoBlockInfo(info);
 601
 602    return spec_info;
 603}
 604
 605BlockDriver bdrv_crypto_luks = {
 606    .format_name        = "luks",
 607    .instance_size      = sizeof(BlockCrypto),
 608    .bdrv_probe         = block_crypto_probe_luks,
 609    .bdrv_open          = block_crypto_open_luks,
 610    .bdrv_close         = block_crypto_close,
 611    .bdrv_child_perm    = bdrv_format_default_perms,
 612    .bdrv_create        = block_crypto_create_luks,
 613    .bdrv_truncate      = block_crypto_truncate,
 614    .create_opts        = &block_crypto_create_opts_luks,
 615
 616    .bdrv_co_readv      = block_crypto_co_readv,
 617    .bdrv_co_writev     = block_crypto_co_writev,
 618    .bdrv_getlength     = block_crypto_getlength,
 619    .bdrv_get_info      = block_crypto_get_info_luks,
 620    .bdrv_get_specific_info = block_crypto_get_specific_info_luks,
 621};
 622
 623static void block_crypto_init(void)
 624{
 625    bdrv_register(&bdrv_crypto_luks);
 626}
 627
 628block_init(block_crypto_init);
 629