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