Merge tag 'pull-request-2024-06-12' of https://gitlab.com/thuth/qemu into staging
[qemu/kevin.git] / crypto / block.c
blob3bcc4270c3c69cec168c9b8087841928b04f981c
1 /*
2 * QEMU Crypto block device encryption
4 * Copyright (c) 2015-2016 Red Hat, Inc.
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.
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.
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/>.
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"
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,
34 bool qcrypto_block_has_format(QCryptoBlockFormat format,
35 const uint8_t *buf,
36 size_t len)
38 const QCryptoBlockDriver *driver;
40 if (format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
41 !qcrypto_block_drivers[format]) {
42 return false;
45 driver = qcrypto_block_drivers[format];
47 return driver->has_format(buf, len);
51 QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
52 const char *optprefix,
53 QCryptoBlockReadFunc readfunc,
54 void *opaque,
55 unsigned int flags,
56 Error **errp)
58 QCryptoBlock *block = g_new0(QCryptoBlock, 1);
60 qemu_mutex_init(&block->mutex);
62 block->format = options->format;
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;
72 block->driver = qcrypto_block_drivers[options->format];
74 if (block->driver->open(block, options, optprefix,
75 readfunc, opaque, flags, errp) < 0)
77 g_free(block);
78 return NULL;
81 return block;
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)
93 QCryptoBlock *block = g_new0(QCryptoBlock, 1);
95 qemu_mutex_init(&block->mutex);
97 block->format = options->format;
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;
107 block->driver = qcrypto_block_drivers[options->format];
108 block->detached_header = flags & QCRYPTO_BLOCK_CREATE_DETACHED;
110 if (block->driver->create(block, options, optprefix, initfunc,
111 writefunc, opaque, errp) < 0) {
112 g_free(block);
113 return NULL;
116 return block;
120 static int qcrypto_block_headerlen_hdr_init_func(QCryptoBlock *block,
121 size_t headerlen, void *opaque, Error **errp)
123 size_t *headerlenp = opaque;
125 /* Stash away the payload size */
126 *headerlenp = headerlen;
127 return 0;
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)
135 /* Discard the bytes, we're not actually writing to an image */
136 return 0;
140 bool
141 qcrypto_block_calculate_payload_offset(QCryptoBlockCreateOptions *create_opts,
142 const char *optprefix,
143 size_t *len,
144 Error **errp)
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;
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)
163 if (options->format != block->format) {
164 error_setg(errp,
165 "Cannot amend encryption format");
166 return -1;
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;
176 return block->driver->amend(block,
177 readfunc,
178 writefunc,
179 opaque,
180 options,
181 force,
182 errp);
185 QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block,
186 Error **errp)
188 QCryptoBlockInfo *info = g_new0(QCryptoBlockInfo, 1);
190 info->format = block->format;
192 if (block->driver->get_info &&
193 block->driver->get_info(block, info, errp) < 0) {
194 g_free(info);
195 return NULL;
198 return info;
202 int qcrypto_block_decrypt(QCryptoBlock *block,
203 uint64_t offset,
204 uint8_t *buf,
205 size_t len,
206 Error **errp)
208 return block->driver->decrypt(block, offset, buf, len, errp);
212 int qcrypto_block_encrypt(QCryptoBlock *block,
213 uint64_t offset,
214 uint8_t *buf,
215 size_t len,
216 Error **errp)
218 return block->driver->encrypt(block, offset, buf, len, errp);
222 QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block)
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:
230 assert(block->max_free_ciphers <= 1);
231 return block->free_ciphers ? block->free_ciphers[0] : NULL;
235 static QCryptoCipher *qcrypto_block_pop_cipher(QCryptoBlock *block,
236 Error **errp)
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];
246 /* Otherwise allocate a new cipher */
247 return qcrypto_cipher_new(block->alg, block->mode, block->key,
248 block->nkey, errp);
252 static void qcrypto_block_push_cipher(QCryptoBlock *block,
253 QCryptoCipher *cipher)
255 QEMU_LOCK_GUARD(&block->mutex);
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);
264 block->free_ciphers[block->n_free_ciphers] = cipher;
265 block->n_free_ciphers++;
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)
275 QCryptoCipher *cipher;
277 assert(!block->free_ciphers && !block->max_free_ciphers &&
278 !block->n_free_ciphers);
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;
287 * Create a new cipher to validate the parameters now. This reduces the
288 * chance of cipher creation failing at I/O time.
290 cipher = qcrypto_block_pop_cipher(block, errp);
291 if (!cipher) {
292 g_free(block->key);
293 block->key = NULL;
294 return -1;
297 qcrypto_block_push_cipher(block, cipher);
298 return 0;
302 void qcrypto_block_free_cipher(QCryptoBlock *block)
304 size_t i;
306 g_free(block->key);
307 block->key = NULL;
309 if (!block->free_ciphers) {
310 return;
313 /* All popped ciphers were eventually pushed back */
314 assert(block->n_free_ciphers == block->max_free_ciphers);
316 for (i = 0; i < block->max_free_ciphers; i++) {
317 qcrypto_cipher_free(block->free_ciphers[i]);
320 g_free(block->free_ciphers);
321 block->free_ciphers = NULL;
322 block->max_free_ciphers = block->n_free_ciphers = 0;
325 QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block)
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:
330 assert(block->max_free_ciphers <= 1);
331 return block->ivgen;
335 QCryptoHashAlgorithm qcrypto_block_get_kdf_hash(QCryptoBlock *block)
337 return block->kdfhash;
341 uint64_t qcrypto_block_get_payload_offset(QCryptoBlock *block)
343 return block->payload_offset;
347 uint64_t qcrypto_block_get_sector_size(QCryptoBlock *block)
349 return block->sector_size;
353 void qcrypto_block_free(QCryptoBlock *block)
355 if (!block) {
356 return;
359 block->driver->cleanup(block);
361 qcrypto_block_free_cipher(block);
362 qcrypto_ivgen_free(block->ivgen);
363 qemu_mutex_destroy(&block->mutex);
364 g_free(block);
368 typedef int (*QCryptoCipherEncDecFunc)(QCryptoCipher *cipher,
369 const void *in,
370 void *out,
371 size_t len,
372 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)
385 g_autofree uint8_t *iv = niv ? g_new0(uint8_t, niv) : NULL;
386 int ret = -1;
387 uint64_t startsector = offset / sectorsize;
389 assert(QEMU_IS_ALIGNED(offset, sectorsize));
390 assert(QEMU_IS_ALIGNED(len, sectorsize));
392 while (len > 0) {
393 size_t nbytes;
394 if (niv) {
395 if (ivgen_mutex) {
396 qemu_mutex_lock(ivgen_mutex);
398 ret = qcrypto_ivgen_calculate(ivgen, startsector, iv, niv, errp);
399 if (ivgen_mutex) {
400 qemu_mutex_unlock(ivgen_mutex);
403 if (ret < 0) {
404 return -1;
407 if (qcrypto_cipher_setiv(cipher,
408 iv, niv,
409 errp) < 0) {
410 return -1;
414 nbytes = len > sectorsize ? sectorsize : len;
415 if (func(cipher, buf, buf, nbytes, errp) < 0) {
416 return -1;
419 startsector++;
420 buf += nbytes;
421 len -= nbytes;
424 return 0;
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)
437 return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
438 offset, buf, len,
439 qcrypto_cipher_decrypt, 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)
452 return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
453 offset, buf, len,
454 qcrypto_cipher_encrypt, 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)
464 int ret;
465 QCryptoCipher *cipher = qcrypto_block_pop_cipher(block, errp);
466 if (!cipher) {
467 return -1;
470 ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
471 &block->mutex, sectorsize, offset, buf,
472 len, qcrypto_cipher_decrypt, errp);
474 qcrypto_block_push_cipher(block, cipher);
476 return ret;
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)
486 int ret;
487 QCryptoCipher *cipher = qcrypto_block_pop_cipher(block, errp);
488 if (!cipher) {
489 return -1;
492 ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
493 &block->mutex, sectorsize, offset, buf,
494 len, qcrypto_cipher_encrypt, errp);
496 qcrypto_block_push_cipher(block, cipher);
498 return ret;