• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revisiond8d5fefd8657d4f7b380b3a1533340434b5b9def (tree)
Time2018-12-14 03:45:18
AuthorPeter Maydell <peter.maydell@lina...>
CommiterPeter Maydell

Log Message

Merge crypto patches 2018/12/12

- Fix documentation about default LUKS algorithms
- Support for multi-threaded block crypto
-----BEGIN PGP SIGNATURE-----

iQIcBAABCAAGBQJcEO9QAAoJEL6G67QVEE/fkE0QAJXHxr3u9UtOE2IllTS/rxtD
nmiH8B4gdTJ2GFdYxoyoQP8nParRh0QEWjDtiOLId8Wnt9BUtbEtd89OOQsPkqw7
EDyfvIBkT0ZfWVHrhayzfItM1UCkQzbUSehdq+unZA7eXU9E/bTC12kme97M9cIh
VdQ2LE67A0hb5Bvv/o1gZcwtrK51h1PVVizhp8fKJh0owTV4VCZ5bbmXJSK0SdmW
dZKstJzBZOQnDrqSBEDMWtNMASuPNnYxfSgB/tgeOwDd3qjjNB6LBH0REaDzpEGR
WzwXzCinfr/KjdyN3OzEbkzuD7J/qySJNsarDe1aT0I+lm1KpjqLC6QRJ+cvXOyg
tX/2Y5XPevKsHPzvrhcyuiOO67OR5Xa/D0c2imWJOM2dmeDK7xMUyjHGKt4ijCBL
4M/Y/zbWDagMJf6DUUA3h3Q7NeWHA7mpQUOh1xjc3TJzjp091Fe3xCwm13dF+gu+
JZ8hF982Yy5SsvVWXBXYLUTtOUdX8tTaMtxDwvzxNram11APbDxiDhruBZ71jV8x
4C1ZmSPDuLGiVylB6T8dUuNoKRdHScIBs42bxUITbBvI8F0lvQBE0LkXqZJMXEY9
IcLAeGvcZTjvx6lsO39anT44UbIWOLWmLfebMQlRItEknb3HdJ0rDuTIHDaRSzKh
OimAIGc7B6BjuIcczBDP
=bOs1
-----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/berrange/tags/qcrypto-next-pull-request' into staging

Merge crypto patches 2018/12/12

- Fix documentation about default LUKS algorithms
- Support for multi-threaded block crypto

# gpg: Signature made Wed 12 Dec 2018 11:21:52 GMT
# gpg: using RSA key BE86EBB415104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>"
# gpg: aka "Daniel P. Berrange <berrange@redhat.com>"
# Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E 8E3F BE86 EBB4 1510 4FDF

* remotes/berrange/tags/qcrypto-next-pull-request:

crypto: support multiple threads accessing one QCryptoBlock
crypto/block: introduce qcrypto_block_*crypt_helper functions
crypto/block: rename qcrypto_block_*crypt_helper
crypto/block: refactor qcrypto_block_*crypt_helper functions
crypto/block-luks: fix memory leak in qcrypto_block_luks_create
crypto: Fix defaults in QCryptoBlockCreateOptionsLUKS

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Change Summary

Incremental Difference

--- a/block/crypto.c
+++ b/block/crypto.c
@@ -229,6 +229,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
229229 block_crypto_read_func,
230230 bs,
231231 cflags,
232+ 1,
232233 errp);
233234
234235 if (!crypto->block) {
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -213,7 +213,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
213213 cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
214214 }
215215 s->crypto = qcrypto_block_open(crypto_opts, "encrypt.",
216- NULL, NULL, cflags, errp);
216+ NULL, NULL, cflags, 1, errp);
217217 if (!s->crypto) {
218218 ret = -EINVAL;
219219 goto fail;
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -294,7 +294,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
294294 }
295295 s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
296296 qcow2_crypto_hdr_read_func,
297- bs, cflags, errp);
297+ bs, cflags, 1, errp);
298298 if (!s->crypto) {
299299 return -EINVAL;
300300 }
@@ -1445,7 +1445,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
14451445 cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
14461446 }
14471447 s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
1448- NULL, NULL, cflags, errp);
1448+ NULL, NULL, cflags, 1, errp);
14491449 if (!s->crypto) {
14501450 ret = -EINVAL;
14511451 goto fail;
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -504,14 +504,14 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
504504 * to reset the encryption cipher every time the master
505505 * key crosses a sector boundary.
506506 */
507- if (qcrypto_block_decrypt_helper(cipher,
508- niv,
509- ivgen,
510- QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
511- 0,
512- splitkey,
513- splitkeylen,
514- errp) < 0) {
507+ if (qcrypto_block_cipher_decrypt_helper(cipher,
508+ niv,
509+ ivgen,
510+ QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
511+ 0,
512+ splitkey,
513+ splitkeylen,
514+ errp) < 0) {
515515 goto cleanup;
516516 }
517517
@@ -636,6 +636,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
636636 QCryptoBlockReadFunc readfunc,
637637 void *opaque,
638638 unsigned int flags,
639+ size_t n_threads,
639640 Error **errp)
640641 {
641642 QCryptoBlockLUKS *luks;
@@ -836,11 +837,10 @@ qcrypto_block_luks_open(QCryptoBlock *block,
836837 goto fail;
837838 }
838839
839- block->cipher = qcrypto_cipher_new(cipheralg,
840- ciphermode,
841- masterkey, masterkeylen,
842- errp);
843- if (!block->cipher) {
840+ ret = qcrypto_block_init_cipher(block, cipheralg, ciphermode,
841+ masterkey, masterkeylen, n_threads,
842+ errp);
843+ if (ret < 0) {
844844 ret = -ENOTSUP;
845845 goto fail;
846846 }
@@ -863,7 +863,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
863863
864864 fail:
865865 g_free(masterkey);
866- qcrypto_cipher_free(block->cipher);
866+ qcrypto_block_free_cipher(block);
867867 qcrypto_ivgen_free(block->ivgen);
868868 g_free(luks);
869869 g_free(password);
@@ -1030,11 +1030,9 @@ qcrypto_block_luks_create(QCryptoBlock *block,
10301030
10311031
10321032 /* Setup the block device payload encryption objects */
1033- block->cipher = qcrypto_cipher_new(luks_opts.cipher_alg,
1034- luks_opts.cipher_mode,
1035- masterkey, luks->header.key_bytes,
1036- errp);
1037- if (!block->cipher) {
1033+ if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg,
1034+ luks_opts.cipher_mode, masterkey,
1035+ luks->header.key_bytes, 1, errp) < 0) {
10381036 goto error;
10391037 }
10401038
@@ -1219,12 +1217,12 @@ qcrypto_block_luks_create(QCryptoBlock *block,
12191217
12201218 /* Now we encrypt the split master key with the key generated
12211219 * from the user's password, before storing it */
1222- if (qcrypto_block_encrypt_helper(cipher, block->niv, ivgen,
1223- QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
1224- 0,
1225- splitkey,
1226- splitkeylen,
1227- errp) < 0) {
1220+ if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen,
1221+ QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
1222+ 0,
1223+ splitkey,
1224+ splitkeylen,
1225+ errp) < 0) {
12281226 goto error;
12291227 }
12301228
@@ -1341,6 +1339,9 @@ qcrypto_block_luks_create(QCryptoBlock *block,
13411339 qcrypto_ivgen_free(ivgen);
13421340 qcrypto_cipher_free(cipher);
13431341
1342+ qcrypto_block_free_cipher(block);
1343+ qcrypto_ivgen_free(block->ivgen);
1344+
13441345 g_free(luks);
13451346 return -1;
13461347 }
@@ -1406,8 +1407,7 @@ qcrypto_block_luks_decrypt(QCryptoBlock *block,
14061407 {
14071408 assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
14081409 assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
1409- return qcrypto_block_decrypt_helper(block->cipher,
1410- block->niv, block->ivgen,
1410+ return qcrypto_block_decrypt_helper(block,
14111411 QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
14121412 offset, buf, len, errp);
14131413 }
@@ -1422,8 +1422,7 @@ qcrypto_block_luks_encrypt(QCryptoBlock *block,
14221422 {
14231423 assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
14241424 assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
1425- return qcrypto_block_encrypt_helper(block->cipher,
1426- block->niv, block->ivgen,
1425+ return qcrypto_block_encrypt_helper(block,
14271426 QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
14281427 offset, buf, len, errp);
14291428 }
--- a/crypto/block-qcow.c
+++ b/crypto/block-qcow.c
@@ -44,6 +44,7 @@ qcrypto_block_qcow_has_format(const uint8_t *buf G_GNUC_UNUSED,
4444 static int
4545 qcrypto_block_qcow_init(QCryptoBlock *block,
4646 const char *keysecret,
47+ size_t n_threads,
4748 Error **errp)
4849 {
4950 char *password;
@@ -71,11 +72,11 @@ qcrypto_block_qcow_init(QCryptoBlock *block,
7172 goto fail;
7273 }
7374
74- block->cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_128,
75- QCRYPTO_CIPHER_MODE_CBC,
76- keybuf, G_N_ELEMENTS(keybuf),
77- errp);
78- if (!block->cipher) {
75+ ret = qcrypto_block_init_cipher(block, QCRYPTO_CIPHER_ALG_AES_128,
76+ QCRYPTO_CIPHER_MODE_CBC,
77+ keybuf, G_N_ELEMENTS(keybuf),
78+ n_threads, errp);
79+ if (ret < 0) {
7980 ret = -ENOTSUP;
8081 goto fail;
8182 }
@@ -86,7 +87,7 @@ qcrypto_block_qcow_init(QCryptoBlock *block,
8687 return 0;
8788
8889 fail:
89- qcrypto_cipher_free(block->cipher);
90+ qcrypto_block_free_cipher(block);
9091 qcrypto_ivgen_free(block->ivgen);
9192 return ret;
9293 }
@@ -99,6 +100,7 @@ qcrypto_block_qcow_open(QCryptoBlock *block,
99100 QCryptoBlockReadFunc readfunc G_GNUC_UNUSED,
100101 void *opaque G_GNUC_UNUSED,
101102 unsigned int flags,
103+ size_t n_threads,
102104 Error **errp)
103105 {
104106 if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
@@ -112,8 +114,8 @@ qcrypto_block_qcow_open(QCryptoBlock *block,
112114 optprefix ? optprefix : "");
113115 return -1;
114116 }
115- return qcrypto_block_qcow_init(block,
116- options->u.qcow.key_secret, errp);
117+ return qcrypto_block_qcow_init(block, options->u.qcow.key_secret,
118+ n_threads, errp);
117119 }
118120 }
119121
@@ -133,7 +135,7 @@ qcrypto_block_qcow_create(QCryptoBlock *block,
133135 return -1;
134136 }
135137 /* QCow2 has no special header, since everything is hardwired */
136- return qcrypto_block_qcow_init(block, options->u.qcow.key_secret, errp);
138+ return qcrypto_block_qcow_init(block, options->u.qcow.key_secret, 1, errp);
137139 }
138140
139141
@@ -152,8 +154,7 @@ qcrypto_block_qcow_decrypt(QCryptoBlock *block,
152154 {
153155 assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE));
154156 assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE));
155- return qcrypto_block_decrypt_helper(block->cipher,
156- block->niv, block->ivgen,
157+ return qcrypto_block_decrypt_helper(block,
157158 QCRYPTO_BLOCK_QCOW_SECTOR_SIZE,
158159 offset, buf, len, errp);
159160 }
@@ -168,8 +169,7 @@ qcrypto_block_qcow_encrypt(QCryptoBlock *block,
168169 {
169170 assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE));
170171 assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE));
171- return qcrypto_block_encrypt_helper(block->cipher,
172- block->niv, block->ivgen,
172+ return qcrypto_block_encrypt_helper(block,
173173 QCRYPTO_BLOCK_QCOW_SECTOR_SIZE,
174174 offset, buf, len, errp);
175175 }
--- a/crypto/block.c
+++ b/crypto/block.c
@@ -52,6 +52,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
5252 QCryptoBlockReadFunc readfunc,
5353 void *opaque,
5454 unsigned int flags,
55+ size_t n_threads,
5556 Error **errp)
5657 {
5758 QCryptoBlock *block = g_new0(QCryptoBlock, 1);
@@ -69,11 +70,14 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
6970 block->driver = qcrypto_block_drivers[options->format];
7071
7172 if (block->driver->open(block, options, optprefix,
72- readfunc, opaque, flags, errp) < 0) {
73+ readfunc, opaque, flags, n_threads, errp) < 0)
74+ {
7375 g_free(block);
7476 return NULL;
7577 }
7678
79+ qemu_mutex_init(&block->mutex);
80+
7781 return block;
7882 }
7983
@@ -105,6 +109,8 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
105109 return NULL;
106110 }
107111
112+ qemu_mutex_init(&block->mutex);
113+
108114 return block;
109115 }
110116
@@ -148,12 +154,97 @@ int qcrypto_block_encrypt(QCryptoBlock *block,
148154
149155 QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block)
150156 {
151- return block->cipher;
157+ /* Ciphers should be accessed through pop/push method to be thread-safe.
158+ * Better, they should not be accessed externally at all (note, that
159+ * pop/push are static functions)
160+ * This function is used only in test with one thread (it's safe to skip
161+ * pop/push interface), so it's enough to assert it here:
162+ */
163+ assert(block->n_ciphers <= 1);
164+ return block->ciphers ? block->ciphers[0] : NULL;
165+}
166+
167+
168+static QCryptoCipher *qcrypto_block_pop_cipher(QCryptoBlock *block)
169+{
170+ QCryptoCipher *cipher;
171+
172+ qemu_mutex_lock(&block->mutex);
173+
174+ assert(block->n_free_ciphers > 0);
175+ block->n_free_ciphers--;
176+ cipher = block->ciphers[block->n_free_ciphers];
177+
178+ qemu_mutex_unlock(&block->mutex);
179+
180+ return cipher;
181+}
182+
183+
184+static void qcrypto_block_push_cipher(QCryptoBlock *block,
185+ QCryptoCipher *cipher)
186+{
187+ qemu_mutex_lock(&block->mutex);
188+
189+ assert(block->n_free_ciphers < block->n_ciphers);
190+ block->ciphers[block->n_free_ciphers] = cipher;
191+ block->n_free_ciphers++;
192+
193+ qemu_mutex_unlock(&block->mutex);
152194 }
153195
154196
197+int qcrypto_block_init_cipher(QCryptoBlock *block,
198+ QCryptoCipherAlgorithm alg,
199+ QCryptoCipherMode mode,
200+ const uint8_t *key, size_t nkey,
201+ size_t n_threads, Error **errp)
202+{
203+ size_t i;
204+
205+ assert(!block->ciphers && !block->n_ciphers && !block->n_free_ciphers);
206+
207+ block->ciphers = g_new0(QCryptoCipher *, n_threads);
208+
209+ for (i = 0; i < n_threads; i++) {
210+ block->ciphers[i] = qcrypto_cipher_new(alg, mode, key, nkey, errp);
211+ if (!block->ciphers[i]) {
212+ qcrypto_block_free_cipher(block);
213+ return -1;
214+ }
215+ block->n_ciphers++;
216+ block->n_free_ciphers++;
217+ }
218+
219+ return 0;
220+}
221+
222+
223+void qcrypto_block_free_cipher(QCryptoBlock *block)
224+{
225+ size_t i;
226+
227+ if (!block->ciphers) {
228+ return;
229+ }
230+
231+ assert(block->n_ciphers == block->n_free_ciphers);
232+
233+ for (i = 0; i < block->n_ciphers; i++) {
234+ qcrypto_cipher_free(block->ciphers[i]);
235+ }
236+
237+ g_free(block->ciphers);
238+ block->ciphers = NULL;
239+ block->n_ciphers = block->n_free_ciphers = 0;
240+}
241+
155242 QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block)
156243 {
244+ /* ivgen should be accessed under mutex. However, this function is used only
245+ * in test with one thread, so it's enough to assert it here:
246+ */
247+ assert(block->n_ciphers <= 1);
157248 return block->ivgen;
158249 }
159250
@@ -184,20 +275,29 @@ void qcrypto_block_free(QCryptoBlock *block)
184275
185276 block->driver->cleanup(block);
186277
187- qcrypto_cipher_free(block->cipher);
278+ qcrypto_block_free_cipher(block);
188279 qcrypto_ivgen_free(block->ivgen);
280+ qemu_mutex_destroy(&block->mutex);
189281 g_free(block);
190282 }
191283
192284
193-int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
194- size_t niv,
195- QCryptoIVGen *ivgen,
196- int sectorsize,
197- uint64_t offset,
198- uint8_t *buf,
199- size_t len,
200- Error **errp)
285+typedef int (*QCryptoCipherEncDecFunc)(QCryptoCipher *cipher,
286+ const void *in,
287+ void *out,
288+ size_t len,
289+ Error **errp);
290+
291+static int do_qcrypto_block_cipher_encdec(QCryptoCipher *cipher,
292+ size_t niv,
293+ QCryptoIVGen *ivgen,
294+ QemuMutex *ivgen_mutex,
295+ int sectorsize,
296+ uint64_t offset,
297+ uint8_t *buf,
298+ size_t len,
299+ QCryptoCipherEncDecFunc func,
300+ Error **errp)
201301 {
202302 uint8_t *iv;
203303 int ret = -1;
@@ -211,10 +311,15 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
211311 while (len > 0) {
212312 size_t nbytes;
213313 if (niv) {
214- if (qcrypto_ivgen_calculate(ivgen,
215- startsector,
216- iv, niv,
217- errp) < 0) {
314+ if (ivgen_mutex) {
315+ qemu_mutex_lock(ivgen_mutex);
316+ }
317+ ret = qcrypto_ivgen_calculate(ivgen, startsector, iv, niv, errp);
318+ if (ivgen_mutex) {
319+ qemu_mutex_unlock(ivgen_mutex);
320+ }
321+
322+ if (ret < 0) {
218323 goto cleanup;
219324 }
220325
@@ -226,8 +331,7 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
226331 }
227332
228333 nbytes = len > sectorsize ? sectorsize : len;
229- if (qcrypto_cipher_decrypt(cipher, buf, buf,
230- nbytes, errp) < 0) {
334+ if (func(cipher, buf, buf, nbytes, errp) < 0) {
231335 goto cleanup;
232336 }
233337
@@ -243,54 +347,69 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
243347 }
244348
245349
246-int qcrypto_block_encrypt_helper(QCryptoCipher *cipher,
247- size_t niv,
248- QCryptoIVGen *ivgen,
350+int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher,
351+ size_t niv,
352+ QCryptoIVGen *ivgen,
353+ int sectorsize,
354+ uint64_t offset,
355+ uint8_t *buf,
356+ size_t len,
357+ Error **errp)
358+{
359+ return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
360+ offset, buf, len,
361+ qcrypto_cipher_decrypt, errp);
362+}
363+
364+
365+int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher,
366+ size_t niv,
367+ QCryptoIVGen *ivgen,
368+ int sectorsize,
369+ uint64_t offset,
370+ uint8_t *buf,
371+ size_t len,
372+ Error **errp)
373+{
374+ return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
375+ offset, buf, len,
376+ qcrypto_cipher_encrypt, errp);
377+}
378+
379+int qcrypto_block_decrypt_helper(QCryptoBlock *block,
249380 int sectorsize,
250381 uint64_t offset,
251382 uint8_t *buf,
252383 size_t len,
253384 Error **errp)
254385 {
255- uint8_t *iv;
256- int ret = -1;
257- uint64_t startsector = offset / sectorsize;
386+ int ret;
387+ QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
258388
259- assert(QEMU_IS_ALIGNED(offset, sectorsize));
260- assert(QEMU_IS_ALIGNED(len, sectorsize));
389+ ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
390+ &block->mutex, sectorsize, offset, buf,
391+ len, qcrypto_cipher_decrypt, errp);
261392
262- iv = niv ? g_new0(uint8_t, niv) : NULL;
393+ qcrypto_block_push_cipher(block, cipher);
263394
264- while (len > 0) {
265- size_t nbytes;
266- if (niv) {
267- if (qcrypto_ivgen_calculate(ivgen,
268- startsector,
269- iv, niv,
270- errp) < 0) {
271- goto cleanup;
272- }
395+ return ret;
396+}
273397
274- if (qcrypto_cipher_setiv(cipher,
275- iv, niv,
276- errp) < 0) {
277- goto cleanup;
278- }
279- }
398+int qcrypto_block_encrypt_helper(QCryptoBlock *block,
399+ int sectorsize,
400+ uint64_t offset,
401+ uint8_t *buf,
402+ size_t len,
403+ Error **errp)
404+{
405+ int ret;
406+ QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
280407
281- nbytes = len > sectorsize ? sectorsize : len;
282- if (qcrypto_cipher_encrypt(cipher, buf, buf,
283- nbytes, errp) < 0) {
284- goto cleanup;
285- }
408+ ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
409+ &block->mutex, sectorsize, offset, buf,
410+ len, qcrypto_cipher_encrypt, errp);
286411
287- startsector++;
288- buf += nbytes;
289- len -= nbytes;
290- }
412+ qcrypto_block_push_cipher(block, cipher);
291413
292- ret = 0;
293- cleanup:
294- g_free(iv);
295414 return ret;
296415 }
--- a/crypto/blockpriv.h
+++ b/crypto/blockpriv.h
@@ -22,6 +22,7 @@
2222 #define QCRYPTO_BLOCKPRIV_H
2323
2424 #include "crypto/block.h"
25+#include "qemu/thread.h"
2526
2627 typedef struct QCryptoBlockDriver QCryptoBlockDriver;
2728
@@ -31,8 +32,12 @@ struct QCryptoBlock {
3132 const QCryptoBlockDriver *driver;
3233 void *opaque;
3334
34- QCryptoCipher *cipher;
35+ QCryptoCipher **ciphers;
36+ size_t n_ciphers;
37+ size_t n_free_ciphers;
3538 QCryptoIVGen *ivgen;
39+ QemuMutex mutex;
40+
3641 QCryptoHashAlgorithm kdfhash;
3742 size_t niv;
3843 uint64_t payload_offset; /* In bytes */
@@ -46,6 +51,7 @@ struct QCryptoBlockDriver {
4651 QCryptoBlockReadFunc readfunc,
4752 void *opaque,
4853 unsigned int flags,
54+ size_t n_threads,
4955 Error **errp);
5056
5157 int (*create)(QCryptoBlock *block,
@@ -78,22 +84,44 @@ struct QCryptoBlockDriver {
7884 };
7985
8086
81-int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
82- size_t niv,
83- QCryptoIVGen *ivgen,
87+int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher,
88+ size_t niv,
89+ QCryptoIVGen *ivgen,
90+ int sectorsize,
91+ uint64_t offset,
92+ uint8_t *buf,
93+ size_t len,
94+ Error **errp);
95+
96+int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher,
97+ size_t niv,
98+ QCryptoIVGen *ivgen,
99+ int sectorsize,
100+ uint64_t offset,
101+ uint8_t *buf,
102+ size_t len,
103+ Error **errp);
104+
105+int qcrypto_block_decrypt_helper(QCryptoBlock *block,
84106 int sectorsize,
85107 uint64_t offset,
86108 uint8_t *buf,
87109 size_t len,
88110 Error **errp);
89111
90-int qcrypto_block_encrypt_helper(QCryptoCipher *cipher,
91- size_t niv,
92- QCryptoIVGen *ivgen,
112+int qcrypto_block_encrypt_helper(QCryptoBlock *block,
93113 int sectorsize,
94114 uint64_t offset,
95115 uint8_t *buf,
96116 size_t len,
97117 Error **errp);
98118
119+int qcrypto_block_init_cipher(QCryptoBlock *block,
120+ QCryptoCipherAlgorithm alg,
121+ QCryptoCipherMode mode,
122+ const uint8_t *key, size_t nkey,
123+ size_t n_threads, Error **errp);
124+
125+void qcrypto_block_free_cipher(QCryptoBlock *block);
126+
99127 #endif /* QCRYPTO_BLOCKPRIV_H */
--- a/include/crypto/block.h
+++ b/include/crypto/block.h
@@ -75,6 +75,7 @@ typedef enum {
7575 * @readfunc: callback for reading data from the volume
7676 * @opaque: data to pass to @readfunc
7777 * @flags: bitmask of QCryptoBlockOpenFlags values
78+ * @n_threads: allow concurrent I/O from up to @n_threads threads
7879 * @errp: pointer to a NULL-initialized error object
7980 *
8081 * Create a new block encryption object for an existing
@@ -107,6 +108,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
107108 QCryptoBlockReadFunc readfunc,
108109 void *opaque,
109110 unsigned int flags,
111+ size_t n_threads,
110112 Error **errp);
111113
112114 /**
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -181,11 +181,11 @@
181181 # The options that apply to LUKS encryption format initialization
182182 #
183183 # @cipher-alg: the cipher algorithm for data encryption
184-# Currently defaults to 'aes'.
184+# Currently defaults to 'aes-256'.
185185 # @cipher-mode: the cipher mode for data encryption
186-# Currently defaults to 'cbc'
186+# Currently defaults to 'xts'
187187 # @ivgen-alg: the initialization vector generator
188-# Currently defaults to 'essiv'
188+# Currently defaults to 'plain64'
189189 # @ivgen-hash-alg: the initialization vector generator hash
190190 # Currently defaults to 'sha256'
191191 # @hash-alg: the master key hash algorithm
--- a/tests/test-crypto-block.c
+++ b/tests/test-crypto-block.c
@@ -305,6 +305,7 @@ static void test_block(gconstpointer opaque)
305305 test_block_read_func,
306306 &header,
307307 0,
308+ 1,
308309 NULL);
309310 g_assert(blk == NULL);
310311
@@ -313,6 +314,7 @@ static void test_block(gconstpointer opaque)
313314 test_block_read_func,
314315 &header,
315316 QCRYPTO_BLOCK_OPEN_NO_IO,
317+ 1,
316318 &error_abort);
317319
318320 g_assert(qcrypto_block_get_cipher(blk) == NULL);
@@ -327,6 +329,7 @@ static void test_block(gconstpointer opaque)
327329 test_block_read_func,
328330 &header,
329331 0,
332+ 1,
330333 &error_abort);
331334 g_assert(blk);
332335