xref: /openbmc/qemu/crypto/block.c (revision af206c28)
1 /*
2  * QEMU Crypto block device 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.1 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 #include "qapi/error.h"
23 #include "qemu/lockable.h"
24 #include "blockpriv.h"
25 #include "block-qcow.h"
26 #include "block-luks.h"
27 
28 static const QCryptoBlockDriver *qcrypto_block_drivers[] = {
29     [Q_CRYPTO_BLOCK_FORMAT_QCOW] = &qcrypto_block_driver_qcow,
30     [Q_CRYPTO_BLOCK_FORMAT_LUKS] = &qcrypto_block_driver_luks,
31 };
32 
33 
34 bool qcrypto_block_has_format(QCryptoBlockFormat format,
35                               const uint8_t *buf,
36                               size_t len)
37 {
38     const QCryptoBlockDriver *driver;
39 
40     if (format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
41         !qcrypto_block_drivers[format]) {
42         return false;
43     }
44 
45     driver = qcrypto_block_drivers[format];
46 
47     return driver->has_format(buf, len);
48 }
49 
50 
51 QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
52                                  const char *optprefix,
53                                  QCryptoBlockReadFunc readfunc,
54                                  void *opaque,
55                                  unsigned int flags,
56                                  size_t n_threads,
57                                  Error **errp)
58 {
59     QCryptoBlock *block = g_new0(QCryptoBlock, 1);
60 
61     qemu_mutex_init(&block->mutex);
62 
63     block->format = options->format;
64 
65     if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
66         !qcrypto_block_drivers[options->format]) {
67         error_setg(errp, "Unsupported block driver %s",
68                    QCryptoBlockFormat_str(options->format));
69         g_free(block);
70         return NULL;
71     }
72 
73     block->driver = qcrypto_block_drivers[options->format];
74 
75     if (block->driver->open(block, options, optprefix,
76                             readfunc, opaque, flags, n_threads, errp) < 0)
77     {
78         g_free(block);
79         return NULL;
80     }
81 
82     return block;
83 }
84 
85 
86 QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
87                                    const char *optprefix,
88                                    QCryptoBlockInitFunc initfunc,
89                                    QCryptoBlockWriteFunc writefunc,
90                                    void *opaque,
91                                    unsigned int flags,
92                                    Error **errp)
93 {
94     QCryptoBlock *block = g_new0(QCryptoBlock, 1);
95 
96     qemu_mutex_init(&block->mutex);
97 
98     block->format = options->format;
99 
100     if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
101         !qcrypto_block_drivers[options->format]) {
102         error_setg(errp, "Unsupported block driver %s",
103                    QCryptoBlockFormat_str(options->format));
104         g_free(block);
105         return NULL;
106     }
107 
108     block->driver = qcrypto_block_drivers[options->format];
109     block->detached_header = flags & QCRYPTO_BLOCK_CREATE_DETACHED;
110 
111     if (block->driver->create(block, options, optprefix, initfunc,
112                               writefunc, opaque, errp) < 0) {
113         g_free(block);
114         return NULL;
115     }
116 
117     return block;
118 }
119 
120 
121 static int qcrypto_block_headerlen_hdr_init_func(QCryptoBlock *block,
122         size_t headerlen, void *opaque, Error **errp)
123 {
124     size_t *headerlenp = opaque;
125 
126     /* Stash away the payload size */
127     *headerlenp = headerlen;
128     return 0;
129 }
130 
131 
132 static int qcrypto_block_headerlen_hdr_write_func(QCryptoBlock *block,
133         size_t offset, const uint8_t *buf, size_t buflen,
134         void *opaque, Error **errp)
135 {
136     /* Discard the bytes, we're not actually writing to an image */
137     return 0;
138 }
139 
140 
141 bool
142 qcrypto_block_calculate_payload_offset(QCryptoBlockCreateOptions *create_opts,
143                                        const char *optprefix,
144                                        size_t *len,
145                                        Error **errp)
146 {
147     /* Fake LUKS creation in order to determine the payload size */
148     g_autoptr(QCryptoBlock) crypto =
149         qcrypto_block_create(create_opts, optprefix,
150                              qcrypto_block_headerlen_hdr_init_func,
151                              qcrypto_block_headerlen_hdr_write_func,
152                              len, 0, errp);
153     return crypto != NULL;
154 }
155 
156 int qcrypto_block_amend_options(QCryptoBlock *block,
157                                 QCryptoBlockReadFunc readfunc,
158                                 QCryptoBlockWriteFunc writefunc,
159                                 void *opaque,
160                                 QCryptoBlockAmendOptions *options,
161                                 bool force,
162                                 Error **errp)
163 {
164     if (options->format != block->format) {
165         error_setg(errp,
166                    "Cannot amend encryption format");
167         return -1;
168     }
169 
170     if (!block->driver->amend) {
171         error_setg(errp,
172                    "Crypto format %s doesn't support format options amendment",
173                    QCryptoBlockFormat_str(block->format));
174         return -1;
175     }
176 
177     return block->driver->amend(block,
178                                 readfunc,
179                                 writefunc,
180                                 opaque,
181                                 options,
182                                 force,
183                                 errp);
184 }
185 
186 QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block,
187                                          Error **errp)
188 {
189     QCryptoBlockInfo *info = g_new0(QCryptoBlockInfo, 1);
190 
191     info->format = block->format;
192 
193     if (block->driver->get_info &&
194         block->driver->get_info(block, info, errp) < 0) {
195         g_free(info);
196         return NULL;
197     }
198 
199     return info;
200 }
201 
202 
203 int qcrypto_block_decrypt(QCryptoBlock *block,
204                           uint64_t offset,
205                           uint8_t *buf,
206                           size_t len,
207                           Error **errp)
208 {
209     return block->driver->decrypt(block, offset, buf, len, errp);
210 }
211 
212 
213 int qcrypto_block_encrypt(QCryptoBlock *block,
214                           uint64_t offset,
215                           uint8_t *buf,
216                           size_t len,
217                           Error **errp)
218 {
219     return block->driver->encrypt(block, offset, buf, len, errp);
220 }
221 
222 
223 QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block)
224 {
225     /* Ciphers should be accessed through pop/push method to be thread-safe.
226      * Better, they should not be accessed externally at all (note, that
227      * pop/push are static functions)
228      * This function is used only in test with one thread (it's safe to skip
229      * pop/push interface), so it's enough to assert it here:
230      */
231     assert(block->max_free_ciphers <= 1);
232     return block->free_ciphers ? block->free_ciphers[0] : NULL;
233 }
234 
235 
236 static QCryptoCipher *qcrypto_block_pop_cipher(QCryptoBlock *block,
237                                                Error **errp)
238 {
239     /* Usually there is a free cipher available */
240     WITH_QEMU_LOCK_GUARD(&block->mutex) {
241         if (block->n_free_ciphers > 0) {
242             block->n_free_ciphers--;
243             return block->free_ciphers[block->n_free_ciphers];
244         }
245     }
246 
247     /* Otherwise allocate a new cipher */
248     return qcrypto_cipher_new(block->alg, block->mode, block->key,
249                               block->nkey, errp);
250 }
251 
252 
253 static void qcrypto_block_push_cipher(QCryptoBlock *block,
254                                       QCryptoCipher *cipher)
255 {
256     QEMU_LOCK_GUARD(&block->mutex);
257 
258     if (block->n_free_ciphers == block->max_free_ciphers) {
259         block->max_free_ciphers++;
260         block->free_ciphers = g_renew(QCryptoCipher *,
261                                       block->free_ciphers,
262                                       block->max_free_ciphers);
263     }
264 
265     block->free_ciphers[block->n_free_ciphers] = cipher;
266     block->n_free_ciphers++;
267 }
268 
269 
270 int qcrypto_block_init_cipher(QCryptoBlock *block,
271                               QCryptoCipherAlgorithm alg,
272                               QCryptoCipherMode mode,
273                               const uint8_t *key, size_t nkey,
274                               Error **errp)
275 {
276     QCryptoCipher *cipher;
277 
278     assert(!block->free_ciphers && !block->max_free_ciphers &&
279            !block->n_free_ciphers);
280 
281     /* Stash away cipher parameters for qcrypto_block_pop_cipher() */
282     block->alg = alg;
283     block->mode = mode;
284     block->key = g_memdup2(key, nkey);
285     block->nkey = nkey;
286 
287     /*
288      * Create a new cipher to validate the parameters now. This reduces the
289      * chance of cipher creation failing at I/O time.
290      */
291     cipher = qcrypto_block_pop_cipher(block, errp);
292     if (!cipher) {
293         g_free(block->key);
294         block->key = NULL;
295         return -1;
296     }
297 
298     qcrypto_block_push_cipher(block, cipher);
299     return 0;
300 }
301 
302 
303 void qcrypto_block_free_cipher(QCryptoBlock *block)
304 {
305     size_t i;
306 
307     g_free(block->key);
308     block->key = NULL;
309 
310     if (!block->free_ciphers) {
311         return;
312     }
313 
314     /* All popped ciphers were eventually pushed back */
315     assert(block->n_free_ciphers == block->max_free_ciphers);
316 
317     for (i = 0; i < block->max_free_ciphers; i++) {
318         qcrypto_cipher_free(block->free_ciphers[i]);
319     }
320 
321     g_free(block->free_ciphers);
322     block->free_ciphers = NULL;
323     block->max_free_ciphers = block->n_free_ciphers = 0;
324 }
325 
326 QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block)
327 {
328     /* ivgen should be accessed under mutex. However, this function is used only
329      * in test with one thread, so it's enough to assert it here:
330      */
331     assert(block->max_free_ciphers <= 1);
332     return block->ivgen;
333 }
334 
335 
336 QCryptoHashAlgorithm qcrypto_block_get_kdf_hash(QCryptoBlock *block)
337 {
338     return block->kdfhash;
339 }
340 
341 
342 uint64_t qcrypto_block_get_payload_offset(QCryptoBlock *block)
343 {
344     return block->payload_offset;
345 }
346 
347 
348 uint64_t qcrypto_block_get_sector_size(QCryptoBlock *block)
349 {
350     return block->sector_size;
351 }
352 
353 
354 void qcrypto_block_free(QCryptoBlock *block)
355 {
356     if (!block) {
357         return;
358     }
359 
360     block->driver->cleanup(block);
361 
362     qcrypto_block_free_cipher(block);
363     qcrypto_ivgen_free(block->ivgen);
364     qemu_mutex_destroy(&block->mutex);
365     g_free(block);
366 }
367 
368 
369 typedef int (*QCryptoCipherEncDecFunc)(QCryptoCipher *cipher,
370                                         const void *in,
371                                         void *out,
372                                         size_t len,
373                                         Error **errp);
374 
375 static int do_qcrypto_block_cipher_encdec(QCryptoCipher *cipher,
376                                           size_t niv,
377                                           QCryptoIVGen *ivgen,
378                                           QemuMutex *ivgen_mutex,
379                                           int sectorsize,
380                                           uint64_t offset,
381                                           uint8_t *buf,
382                                           size_t len,
383                                           QCryptoCipherEncDecFunc func,
384                                           Error **errp)
385 {
386     g_autofree uint8_t *iv = niv ? g_new0(uint8_t, niv) : NULL;
387     int ret = -1;
388     uint64_t startsector = offset / sectorsize;
389 
390     assert(QEMU_IS_ALIGNED(offset, sectorsize));
391     assert(QEMU_IS_ALIGNED(len, sectorsize));
392 
393     while (len > 0) {
394         size_t nbytes;
395         if (niv) {
396             if (ivgen_mutex) {
397                 qemu_mutex_lock(ivgen_mutex);
398             }
399             ret = qcrypto_ivgen_calculate(ivgen, startsector, iv, niv, errp);
400             if (ivgen_mutex) {
401                 qemu_mutex_unlock(ivgen_mutex);
402             }
403 
404             if (ret < 0) {
405                 return -1;
406             }
407 
408             if (qcrypto_cipher_setiv(cipher,
409                                      iv, niv,
410                                      errp) < 0) {
411                 return -1;
412             }
413         }
414 
415         nbytes = len > sectorsize ? sectorsize : len;
416         if (func(cipher, buf, buf, nbytes, errp) < 0) {
417             return -1;
418         }
419 
420         startsector++;
421         buf += nbytes;
422         len -= nbytes;
423     }
424 
425     return 0;
426 }
427 
428 
429 int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher,
430                                         size_t niv,
431                                         QCryptoIVGen *ivgen,
432                                         int sectorsize,
433                                         uint64_t offset,
434                                         uint8_t *buf,
435                                         size_t len,
436                                         Error **errp)
437 {
438     return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
439                                           offset, buf, len,
440                                           qcrypto_cipher_decrypt, errp);
441 }
442 
443 
444 int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher,
445                                         size_t niv,
446                                         QCryptoIVGen *ivgen,
447                                         int sectorsize,
448                                         uint64_t offset,
449                                         uint8_t *buf,
450                                         size_t len,
451                                         Error **errp)
452 {
453     return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
454                                           offset, buf, len,
455                                           qcrypto_cipher_encrypt, errp);
456 }
457 
458 int qcrypto_block_decrypt_helper(QCryptoBlock *block,
459                                  int sectorsize,
460                                  uint64_t offset,
461                                  uint8_t *buf,
462                                  size_t len,
463                                  Error **errp)
464 {
465     int ret;
466     QCryptoCipher *cipher = qcrypto_block_pop_cipher(block, errp);
467     if (!cipher) {
468         return -1;
469     }
470 
471     ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
472                                          &block->mutex, sectorsize, offset, buf,
473                                          len, qcrypto_cipher_decrypt, errp);
474 
475     qcrypto_block_push_cipher(block, cipher);
476 
477     return ret;
478 }
479 
480 int qcrypto_block_encrypt_helper(QCryptoBlock *block,
481                                  int sectorsize,
482                                  uint64_t offset,
483                                  uint8_t *buf,
484                                  size_t len,
485                                  Error **errp)
486 {
487     int ret;
488     QCryptoCipher *cipher = qcrypto_block_pop_cipher(block, errp);
489     if (!cipher) {
490         return -1;
491     }
492 
493     ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
494                                          &block->mutex, sectorsize, offset, buf,
495                                          len, qcrypto_cipher_encrypt, errp);
496 
497     qcrypto_block_push_cipher(block, cipher);
498 
499     return ret;
500 }
501