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