xref: /openbmc/qemu/block/crypto.c (revision d40d3da0)
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     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 
320 static 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 
363 static 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 
375 static 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 
384 static coroutine_fn int
385 block_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 
452 static coroutine_fn int
453 block_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 
520 static 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 
533 static 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 
540 static 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 
550 static 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 
558 static 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 
576 static ImageInfoSpecific *
577 block_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 
605 BlockDriver 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 
623 static void block_crypto_init(void)
624 {
625     bdrv_register(&bdrv_crypto_luks);
626 }
627 
628 block_init(block_crypto_init);
629