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