xref: /openbmc/qemu/block/crypto.c (revision 121d0712)
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-visit.h"
28 #include "qapi/error.h"
29 
30 #define BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET "key-secret"
31 #define BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG "cipher-alg"
32 #define BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE "cipher-mode"
33 #define BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG "ivgen-alg"
34 #define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-alg"
35 #define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg"
36 
37 typedef struct BlockCrypto BlockCrypto;
38 
39 struct BlockCrypto {
40     QCryptoBlock *block;
41 };
42 
43 
44 static int block_crypto_probe_generic(QCryptoBlockFormat format,
45                                       const uint8_t *buf,
46                                       int buf_size,
47                                       const char *filename)
48 {
49     if (qcrypto_block_has_format(format, buf, buf_size)) {
50         return 100;
51     } else {
52         return 0;
53     }
54 }
55 
56 
57 static ssize_t block_crypto_read_func(QCryptoBlock *block,
58                                       size_t offset,
59                                       uint8_t *buf,
60                                       size_t buflen,
61                                       Error **errp,
62                                       void *opaque)
63 {
64     BlockDriverState *bs = opaque;
65     ssize_t ret;
66 
67     ret = bdrv_pread(bs->file, offset, buf, buflen);
68     if (ret < 0) {
69         error_setg_errno(errp, -ret, "Could not read encryption header");
70         return ret;
71     }
72     return ret;
73 }
74 
75 
76 struct BlockCryptoCreateData {
77     const char *filename;
78     QemuOpts *opts;
79     BlockBackend *blk;
80     uint64_t size;
81 };
82 
83 
84 static ssize_t block_crypto_write_func(QCryptoBlock *block,
85                                        size_t offset,
86                                        const uint8_t *buf,
87                                        size_t buflen,
88                                        Error **errp,
89                                        void *opaque)
90 {
91     struct BlockCryptoCreateData *data = opaque;
92     ssize_t ret;
93 
94     ret = blk_pwrite(data->blk, offset, buf, buflen, 0);
95     if (ret < 0) {
96         error_setg_errno(errp, -ret, "Could not write encryption header");
97         return ret;
98     }
99     return ret;
100 }
101 
102 
103 static ssize_t block_crypto_init_func(QCryptoBlock *block,
104                                       size_t headerlen,
105                                       Error **errp,
106                                       void *opaque)
107 {
108     struct BlockCryptoCreateData *data = opaque;
109     int ret;
110 
111     /* User provided size should reflect amount of space made
112      * available to the guest, so we must take account of that
113      * which will be used by the crypto header
114      */
115     data->size += headerlen;
116 
117     qemu_opt_set_number(data->opts, BLOCK_OPT_SIZE, data->size, &error_abort);
118     ret = bdrv_create_file(data->filename, data->opts, errp);
119     if (ret < 0) {
120         return -1;
121     }
122 
123     data->blk = blk_new_open(data->filename, NULL, NULL,
124                              BDRV_O_RDWR | BDRV_O_PROTOCOL, errp);
125     if (!data->blk) {
126         return -1;
127     }
128 
129     return 0;
130 }
131 
132 
133 static QemuOptsList block_crypto_runtime_opts_luks = {
134     .name = "crypto",
135     .head = QTAILQ_HEAD_INITIALIZER(block_crypto_runtime_opts_luks.head),
136     .desc = {
137         {
138             .name = BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
139             .type = QEMU_OPT_STRING,
140             .help = "ID of the secret that provides the encryption key",
141         },
142         { /* end of list */ }
143     },
144 };
145 
146 
147 static QemuOptsList block_crypto_create_opts_luks = {
148     .name = "crypto",
149     .head = QTAILQ_HEAD_INITIALIZER(block_crypto_create_opts_luks.head),
150     .desc = {
151         {
152             .name = BLOCK_OPT_SIZE,
153             .type = QEMU_OPT_SIZE,
154             .help = "Virtual disk size"
155         },
156         {
157             .name = BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
158             .type = QEMU_OPT_STRING,
159             .help = "ID of the secret that provides the encryption key",
160         },
161         {
162             .name = BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG,
163             .type = QEMU_OPT_STRING,
164             .help = "Name of encryption cipher algorithm",
165         },
166         {
167             .name = BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE,
168             .type = QEMU_OPT_STRING,
169             .help = "Name of encryption cipher mode",
170         },
171         {
172             .name = BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG,
173             .type = QEMU_OPT_STRING,
174             .help = "Name of IV generator algorithm",
175         },
176         {
177             .name = BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG,
178             .type = QEMU_OPT_STRING,
179             .help = "Name of IV generator hash algorithm",
180         },
181         {
182             .name = BLOCK_CRYPTO_OPT_LUKS_HASH_ALG,
183             .type = QEMU_OPT_STRING,
184             .help = "Name of encryption hash algorithm",
185         },
186         { /* end of list */ }
187     },
188 };
189 
190 
191 static QCryptoBlockOpenOptions *
192 block_crypto_open_opts_init(QCryptoBlockFormat format,
193                             QemuOpts *opts,
194                             Error **errp)
195 {
196     Visitor *v;
197     QCryptoBlockOpenOptions *ret = NULL;
198     Error *local_err = NULL;
199 
200     ret = g_new0(QCryptoBlockOpenOptions, 1);
201     ret->format = format;
202 
203     v = opts_visitor_new(opts);
204 
205     visit_start_struct(v, NULL, NULL, 0, &local_err);
206     if (local_err) {
207         goto out;
208     }
209 
210     switch (format) {
211     case Q_CRYPTO_BLOCK_FORMAT_LUKS:
212         visit_type_QCryptoBlockOptionsLUKS_members(
213             v, &ret->u.luks, &local_err);
214         break;
215 
216     default:
217         error_setg(&local_err, "Unsupported block format %d", format);
218         break;
219     }
220     if (!local_err) {
221         visit_check_struct(v, &local_err);
222     }
223 
224     visit_end_struct(v, NULL);
225 
226  out:
227     if (local_err) {
228         error_propagate(errp, local_err);
229         qapi_free_QCryptoBlockOpenOptions(ret);
230         ret = NULL;
231     }
232     visit_free(v);
233     return ret;
234 }
235 
236 
237 static QCryptoBlockCreateOptions *
238 block_crypto_create_opts_init(QCryptoBlockFormat format,
239                               QemuOpts *opts,
240                               Error **errp)
241 {
242     Visitor *v;
243     QCryptoBlockCreateOptions *ret = NULL;
244     Error *local_err = NULL;
245 
246     ret = g_new0(QCryptoBlockCreateOptions, 1);
247     ret->format = format;
248 
249     v = opts_visitor_new(opts);
250 
251     visit_start_struct(v, NULL, NULL, 0, &local_err);
252     if (local_err) {
253         goto out;
254     }
255 
256     switch (format) {
257     case Q_CRYPTO_BLOCK_FORMAT_LUKS:
258         visit_type_QCryptoBlockCreateOptionsLUKS_members(
259             v, &ret->u.luks, &local_err);
260         break;
261 
262     default:
263         error_setg(&local_err, "Unsupported block format %d", format);
264         break;
265     }
266     if (!local_err) {
267         visit_check_struct(v, &local_err);
268     }
269 
270     visit_end_struct(v, NULL);
271 
272  out:
273     if (local_err) {
274         error_propagate(errp, local_err);
275         qapi_free_QCryptoBlockCreateOptions(ret);
276         ret = NULL;
277     }
278     visit_free(v);
279     return ret;
280 }
281 
282 
283 static int block_crypto_open_generic(QCryptoBlockFormat format,
284                                      QemuOptsList *opts_spec,
285                                      BlockDriverState *bs,
286                                      QDict *options,
287                                      int flags,
288                                      Error **errp)
289 {
290     BlockCrypto *crypto = bs->opaque;
291     QemuOpts *opts = NULL;
292     Error *local_err = NULL;
293     int ret = -EINVAL;
294     QCryptoBlockOpenOptions *open_opts = NULL;
295     unsigned int cflags = 0;
296 
297     opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort);
298     qemu_opts_absorb_qdict(opts, options, &local_err);
299     if (local_err) {
300         error_propagate(errp, local_err);
301         goto cleanup;
302     }
303 
304     open_opts = block_crypto_open_opts_init(format, opts, errp);
305     if (!open_opts) {
306         goto cleanup;
307     }
308 
309     if (flags & BDRV_O_NO_IO) {
310         cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
311     }
312     crypto->block = qcrypto_block_open(open_opts,
313                                        block_crypto_read_func,
314                                        bs,
315                                        cflags,
316                                        errp);
317 
318     if (!crypto->block) {
319         ret = -EIO;
320         goto cleanup;
321     }
322 
323     bs->encrypted = true;
324     bs->valid_key = true;
325 
326     ret = 0;
327  cleanup:
328     qapi_free_QCryptoBlockOpenOptions(open_opts);
329     return ret;
330 }
331 
332 
333 static int block_crypto_create_generic(QCryptoBlockFormat format,
334                                        const char *filename,
335                                        QemuOpts *opts,
336                                        Error **errp)
337 {
338     int ret = -EINVAL;
339     QCryptoBlockCreateOptions *create_opts = NULL;
340     QCryptoBlock *crypto = NULL;
341     struct BlockCryptoCreateData data = {
342         .size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
343                          BDRV_SECTOR_SIZE),
344         .opts = opts,
345         .filename = filename,
346     };
347 
348     create_opts = block_crypto_create_opts_init(format, opts, errp);
349     if (!create_opts) {
350         return -1;
351     }
352 
353     crypto = qcrypto_block_create(create_opts,
354                                   block_crypto_init_func,
355                                   block_crypto_write_func,
356                                   &data,
357                                   errp);
358 
359     if (!crypto) {
360         ret = -EIO;
361         goto cleanup;
362     }
363 
364     ret = 0;
365  cleanup:
366     qcrypto_block_free(crypto);
367     blk_unref(data.blk);
368     qapi_free_QCryptoBlockCreateOptions(create_opts);
369     return ret;
370 }
371 
372 static int block_crypto_truncate(BlockDriverState *bs, int64_t offset)
373 {
374     BlockCrypto *crypto = bs->opaque;
375     size_t payload_offset =
376         qcrypto_block_get_payload_offset(crypto->block);
377 
378     offset += payload_offset;
379 
380     return bdrv_truncate(bs->file->bs, offset);
381 }
382 
383 static void block_crypto_close(BlockDriverState *bs)
384 {
385     BlockCrypto *crypto = bs->opaque;
386     qcrypto_block_free(crypto->block);
387 }
388 
389 
390 #define BLOCK_CRYPTO_MAX_SECTORS 32
391 
392 static coroutine_fn int
393 block_crypto_co_readv(BlockDriverState *bs, int64_t sector_num,
394                       int remaining_sectors, QEMUIOVector *qiov)
395 {
396     BlockCrypto *crypto = bs->opaque;
397     int cur_nr_sectors; /* number of sectors in current iteration */
398     uint64_t bytes_done = 0;
399     uint8_t *cipher_data = NULL;
400     QEMUIOVector hd_qiov;
401     int ret = 0;
402     size_t payload_offset =
403         qcrypto_block_get_payload_offset(crypto->block) / 512;
404 
405     qemu_iovec_init(&hd_qiov, qiov->niov);
406 
407     /* Bounce buffer so we have a linear mem region for
408      * entire sector. XXX optimize so we avoid bounce
409      * buffer in case that qiov->niov == 1
410      */
411     cipher_data =
412         qemu_try_blockalign(bs->file->bs, MIN(BLOCK_CRYPTO_MAX_SECTORS * 512,
413                                               qiov->size));
414     if (cipher_data == NULL) {
415         ret = -ENOMEM;
416         goto cleanup;
417     }
418 
419     while (remaining_sectors) {
420         cur_nr_sectors = remaining_sectors;
421 
422         if (cur_nr_sectors > BLOCK_CRYPTO_MAX_SECTORS) {
423             cur_nr_sectors = BLOCK_CRYPTO_MAX_SECTORS;
424         }
425 
426         qemu_iovec_reset(&hd_qiov);
427         qemu_iovec_add(&hd_qiov, cipher_data, cur_nr_sectors * 512);
428 
429         ret = bdrv_co_readv(bs->file,
430                             payload_offset + sector_num,
431                             cur_nr_sectors, &hd_qiov);
432         if (ret < 0) {
433             goto cleanup;
434         }
435 
436         if (qcrypto_block_decrypt(crypto->block,
437                                   sector_num,
438                                   cipher_data, cur_nr_sectors * 512,
439                                   NULL) < 0) {
440             ret = -EIO;
441             goto cleanup;
442         }
443 
444         qemu_iovec_from_buf(qiov, bytes_done,
445                             cipher_data, cur_nr_sectors * 512);
446 
447         remaining_sectors -= cur_nr_sectors;
448         sector_num += cur_nr_sectors;
449         bytes_done += cur_nr_sectors * 512;
450     }
451 
452  cleanup:
453     qemu_iovec_destroy(&hd_qiov);
454     qemu_vfree(cipher_data);
455 
456     return ret;
457 }
458 
459 
460 static coroutine_fn int
461 block_crypto_co_writev(BlockDriverState *bs, int64_t sector_num,
462                        int remaining_sectors, QEMUIOVector *qiov)
463 {
464     BlockCrypto *crypto = bs->opaque;
465     int cur_nr_sectors; /* number of sectors in current iteration */
466     uint64_t bytes_done = 0;
467     uint8_t *cipher_data = NULL;
468     QEMUIOVector hd_qiov;
469     int ret = 0;
470     size_t payload_offset =
471         qcrypto_block_get_payload_offset(crypto->block) / 512;
472 
473     qemu_iovec_init(&hd_qiov, qiov->niov);
474 
475     /* Bounce buffer so we have a linear mem region for
476      * entire sector. XXX optimize so we avoid bounce
477      * buffer in case that qiov->niov == 1
478      */
479     cipher_data =
480         qemu_try_blockalign(bs->file->bs, MIN(BLOCK_CRYPTO_MAX_SECTORS * 512,
481                                               qiov->size));
482     if (cipher_data == NULL) {
483         ret = -ENOMEM;
484         goto cleanup;
485     }
486 
487     while (remaining_sectors) {
488         cur_nr_sectors = remaining_sectors;
489 
490         if (cur_nr_sectors > BLOCK_CRYPTO_MAX_SECTORS) {
491             cur_nr_sectors = BLOCK_CRYPTO_MAX_SECTORS;
492         }
493 
494         qemu_iovec_to_buf(qiov, bytes_done,
495                           cipher_data, cur_nr_sectors * 512);
496 
497         if (qcrypto_block_encrypt(crypto->block,
498                                   sector_num,
499                                   cipher_data, cur_nr_sectors * 512,
500                                   NULL) < 0) {
501             ret = -EIO;
502             goto cleanup;
503         }
504 
505         qemu_iovec_reset(&hd_qiov);
506         qemu_iovec_add(&hd_qiov, cipher_data, cur_nr_sectors * 512);
507 
508         ret = bdrv_co_writev(bs->file,
509                              payload_offset + sector_num,
510                              cur_nr_sectors, &hd_qiov);
511         if (ret < 0) {
512             goto cleanup;
513         }
514 
515         remaining_sectors -= cur_nr_sectors;
516         sector_num += cur_nr_sectors;
517         bytes_done += cur_nr_sectors * 512;
518     }
519 
520  cleanup:
521     qemu_iovec_destroy(&hd_qiov);
522     qemu_vfree(cipher_data);
523 
524     return ret;
525 }
526 
527 
528 static int64_t block_crypto_getlength(BlockDriverState *bs)
529 {
530     BlockCrypto *crypto = bs->opaque;
531     int64_t len = bdrv_getlength(bs->file->bs);
532 
533     ssize_t offset = qcrypto_block_get_payload_offset(crypto->block);
534 
535     len -= offset;
536 
537     return len;
538 }
539 
540 
541 static int block_crypto_probe_luks(const uint8_t *buf,
542                                    int buf_size,
543                                    const char *filename) {
544     return block_crypto_probe_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
545                                       buf, buf_size, filename);
546 }
547 
548 static int block_crypto_open_luks(BlockDriverState *bs,
549                                   QDict *options,
550                                   int flags,
551                                   Error **errp)
552 {
553     return block_crypto_open_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
554                                      &block_crypto_runtime_opts_luks,
555                                      bs, options, flags, errp);
556 }
557 
558 static int block_crypto_create_luks(const char *filename,
559                                     QemuOpts *opts,
560                                     Error **errp)
561 {
562     return block_crypto_create_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
563                                        filename, opts, errp);
564 }
565 
566 BlockDriver bdrv_crypto_luks = {
567     .format_name        = "luks",
568     .instance_size      = sizeof(BlockCrypto),
569     .bdrv_probe         = block_crypto_probe_luks,
570     .bdrv_open          = block_crypto_open_luks,
571     .bdrv_close         = block_crypto_close,
572     .bdrv_create        = block_crypto_create_luks,
573     .bdrv_truncate      = block_crypto_truncate,
574     .create_opts        = &block_crypto_create_opts_luks,
575 
576     .bdrv_co_readv      = block_crypto_co_readv,
577     .bdrv_co_writev     = block_crypto_co_writev,
578     .bdrv_getlength     = block_crypto_getlength,
579 };
580 
581 static void block_crypto_init(void)
582 {
583     bdrv_register(&bdrv_crypto_luks);
584 }
585 
586 block_init(block_crypto_init);
587