crypto.c 18.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * QEMU block full disk encryption
 *
 * Copyright (c) 2015-2016 Red Hat, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "qemu/osdep.h"

#include "block/block_int.h"
24
#include "block/qdict.h"
25 26 27
#include "sysemu/block-backend.h"
#include "crypto/block.h"
#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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

typedef struct BlockCrypto BlockCrypto;

struct BlockCrypto {
    QCryptoBlock *block;
};


static int block_crypto_probe_generic(QCryptoBlockFormat format,
                                      const uint8_t *buf,
                                      int buf_size,
                                      const char *filename)
{
    if (qcrypto_block_has_format(format, buf, buf_size)) {
        return 100;
    } else {
        return 0;
    }
}


static ssize_t block_crypto_read_func(QCryptoBlock *block,
                                      size_t offset,
                                      uint8_t *buf,
                                      size_t buflen,
58
                                      void *opaque,
59
                                      Error **errp)
60 61 62 63
{
    BlockDriverState *bs = opaque;
    ssize_t ret;

64
    ret = bdrv_pread(bs->file, offset, buf, buflen);
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Could not read encryption header");
        return ret;
    }
    return ret;
}


struct BlockCryptoCreateData {
    BlockBackend *blk;
    uint64_t size;
};


static ssize_t block_crypto_write_func(QCryptoBlock *block,
                                       size_t offset,
                                       const uint8_t *buf,
                                       size_t buflen,
83
                                       void *opaque,
84
                                       Error **errp)
85 86 87 88
{
    struct BlockCryptoCreateData *data = opaque;
    ssize_t ret;

89
    ret = blk_pwrite(data->blk, offset, buf, buflen, 0);
90 91 92 93 94 95 96 97 98 99
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Could not write encryption header");
        return ret;
    }
    return ret;
}


static ssize_t block_crypto_init_func(QCryptoBlock *block,
                                      size_t headerlen,
100
                                      void *opaque,
101
                                      Error **errp)
102 103 104
{
    struct BlockCryptoCreateData *data = opaque;

105 106 107 108 109
    if (data->size > INT64_MAX || headerlen > INT64_MAX - data->size) {
        error_setg(errp, "The requested file size is too large");
        return -EFBIG;
    }

110 111 112 113
    /* User provided size should reflect amount of space made
     * available to the guest, so we must take account of that
     * which will be used by the crypto header
     */
114 115
    return blk_truncate(data->blk, data->size + headerlen, PREALLOC_MODE_OFF,
                        errp);
116 117 118 119 120 121 122
}


static QemuOptsList block_crypto_runtime_opts_luks = {
    .name = "crypto",
    .head = QTAILQ_HEAD_INITIALIZER(block_crypto_runtime_opts_luks.head),
    .desc = {
123
        BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(""),
124 125 126 127 128 129 130 131 132 133 134 135 136 137
        { /* end of list */ }
    },
};


static QemuOptsList block_crypto_create_opts_luks = {
    .name = "crypto",
    .head = QTAILQ_HEAD_INITIALIZER(block_crypto_create_opts_luks.head),
    .desc = {
        {
            .name = BLOCK_OPT_SIZE,
            .type = QEMU_OPT_SIZE,
            .help = "Virtual disk size"
        },
138 139 140 141 142 143 144
        BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(""),
        BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG(""),
        BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE(""),
        BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG(""),
        BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(""),
        BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(""),
        BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""),
145 146 147 148 149
        { /* end of list */ }
    },
};


150
QCryptoBlockOpenOptions *
151
block_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 165 166 167
    return ret;
}


168
QCryptoBlockCreateOptions *
169
block_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 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
    return ret;
}


static int block_crypto_open_generic(QCryptoBlockFormat format,
                                     QemuOptsList *opts_spec,
                                     BlockDriverState *bs,
                                     QDict *options,
                                     int flags,
                                     Error **errp)
{
    BlockCrypto *crypto = bs->opaque;
    QemuOpts *opts = NULL;
    Error *local_err = NULL;
    int ret = -EINVAL;
    QCryptoBlockOpenOptions *open_opts = NULL;
    unsigned int cflags = 0;
199
    QDict *cryptoopts = NULL;
200

201 202 203 204 205 206
    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
                               false, errp);
    if (!bs->file) {
        return -EINVAL;
    }

207 208 209
    bs->supported_write_flags = BDRV_REQ_FUA &
        bs->file->bs->supported_write_flags;

210 211 212 213 214 215 216
    opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort);
    qemu_opts_absorb_qdict(opts, options, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        goto cleanup;
    }

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 222 223 224 225 226 227
    if (!open_opts) {
        goto cleanup;
    }

    if (flags & BDRV_O_NO_IO) {
        cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
    }
228
    crypto->block = qcrypto_block_open(open_opts, NULL,
229 230 231 232 233 234 235 236 237 238
                                       block_crypto_read_func,
                                       bs,
                                       cflags,
                                       errp);

    if (!crypto->block) {
        ret = -EIO;
        goto cleanup;
    }

239
    bs->encrypted = true;
240 241 242

    ret = 0;
 cleanup:
243
    qobject_unref(cryptoopts);
244 245 246 247 248
    qapi_free_QCryptoBlockOpenOptions(open_opts);
    return ret;
}


249 250 251 252
static int block_crypto_co_create_generic(BlockDriverState *bs,
                                          int64_t size,
                                          QCryptoBlockCreateOptions *opts,
                                          Error **errp)
253
{
254 255
    int ret;
    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 267 268 269
    data = (struct BlockCryptoCreateData) {
        .blk = blk,
        .size = size,
    };
270

271
    crypto = qcrypto_block_create(opts, NULL,
272 273 274 275 276 277 278 279 280 281 282 283 284
                                  block_crypto_init_func,
                                  block_crypto_write_func,
                                  &data,
                                  errp);

    if (!crypto) {
        ret = -EIO;
        goto cleanup;
    }

    ret = 0;
 cleanup:
    qcrypto_block_free(crypto);
285
    blk_unref(blk);
286 287 288
    return ret;
}

289 290 291
static int coroutine_fn
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset,
                         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 298 299 300

    if (payload_offset > INT64_MAX - offset) {
        error_setg(errp, "The requested file size is too large");
        return -EFBIG;
    }
301 302 303

    offset += payload_offset;

304
    return bdrv_co_truncate(bs->file, offset, prealloc, errp);
305 306 307 308 309 310 311 312
}

static void block_crypto_close(BlockDriverState *bs)
{
    BlockCrypto *crypto = bs->opaque;
    qcrypto_block_free(crypto->block);
}

313 314 315 316 317 318
static int block_crypto_reopen_prepare(BDRVReopenState *state,
                                       BlockReopenQueue *queue, Error **errp)
{
    /* nothing needs checking */
    return 0;
}
319

320 321 322 323 324
/*
 * 1 MB bounce buffer gives good performance / memory tradeoff
 * when using cache=none|directsync.
 */
#define BLOCK_CRYPTO_MAX_IO_SIZE (1024 * 1024)
325 326

static coroutine_fn int
327 328
block_crypto_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
                       QEMUIOVector *qiov, int flags)
329 330
{
    BlockCrypto *crypto = bs->opaque;
331
    uint64_t cur_bytes; /* number of bytes in current iteration */
332 333 334 335
    uint64_t bytes_done = 0;
    uint8_t *cipher_data = NULL;
    QEMUIOVector hd_qiov;
    int ret = 0;
336 337 338 339 340 341 342
    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
    uint64_t payload_offset = qcrypto_block_get_payload_offset(crypto->block);

    assert(!flags);
    assert(payload_offset < INT64_MAX);
    assert(QEMU_IS_ALIGNED(offset, sector_size));
    assert(QEMU_IS_ALIGNED(bytes, sector_size));
343 344 345

    qemu_iovec_init(&hd_qiov, qiov->niov);

346 347
    /* Bounce buffer because we don't wish to expose cipher text
     * 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 352 353 354 355 356
                                              qiov->size));
    if (cipher_data == NULL) {
        ret = -ENOMEM;
        goto cleanup;
    }

357 358
    while (bytes) {
        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 364
        ret = bdrv_co_preadv(bs->file, payload_offset + offset + bytes_done,
                             cur_bytes, &hd_qiov, 0);
365 366 367 368
        if (ret < 0) {
            goto cleanup;
        }

369 370
        if (qcrypto_block_decrypt(crypto->block, offset + bytes_done,
                                  cipher_data, cur_bytes, NULL) < 0) {
371 372 373 374
            ret = -EIO;
            goto cleanup;
        }

375
        qemu_iovec_from_buf(qiov, bytes_done, cipher_data, cur_bytes);
376

377 378
        bytes -= cur_bytes;
        bytes_done += cur_bytes;
379 380 381 382 383 384 385 386 387 388 389
    }

 cleanup:
    qemu_iovec_destroy(&hd_qiov);
    qemu_vfree(cipher_data);

    return ret;
}


static coroutine_fn int
390 391
block_crypto_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
                        QEMUIOVector *qiov, int flags)
392 393
{
    BlockCrypto *crypto = bs->opaque;
394
    uint64_t cur_bytes; /* number of bytes in current iteration */
395 396 397 398
    uint64_t bytes_done = 0;
    uint8_t *cipher_data = NULL;
    QEMUIOVector hd_qiov;
    int ret = 0;
399 400 401
    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
    uint64_t payload_offset = qcrypto_block_get_payload_offset(crypto->block);

402
    assert(!(flags & ~BDRV_REQ_FUA));
403 404 405
    assert(payload_offset < INT64_MAX);
    assert(QEMU_IS_ALIGNED(offset, sector_size));
    assert(QEMU_IS_ALIGNED(bytes, sector_size));
406 407 408

    qemu_iovec_init(&hd_qiov, qiov->niov);

409 410
    /* Bounce buffer because we're not permitted to touch
     * 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 415 416 417 418 419
                                              qiov->size));
    if (cipher_data == NULL) {
        ret = -ENOMEM;
        goto cleanup;
    }

420 421
    while (bytes) {
        cur_bytes = MIN(bytes, BLOCK_CRYPTO_MAX_IO_SIZE);
422

423
        qemu_iovec_to_buf(qiov, bytes_done, cipher_data, cur_bytes);
424

425 426
        if (qcrypto_block_encrypt(crypto->block, offset + bytes_done,
                                  cipher_data, cur_bytes, NULL) < 0) {
427 428 429 430 431
            ret = -EIO;
            goto cleanup;
        }

        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 437 438 439
        if (ret < 0) {
            goto cleanup;
        }

440 441
        bytes -= cur_bytes;
        bytes_done += cur_bytes;
442 443 444 445 446 447 448 449 450
    }

 cleanup:
    qemu_iovec_destroy(&hd_qiov);
    qemu_vfree(cipher_data);

    return ret;
}

451 452 453 454 455 456 457
static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp)
{
    BlockCrypto *crypto = bs->opaque;
    uint64_t sector_size = qcrypto_block_get_sector_size(crypto->block);
    bs->bl.request_alignment = sector_size; /* No sub-sector I/O */
}

458 459 460 461 462 463

static int64_t block_crypto_getlength(BlockDriverState *bs)
{
    BlockCrypto *crypto = bs->opaque;
    int64_t len = bdrv_getlength(bs->file->bs);

464 465
    uint64_t offset = qcrypto_block_get_payload_offset(crypto->block);
    assert(offset < INT64_MAX);
466 467 468 469

    if (offset > len) {
        return -EIO;
    }
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493

    len -= offset;

    return len;
}


static int block_crypto_probe_luks(const uint8_t *buf,
                                   int buf_size,
                                   const char *filename) {
    return block_crypto_probe_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
                                      buf, buf_size, filename);
}

static int block_crypto_open_luks(BlockDriverState *bs,
                                  QDict *options,
                                  int flags,
                                  Error **errp)
{
    return block_crypto_open_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
                                     &block_crypto_runtime_opts_luks,
                                     bs, options, flags, errp);
}

K
Kevin Wolf 已提交
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
static int coroutine_fn
block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
{
    BlockdevCreateOptionsLUKS *luks_opts;
    BlockDriverState *bs = NULL;
    QCryptoBlockCreateOptions create_opts;
    int ret;

    assert(create_options->driver == BLOCKDEV_DRIVER_LUKS);
    luks_opts = &create_options->u.luks;

    bs = bdrv_open_blockdev_ref(luks_opts->file, errp);
    if (bs == NULL) {
        return -EIO;
    }

    create_opts = (QCryptoBlockCreateOptions) {
        .format = Q_CRYPTO_BLOCK_FORMAT_LUKS,
        .u.luks = *qapi_BlockdevCreateOptionsLUKS_base(luks_opts),
    };

    ret = block_crypto_co_create_generic(bs, luks_opts->size, &create_opts,
                                         errp);
    if (ret < 0) {
        goto fail;
    }

    ret = 0;
fail:
    bdrv_unref(bs);
    return ret;
}

527 528 529
static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
                                                         QemuOpts *opts,
                                                         Error **errp)
530
{
531 532 533 534 535 536 537 538 539 540 541 542 543
    QCryptoBlockCreateOptions *create_opts = NULL;
    BlockDriverState *bs = NULL;
    QDict *cryptoopts;
    int64_t size;
    int ret;

    /* Parse options */
    size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);

    cryptoopts = qemu_opts_to_qdict_filtered(opts, NULL,
                                             &block_crypto_create_opts_luks,
                                             true);

544 545
    qdict_put_str(cryptoopts, "format", "luks");
    create_opts = block_crypto_create_opts_init(cryptoopts, errp);
546 547 548 549 550 551 552 553
    if (!create_opts) {
        ret = -EINVAL;
        goto fail;
    }

    /* Create protocol layer */
    ret = bdrv_create_file(filename, opts, errp);
    if (ret < 0) {
554
        goto fail;
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
    }

    bs = bdrv_open(filename, NULL, NULL,
                   BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
    if (!bs) {
        ret = -EINVAL;
        goto fail;
    }

    /* Create format layer */
    ret = block_crypto_co_create_generic(bs, size, create_opts, errp);
    if (ret < 0) {
        goto fail;
    }

    ret = 0;
fail:
    bdrv_unref(bs);
    qapi_free_QCryptoBlockCreateOptions(create_opts);
574
    qobject_unref(cryptoopts);
575
    return ret;
576 577
}

578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
static int block_crypto_get_info_luks(BlockDriverState *bs,
                                      BlockDriverInfo *bdi)
{
    BlockDriverInfo subbdi;
    int ret;

    ret = bdrv_get_info(bs->file->bs, &subbdi);
    if (ret != 0) {
        return ret;
    }

    bdi->unallocated_blocks_are_zero = false;
    bdi->cluster_size = subbdi.cluster_size;

    return 0;
}

static ImageInfoSpecific *
block_crypto_get_specific_info_luks(BlockDriverState *bs)
{
    BlockCrypto *crypto = bs->opaque;
    ImageInfoSpecific *spec_info;
    QCryptoBlockInfo *info;

    info = qcrypto_block_get_info(crypto->block, NULL);
    if (!info) {
        return NULL;
    }
    if (info->format != Q_CRYPTO_BLOCK_FORMAT_LUKS) {
        qapi_free_QCryptoBlockInfo(info);
        return NULL;
    }

    spec_info = g_new(ImageInfoSpecific, 1);
    spec_info->type = IMAGE_INFO_SPECIFIC_KIND_LUKS;
    spec_info->u.luks.data = g_new(QCryptoBlockInfoLUKS, 1);
    *spec_info->u.luks.data = info->u.luks;

    /* Blank out pointers we've just stolen to avoid double free */
    memset(&info->u.luks, 0, sizeof(info->u.luks));

    qapi_free_QCryptoBlockInfo(info);

    return spec_info;
}

624 625 626 627 628 629
BlockDriver bdrv_crypto_luks = {
    .format_name        = "luks",
    .instance_size      = sizeof(BlockCrypto),
    .bdrv_probe         = block_crypto_probe_luks,
    .bdrv_open          = block_crypto_open_luks,
    .bdrv_close         = block_crypto_close,
630
    .bdrv_child_perm    = bdrv_format_default_perms,
K
Kevin Wolf 已提交
631
    .bdrv_co_create     = block_crypto_co_create_luks,
632
    .bdrv_co_create_opts = block_crypto_co_create_opts_luks,
633
    .bdrv_co_truncate   = block_crypto_co_truncate,
634 635
    .create_opts        = &block_crypto_create_opts_luks,

636
    .bdrv_reopen_prepare = block_crypto_reopen_prepare,
637 638 639
    .bdrv_refresh_limits = block_crypto_refresh_limits,
    .bdrv_co_preadv     = block_crypto_co_preadv,
    .bdrv_co_pwritev    = block_crypto_co_pwritev,
640
    .bdrv_getlength     = block_crypto_getlength,
641 642
    .bdrv_get_info      = block_crypto_get_info_luks,
    .bdrv_get_specific_info = block_crypto_get_specific_info_luks,
643 644 645 646 647 648 649 650
};

static void block_crypto_init(void)
{
    bdrv_register(&bdrv_crypto_luks);
}

block_init(block_crypto_init);