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