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