crypto threads
Subsystems (2)
v3 cover crypto threads
Hi all.
v3:
01: add r-b by Daniel and Alberto
02: Alberto r-b
encrypt->encdec for generic
03: qcrypto_cipher_*crypt_helper->
qcrypto_block_cipher_*crypt_helper
04: rebased on previous renamings
Daniel r-b
05: use size_t
improve comment about n_threads
don't use ret in qcrypto_block_luks_create
do qemu_mutex_init at the end of open/create
do qemu_mutex_destroy in free
fix comment for qcrypto_block_get_cipher
v2:
05: fix compilation of test-crypto-block (I am ashamed:(
and change QCryptoBlock interface to be a bit more safe.
These series are preliminary step before moving encryption code in qcow2 to the threads. The first attempt of doing it is on list ([PATCH 00/11] qcow2: encryption threads :
https://lists.gnu.org/archive/html/qemu-block/2018-11/msg00729.html)
But it's approach with multiplying the whole QCryptoBlock per thread was rejected. So, here is a solution to maintain multitasking inside QCryptoBlock.
Vladimir Sementsov-Ogievskiy (5):
crypto/block-luks: fix memory leak in qcrypto_block_luks_create crypto/block: refactor qcrypto_block_*crypt_helper functions crypto/block: rename qcrypto_block_*crypt_helper crypto/block: introduce qcrypto_block_*crypt_helper functions
crypto: support multiple threads accessing one QCryptoBlock
crypto/blockpriv.h | 42 +++++-- include/crypto/block.h | 2 + block/crypto.c | 1 + block/qcow.c | 2 +- block/qcow2.c | 4 +- crypto/block-luks.c | 57 +++++----- crypto/block-qcow.c | 26 ++--- crypto/block.c | 225 +++++++++++++++++++++++++++++--------- tests/test-crypto-block.c | 3 + 9 files changed, 257 insertions(+), 105 deletions(-)
Signature · 1 line
2.18.0
PATCH v3 1/5 crypto/block-luks: fix memory leak in qcrypto_block_luks_create
Free block->cipher and block->ivgen on error path.
--- crypto/block-luks.c | 3 +++ 1 file changed, 3 insertions(+)
crypto/block-luks.c +3 -0
@@ -1341,6 +1341,9 @@ qcrypto_block_luks_create(QCryptoBlock *block,qcrypto_ivgen_free (ivgen);qcrypto_cipher_free (cipher); +qcrypto_cipher_free (block->cipher); +qcrypto_ivgen_free (block->ivgen); +g_free (luks);return -1 ; }
Signature · 1 line
2.18.0
PATCH v3 2/5 crypto/block: refactor qcrypto_block_*crypt_helper functions
In reply to Vladimir Sementsov-Ogievskiyqcrypto_block_encrypt_helper and qcrypto_block_decrypt_helper are almost identical, let's reduce code duplication and simplify further improvements.
--- crypto/block.c | 81 +++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 50 deletions(-)
crypto/block.c +31 -50
@@ -190,14 +190,21 @@ void qcrypto_block_free(QCryptoBlock *block) } -int qcrypto_block_decrypt_helper (QCryptoCipher *cipher, -size_t niv, -QCryptoIVGen *ivgen, -int sectorsize, -uint64_t offset, -uint8_t *buf, -size_t len, -Error **errp) +typedef int (*QCryptoCipherEncDecFunc )(QCryptoCipher *cipher, +const void *in, +void *out, +size_t len, +Error **errp); + +static int do_qcrypto_block_encdec (QCryptoCipher *cipher, +size_t niv, +QCryptoIVGen *ivgen, +int sectorsize, +uint64_t offset, +uint8_t *buf, +size_t len, +QCryptoCipherEncDecFunc func, +Error **errp) {uint8_t *iv;int ret =-1 ;
@@ -226,8 +233,7 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, } nbytes = len > sectorsize ? sectorsize : len; -if (qcrypto_cipher_decrypt (cipher, buf, buf, - nbytes, errp) <0 ) { +if (func (cipher, buf, buf, nbytes, errp) <0 ) { goto cleanup; }
@@ -243,7 +249,7 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, } -int qcrypto_block_encrypt_helper(QCryptoCipher *cipher, +int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, size_t niv, QCryptoIVGen *ivgen, int sectorsize,
@@ -252,45 +258,20 @@ int qcrypto_block_encrypt_helper(QCryptoCipher *cipher,size_t len, Error **errp) { - uint8_t *iv; -int ret =-1 ; -uint64_t startsector = offset / sectorsize; - -assert (QEMU_IS_ALIGNED (offset, sectorsize)); -assert (QEMU_IS_ALIGNED (len, sectorsize)); - - iv = niv ?g_new0 (uint8_t, niv) :NULL ; - -while (len >0 ) { -size_t nbytes; -if (niv) { -if (qcrypto_ivgen_calculate (ivgen, - startsector, - iv, niv, - errp) <0 ) { - goto cleanup; - } + return do_qcrypto_block_encdec(cipher, niv, ivgen, sectorsize, offset, +buf ,len ,qcrypto_cipher_decrypt ,errp ); +} -if (qcrypto_cipher_setiv (cipher, - iv, niv, - errp) <0 ) { - goto cleanup; - } - } - nbytes = len > sectorsize ? sectorsize : len; -if (qcrypto_cipher_encrypt (cipher, buf, buf, - nbytes, errp) <0 ) { - goto cleanup; - } - - startsector++; - buf += nbytes; - len -= nbytes; - } - - ret =0 ; - cleanup: -g_free (iv); -return ret; +int qcrypto_block_encrypt_helper (QCryptoCipher *cipher, +size_t niv, +QCryptoIVGen *ivgen, +int sectorsize, +uint64_t offset, +uint8_t *buf, +size_t len, +Error **errp) +{ +return do_qcrypto_block_encdec (cipher, niv, ivgen, sectorsize, offset, + buf, len, qcrypto_cipher_encrypt, errp); }
Signature · 1 line
2.18.0
PATCH v3 3/5 crypto/block: rename qcrypto_block_*crypt_helper
In reply to Vladimir Sementsov-OgievskiyRename qcrypto_block_*crypt_helper to qcrypto_cipher_*crypt_helper, as it's not about QCryptoBlock. This is needed to introduce qcrypto_block_*crypt_helper in the next commit, which will have QCryptoBlock pointer and than will be able to use additional fields of it, which in turn will be used to implement thread-safe QCryptoBlock operations.
--- crypto/blockpriv.h | 34 +++++++++++----------- crypto/block-luks.c | 44 ++++++++++++++-------------- crypto/block-qcow.c | 16 +++++------ crypto/block.c | 70 +++++++++++++++++++++++---------------------- 4 files changed, 83 insertions(+), 81 deletions(-)
crypto/blockpriv.h +17 -17
@@ -78,22 +78,22 @@ struct QCryptoBlockDriver { }; -int qcrypto_block_decrypt_helper (QCryptoCipher *cipher, -size_t niv, -QCryptoIVGen *ivgen, -int sectorsize, -uint64_t offset, -uint8_t *buf, -size_t len, -Error **errp); - -int qcrypto_block_encrypt_helper (QCryptoCipher *cipher, -size_t niv, -QCryptoIVGen *ivgen, -int sectorsize, -uint64_t offset, -uint8_t *buf, -size_t len, -Error **errp); +int 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); + +int 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);#endif /* QCRYPTO_BLOCKPRIV_H */
crypto/block-luks.c +22 -22
68 lines not on this page · raw message
crypto/block-qcow.c +8 -8
@@ -152,10 +152,10 @@ qcrypto_block_qcow_decrypt(QCryptoBlock *block, {assert (QEMU_IS_ALIGNED (offset,QCRYPTO_BLOCK_QCOW_SECTOR_SIZE ));assert (QEMU_IS_ALIGNED (len,QCRYPTO_BLOCK_QCOW_SECTOR_SIZE )); -return qcrypto_block_decrypt_helper (block->cipher, - block->niv, block->ivgen, -QCRYPTO_BLOCK_QCOW_SECTOR_SIZE , - offset, buf, len, errp); +return qcrypto_block_cipher_decrypt_helper (block->cipher, + block->niv, block->ivgen, +QCRYPTO_BLOCK_QCOW_SECTOR_SIZE , + offset, buf, len, errp); }
@@ -168,10 +168,10 @@ qcrypto_block_qcow_encrypt(QCryptoBlock *block, {assert (QEMU_IS_ALIGNED (offset,QCRYPTO_BLOCK_QCOW_SECTOR_SIZE ));assert (QEMU_IS_ALIGNED (len,QCRYPTO_BLOCK_QCOW_SECTOR_SIZE )); -return qcrypto_block_encrypt_helper (block->cipher, - block->niv, block->ivgen, -QCRYPTO_BLOCK_QCOW_SECTOR_SIZE , - offset, buf, len, errp); +return qcrypto_block_cipher_encrypt_helper (block->cipher, + block->niv, block->ivgen, +QCRYPTO_BLOCK_QCOW_SECTOR_SIZE , + offset, buf, len, errp); }
crypto/block.c +36 -34
85 lines not on this page · raw message
Signature · 1 line
2.18.0
Re: [Qemu-devel] [PATCH v3 3/5] crypto/block: rename qcrypto_block_*crypt_helper
Quoted 1 line · Vladimir Sementsov-Ogievskiy
Rename qcrypto_block_*crypt_helper to qcrypto_cipher_*crypt_helper, as
You forgot to update the new function names in the commit message.
crypto/blockpriv.h struct QCryptoBlockDriver { · line 90
Quoted 4 lines
crypto/blockpriv.h +2
-2-int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, -int qcrypto_block_encrypt_helper(QCryptoCipher *cipher, +int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher, +int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher,
Berto
Re: [Qemu-devel] [PATCH v3 3/5] crypto/block: rename qcrypto_block_*crypt_helper
Quoted 9 lines · Alberto Garcia
Quoted 1 line · Vladimir Sementsov-Ogievskiy
Rename qcrypto_block_*crypt_helper to qcrypto_cipher_*crypt_helper, as
You forgot to update the new function names in the commit message.
crypto/blockpriv.h struct QCryptoBlockDriver { · line 90
Quoted 4 lines
crypto/blockpriv.h +2
-2-int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, -int qcrypto_block_encrypt_helper(QCryptoCipher *cipher, +int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher, +int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher,
I'll take care of that when queuing these patches
Regards,
Daniel
Signature · 3 lines
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
Alberto Garcia
Reviewed-byRe: [Qemu-devel] [PATCH v3 3/5] crypto/block: rename qcrypto_block_*crypt_helper
Quoted 4 lines · Daniel P. Berrangé
Quoted 3 lines · Alberto Garcia
Quoted 1 line · Vladimir Sementsov-Ogievskiy
Rename qcrypto_block_*crypt_helper to qcrypto_cipher_*crypt_helper, as
Quoted 8 lines
Quoted 6 lines
You forgot to update the new function names in the commit message.
crypto/blockpriv.h struct QCryptoBlockDriver { · line 90
Quoted 4 lines
crypto/blockpriv.h +2
-2-int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, -int qcrypto_block_encrypt_helper(QCryptoCipher *cipher, +int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher, +int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher,I'll take care of that when queuing these patches
Ok then
Berto
PATCH v3 4/5 crypto/block: introduce qcrypto_block_*crypt_helper functions
In reply to Vladimir Sementsov-OgievskiyIntroduce QCryptoBlock-based functions and use them where possible. This is needed to implement thread-safe encrypt/decrypt operations.
--- crypto/blockpriv.h | 14 ++++++++++++++ crypto/block-luks.c | 14 ++++++-------- crypto/block-qcow.c | 14 ++++++-------- crypto/block.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 16 deletions(-)
crypto/blockpriv.h +14 -0
@@ -96,4 +96,18 @@ int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher,size_t len, Error **errp); +int qcrypto_block_decrypt_helper (QCryptoBlock *block, +int sectorsize, +uint64_t offset, +uint8_t *buf, +size_t len, +Error **errp); + +int qcrypto_block_encrypt_helper (QCryptoBlock *block, +int sectorsize, +uint64_t offset, +uint8_t *buf, +size_t len, +Error **errp); +#endif /* QCRYPTO_BLOCKPRIV_H */
crypto/block-luks.c +6 -8
@@ -1409,10 +1409,9 @@ qcrypto_block_luks_decrypt(QCryptoBlock *block, {assert (QEMU_IS_ALIGNED (offset,QCRYPTO_BLOCK_LUKS_SECTOR_SIZE ));assert (QEMU_IS_ALIGNED (len,QCRYPTO_BLOCK_LUKS_SECTOR_SIZE )); -return qcrypto_block_cipher_decrypt_helper (block->cipher, - block->niv, block->ivgen, -QCRYPTO_BLOCK_LUKS_SECTOR_SIZE , - offset, buf, len, errp); +return qcrypto_block_decrypt_helper (block, +QCRYPTO_BLOCK_LUKS_SECTOR_SIZE , + offset, buf, len, errp); }
@@ -1425,10 +1424,9 @@ qcrypto_block_luks_encrypt(QCryptoBlock *block, {assert (QEMU_IS_ALIGNED (offset,QCRYPTO_BLOCK_LUKS_SECTOR_SIZE ));assert (QEMU_IS_ALIGNED (len,QCRYPTO_BLOCK_LUKS_SECTOR_SIZE )); -return qcrypto_block_cipher_encrypt_helper (block->cipher, - block->niv, block->ivgen, -QCRYPTO_BLOCK_LUKS_SECTOR_SIZE , - offset, buf, len, errp); +return qcrypto_block_encrypt_helper (block, +QCRYPTO_BLOCK_LUKS_SECTOR_SIZE , + offset, buf, len, errp); }
crypto/block-qcow.c +6 -8
@@ -152,10 +152,9 @@ qcrypto_block_qcow_decrypt(QCryptoBlock *block, {assert (QEMU_IS_ALIGNED (offset,QCRYPTO_BLOCK_QCOW_SECTOR_SIZE ));assert (QEMU_IS_ALIGNED (len,QCRYPTO_BLOCK_QCOW_SECTOR_SIZE )); -return qcrypto_block_cipher_decrypt_helper (block->cipher, - block->niv, block->ivgen, -QCRYPTO_BLOCK_QCOW_SECTOR_SIZE , - offset, buf, len, errp); +return qcrypto_block_decrypt_helper (block, +QCRYPTO_BLOCK_QCOW_SECTOR_SIZE , + offset, buf, len, errp); }
@@ -168,10 +167,9 @@ qcrypto_block_qcow_encrypt(QCryptoBlock *block, {assert (QEMU_IS_ALIGNED (offset,QCRYPTO_BLOCK_QCOW_SECTOR_SIZE ));assert (QEMU_IS_ALIGNED (len,QCRYPTO_BLOCK_QCOW_SECTOR_SIZE )); -return qcrypto_block_cipher_encrypt_helper (block->cipher, - block->niv, block->ivgen, -QCRYPTO_BLOCK_QCOW_SECTOR_SIZE , - offset, buf, len, errp); +return qcrypto_block_encrypt_helper (block, +QCRYPTO_BLOCK_QCOW_SECTOR_SIZE , + offset, buf, len, errp); }
crypto/block.c +28 -0
@@ -277,3 +277,31 @@ int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher, offset, buf, len, qcrypto_cipher_encrypt, errp); } + + +int qcrypto_block_decrypt_helper (QCryptoBlock *block, +int sectorsize, +uint64_t offset, +uint8_t *buf, +size_t len, +Error **errp) +{ +return do_qcrypto_block_cipher_encdec (block->cipher, block->niv, + block->ivgen, + sectorsize, offset, buf, len, + qcrypto_cipher_decrypt, errp); +} + + +int qcrypto_block_encrypt_helper (QCryptoBlock *block, +int sectorsize, +uint64_t offset, +uint8_t *buf, +size_t len, +Error **errp) +{ +return do_qcrypto_block_cipher_encdec (block->cipher, block->niv, + block->ivgen, + sectorsize, offset, buf, len, + qcrypto_cipher_encrypt, errp); +}
Signature · 1 line
2.18.0
Re: [Qemu-devel] [PATCH v3 4/5] crypto/block: introduce qcrypto_block_*crypt_helper functions
Quoted 5 lines · Vladimir Sementsov-Ogievskiy
Introduce QCryptoBlock-based functions and use them where possible. This is needed to implement thread-safe encrypt/decrypt operations.
Signed-off-by Vladimir Sementsov-Ogievskiy <[email protected]>Reviewed-by Daniel P. Berrangé <[email protected]>
Berto
PATCH v3 5/5 crypto: support multiple threads accessing one QCryptoBlock
In reply to Vladimir Sementsov-OgievskiyThe two thing that should be handled are cipher and ivgen. For ivgen the solution is just mutex, as iv calculations should not be long in comparison with encryption/decryption. And for cipher let's just keep per-thread ciphers.
--- crypto/blockpriv.h | 16 ++++- include/crypto/block.h | 2 + block/crypto.c | 1 + block/qcow.c | 2 +- block/qcow2.c | 4 +- crypto/block-luks.c | 22 +++--- crypto/block-qcow.c | 20 +++--- crypto/block.c | 146 +++++++++++++++++++++++++++++++++----- tests/test-crypto-block.c | 3 + 9 files changed, 172 insertions(+), 44 deletions(-)
crypto/blockpriv.h +15 -1
@@ -22,6 +22,7 @@#define QCRYPTO_BLOCKPRIV_H #include "crypto/block.h" +#include "qemu/thread.h" typedef struct QCryptoBlockDriver QCryptoBlockDriver ;
@@ -31,8 +32,12 @@ struct QCryptoBlock {const QCryptoBlockDriver *driver;void *opaque; -QCryptoCipher *cipher; +QCryptoCipher **ciphers; +size_t n_ciphers; +size_t n_free_ciphers;QCryptoIVGen *ivgen; +QemuMutex mutex; +QCryptoHashAlgorithm kdfhash;size_t niv;uint64_t payload_offset;/* In bytes */
@@ -46,6 +51,7 @@ struct QCryptoBlockDriver {QCryptoBlockReadFunc readfunc, void *opaque, unsigned int flags, + size_t n_threads, Error **errp); int (*create)(QCryptoBlock *block,
@@ -110,4 +116,12 @@ int qcrypto_block_encrypt_helper(QCryptoBlock *block,size_t len, Error **errp); +int qcrypto_block_init_cipher (QCryptoBlock *block, +QCryptoCipherAlgorithm alg, +QCryptoCipherMode mode, +const uint8_t *key,size_t nkey, +size_t n_threads,Error **errp); + +void qcrypto_block_free_cipher (QCryptoBlock *block); +#endif /* QCRYPTO_BLOCKPRIV_H */
include/crypto/block.h +2 -0
@@ -75,6 +75,7 @@ typedef enum {* @readfunc: callback for reading data from the volume * @opaque: data to pass to @readfunc * @flags: bitmask of QCryptoBlockOpenFlags values +* @n_threads: allow concurrent I/O from up to @n_threads threads * @errp: pointer to a NULL-initialized error object * * Create a new block encryption object for an existing
@@ -107,6 +108,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,QCryptoBlockReadFunc readfunc, void *opaque, unsigned int flags, + size_t n_threads, Error **errp);/**
block/crypto.c +1 -0
@@ -229,6 +229,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, block_crypto_read_func, bs, cflags, +1 , errp);if (!crypto->block) {
block/qcow.c +1 -1
@@ -213,7 +213,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, cflags |=QCRYPTO_BLOCK_OPEN_NO_IO ; } s->crypto =qcrypto_block_open (crypto_opts,"encrypt." , -NULL ,NULL , cflags, errp); +NULL ,NULL , cflags,1 , errp);if (!s->crypto) { ret = -EINVAL ; goto fail;
block/qcow2.c +2 -2
@@ -294,7 +294,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, } s->crypto =qcrypto_block_open (s->crypto_opts,"encrypt." , qcow2_crypto_hdr_read_func, - bs, cflags, errp); + bs, cflags,1 , errp);if (!s->crypto) {return -EINVAL ; }
@@ -1445,7 +1445,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, cflags |=QCRYPTO_BLOCK_OPEN_NO_IO ; } s->crypto =qcrypto_block_open (s->crypto_opts,"encrypt." , -NULL ,NULL , cflags, errp); +NULL ,NULL , cflags,1 , errp);if (!s->crypto) { ret = -EINVAL ; goto fail;
crypto/block-luks.c +10 -12
@@ -636,6 +636,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,QCryptoBlockReadFunc readfunc, void *opaque, unsigned int flags, + size_t n_threads, Error **errp) { QCryptoBlockLUKS *luks;
@@ -836,11 +837,10 @@ qcrypto_block_luks_open(QCryptoBlock *block, goto fail; } - block->cipher =qcrypto_cipher_new (cipheralg, - ciphermode, - masterkey, masterkeylen, - errp); -if (!block->cipher) { + ret =qcrypto_block_init_cipher (block, cipheralg, ciphermode, + masterkey, masterkeylen, n_threads, + errp); +if (ret <0 ) { ret = -ENOTSUP ; goto fail; }
@@ -863,7 +863,7 @@ qcrypto_block_luks_open(QCryptoBlock *block, fail:g_free (masterkey); -qcrypto_cipher_free (block->cipher); +qcrypto_block_free_cipher (block);qcrypto_ivgen_free (block->ivgen);g_free (luks);g_free (password);
@@ -1030,11 +1030,9 @@ qcrypto_block_luks_create(QCryptoBlock *block,/* Setup the block device payload encryption objects */ - block->cipher =qcrypto_cipher_new (luks_opts.cipher_alg, - luks_opts.cipher_mode, - masterkey, luks->header.key_bytes, - errp); -if (!block->cipher) { +if (qcrypto_block_init_cipher (block, luks_opts.cipher_alg, + luks_opts.cipher_mode, masterkey, + luks->header.key_bytes,1 , errp) <0 ) { goto error; }
@@ -1341,7 +1339,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,qcrypto_ivgen_free (ivgen);qcrypto_cipher_free (cipher); -qcrypto_cipher_free (block->cipher); +qcrypto_block_free_cipher (block);qcrypto_ivgen_free (block->ivgen);g_free (luks);
crypto/block-qcow.c +11 -9
@@ -44,6 +44,7 @@ qcrypto_block_qcow_has_format(const uint8_t *buf G_GNUC_UNUSED,static int qcrypto_block_qcow_init (QCryptoBlock *block,const char *keysecret, +size_t n_threads,Error **errp) {char *password;
@@ -71,11 +72,11 @@ qcrypto_block_qcow_init(QCryptoBlock *block, goto fail; } - block->cipher =qcrypto_cipher_new (QCRYPTO_CIPHER_ALG_AES_128 , -QCRYPTO_CIPHER_MODE_CBC , - keybuf,G_N_ELEMENTS (keybuf), - errp); -if (!block->cipher) { + ret =qcrypto_block_init_cipher (block,QCRYPTO_CIPHER_ALG_AES_128 , +QCRYPTO_CIPHER_MODE_CBC , + keybuf,G_N_ELEMENTS (keybuf), + n_threads, errp); +if (ret <0 ) { ret = -ENOTSUP ; goto fail; }
@@ -86,7 +87,7 @@ qcrypto_block_qcow_init(QCryptoBlock *block,return 0 ; fail: -qcrypto_cipher_free (block->cipher); +qcrypto_block_free_cipher (block);qcrypto_ivgen_free (block->ivgen);return ret; }
@@ -99,6 +100,7 @@ qcrypto_block_qcow_open(QCryptoBlock *block, QCryptoBlockReadFunc readfunc G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED, unsigned int flags, + size_t n_threads, Error **errp) { if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
@@ -112,8 +114,8 @@ qcrypto_block_qcow_open(QCryptoBlock *block, optprefix ? optprefix : "");return -1 ; } -return qcrypto_block_qcow_init (block, - options->u.qcow.key_secret, errp); +return qcrypto_block_qcow_init (block, options->u.qcow.key_secret, + n_threads, errp); } }
@@ -133,7 +135,7 @@ qcrypto_block_qcow_create(QCryptoBlock *block,return -1 ; }/* QCow2 has no special header, since everything is hardwired */ -return qcrypto_block_qcow_init (block, options->u.qcow.key_secret, errp); +return qcrypto_block_qcow_init (block, options->u.qcow.key_secret,1 , errp); }
crypto/block.c +127 -19
225 lines not on this page · raw message
tests/test-crypto-block.c +3 -0
@@ -305,6 +305,7 @@ static void test_block(gconstpointer opaque) test_block_read_func, &header,0 , +1 , NULL);g_assert (blk ==NULL );
@@ -313,6 +314,7 @@ static void test_block(gconstpointer opaque) test_block_read_func, &header,QCRYPTO_BLOCK_OPEN_NO_IO , +1 , &error_abort);g_assert (qcrypto_block_get_cipher (blk) ==NULL );
@@ -327,6 +329,7 @@ static void test_block(gconstpointer opaque) test_block_read_func, &header,0 , +1 , &error_abort);g_assert (blk);
Signature · 1 line
2.18.0
Re: [Qemu-devel] [PATCH v3 5/5] crypto: support multiple threads accessing one QCryptoBlock
crypto/block.c int qcrypto_block_encrypt(QCryptoBlock *block, · line 164
Quoted 13 lines · Vladimir Sementsov-Ogievskiy
crypto/block.c +8
-1@@ -148,12 +154,97 @@ int qcrypto_block_encrypt(QCryptoBlock *block,QCryptoCipher *qcrypto_block_get_cipher (QCryptoBlock *block) { -return block->cipher; +/* Ciphers should be accessed through pop/push method to be thread-safe. +* Better, they should not be accessed externally at all (note, that +* pop/push are static functions) +* This function is used only in test with one thread (it's safe to skip +* pop/push interface), so it's enough to assert it here: +*/ +assert (block->n_ciphers <=1 ); +return block->ciphers ? block->ciphers[0 ] :NULL ;
If this is only supposed to be called in test mode I think you can also assert that g_test_initialized() is true.
And the same with qcrypto_block_get_ivgen() later in this patch.
crypto/block.c int qcrypto_block_encrypt(QCryptoBlock *block, · line 207
Quoted 11 lines
crypto/block.c +11
-0+int qcrypto_block_init_cipher (QCryptoBlock *block, +QCryptoCipherAlgorithm alg, +QCryptoCipherMode mode, +const uint8_t *key,size_t nkey, +size_t n_threads,Error **errp) +{ +size_t i; + +assert (!block->ciphers && !block->n_ciphers && !block->n_free_ciphers); + + block->ciphers = g_new0(QCryptoCipher *, n_threads);
You can use g_new() instead of g_new0() because you're anyway overwriting all elements of the array.
But these are minor nits, the patchs looks good to me else.
Berto
Re: [Qemu-devel] [PATCH v3 5/5] crypto: support multiple threads accessing one QCryptoBlock
Quoted 18 lines · Alberto Garcia
crypto/block.c int qcrypto_block_encrypt(QCryptoBlock *block, · line 164
Quoted 13 lines · Vladimir Sementsov-Ogievskiy
crypto/block.c +8
-1@@ -148,12 +154,97 @@ int qcrypto_block_encrypt(QCryptoBlock *block,QCryptoCipher *qcrypto_block_get_cipher (QCryptoBlock *block) { -return block->cipher; +/* Ciphers should be accessed through pop/push method to be thread-safe. +* Better, they should not be accessed externally at all (note, that +* pop/push are static functions) +* This function is used only in test with one thread (it's safe to skip +* pop/push interface), so it's enough to assert it here: +*/ +assert (block->n_ciphers <=1 ); +return block->ciphers ? block->ciphers[0 ] :NULL ;If this is only supposed to be called in test mode I think you can also assert that
g_test_initialized()is true.
Quoted 1 line
And the same with
qcrypto_block_get_ivgen()later in this patch.
I consider these APIs as being valid for use anywhere - it just happens it is only used in the tests right now. So I think it is ok to assert on n_cipers here.
Quoted 6 lines
Quoted 6 lines
crypto/block.c +6
-0+int qcrypto_block_init_cipher (QCryptoBlock *block, +QCryptoCipherAlgorithm alg, +QCryptoCipherMode mode, +const uint8_t *key,size_t nkey, +size_t n_threads,Error **errp) +{
Quoted 8 lines
crypto/block.c int qcrypto_block_encrypt(QCryptoBlock *block, · line 207
Quoted 5 lines
crypto/block.c +5
-0+size_t i; + +assert (!block->ciphers && !block->n_ciphers && !block->n_free_ciphers); + + block->ciphers = g_new0(QCryptoCipher *, n_threads);You can use
g_new()instead ofg_new0()because you're anyway overwriting all elements of the array.
I'd rather have it initialized to zero upfront, so if creating any cipher in the array fails, we don't have uninitialized array elements during later cleanup code.
Quoted 3 lines
But these are minor nits, the patchs looks good to me else.
Reviewed-by Alberto Garcia <[email protected]>
Regards,
Daniel
Signature · 3 lines
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
Re: [Qemu-devel] [PATCH v3 5/5] crypto: support multiple threads accessing one QCryptoBlock
Quoted 15 lines · Daniel P. Berrangé
Quoted 6 lines
Quoted 6 lines
crypto/block.c +6
-0+int qcrypto_block_init_cipher (QCryptoBlock *block, +QCryptoCipherAlgorithm alg, +QCryptoCipherMode mode, +const uint8_t *key,size_t nkey, +size_t n_threads,Error **errp) +{Quoted 8 lines
crypto/block.c int qcrypto_block_encrypt(QCryptoBlock *block, · line 207
Quoted 5 lines
crypto/block.c +5
-0+size_t i; + +assert (!block->ciphers && !block->n_ciphers && !block->n_free_ciphers); + + block->ciphers = g_new0(QCryptoCipher *, n_threads);You can use
g_new()instead ofg_new0()because you're anyway overwriting all elements of the array.
Quoted 3 lines
I'd rather have it initialized to zero upfront, so if creating any cipher in the array fails, we don't have uninitialized array elements during later cleanup code.
But it is the value of block->n_ciphers that determines the size of the array, and that is only incremented after each successful iteration:
for (i = 0; i < n_threads; i++) {
block->ciphers[i] = qcrypto_cipher_new(alg, mode, key, nkey, errp);
/* ... error handling ... */
block->n_ciphers++;
block->n_free_ciphers++;
}In other words, the cleanup code won't touch uninitialized elements because it cannot even tell the difference between an index that points to an uninitialized element of the array and an index that points beyond the allocated memory.
Berto
Re: [Qemu-devel] [PATCH v3 5/5] crypto: support multiple threads accessing one QCryptoBlock
Quoted 30 lines · Alberto Garcia
Quoted 15 lines · Daniel P. Berrangé
Quoted 6 lines
Quoted 6 lines
crypto/block.c +6
-0+int qcrypto_block_init_cipher (QCryptoBlock *block, +QCryptoCipherAlgorithm alg, +QCryptoCipherMode mode, +const uint8_t *key,size_t nkey, +size_t n_threads,Error **errp) +{Quoted 8 lines
crypto/block.c int qcrypto_block_encrypt(QCryptoBlock *block, · line 207
Quoted 5 lines
crypto/block.c +5
-0+size_t i; + +assert (!block->ciphers && !block->n_ciphers && !block->n_free_ciphers); + + block->ciphers = g_new0(QCryptoCipher *, n_threads);You can use
g_new()instead ofg_new0()because you're anyway overwriting all elements of the array.Quoted 3 lines
I'd rather have it initialized to zero upfront, so if creating any cipher in the array fails, we don't have uninitialized array elements during later cleanup code.
But it is the value of
block->n_ciphersthat determines the size of the array, and that is only incremented after each successful iteration:for (i = 0; i < n_threads; i++) { block->ciphers[i] = qcrypto_cipher_new(alg, mode, key, nkey, errp); /* ... error handling ... */ block->n_ciphers++; block->n_free_ciphers++; }
Quoted 4 lines
In other words, the cleanup code won't touch uninitialized elements because it cannot even tell the difference between an index that points to an uninitialized element of the array and an index that points beyond the allocated memory.
.../correctly written/ cleanup code won't touch uninitialized elements...
I prefer to see the code be hardened against mistakes and so would always zero-initialize everything unless there's compelling performance reason not to in certain specific places.
Regards,
Daniel
Signature · 3 lines
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
Re: [Qemu-devel] [PATCH v3 5/5] crypto: support multiple threads accessing one QCryptoBlock
Quoted 10 lines · Daniel P. Berrangé
Quoted 4 lines
In other words, the cleanup code won't touch uninitialized elements because it cannot even tell the difference between an index that points to an uninitialized element of the array and an index that points beyond the allocated memory.
.../correctly written/ cleanup code won't touch uninitialized elements...
I prefer to see the code be hardened against mistakes and so would always zero-initialize everything unless there's compelling performance reason not to in certain specific places.
Ok, sounds reasonable.
Berto
Quoted 21 lines · Vladimir Sementsov-Ogievskiy
Hi all.
v3:
01: add r-b by Daniel and Alberto
02: Alberto r-bencrypt->encdec for generic03: qcrypto_cipher_*crypt_helper->
qcrypto_block_cipher_*crypt_helper
04: rebased on previous renamings
Daniel r-b
05: usesize_t
improve comment aboutn_threads
don't use ret inqcrypto_block_luks_create
doqemu_mutex_initat the end of open/create
doqemu_mutex_destroyin free
fix comment forqcrypto_block_get_cipherv2:
05: fix compilation of test-crypto-block (I am ashamed:(
and change QCryptoBlock interface to be a bit more safe.
Quoted 7 lines
These series are preliminary step before moving encryption code in qcow2 to the threads. The first attempt of doing it is on list ([PATCH 00/11] qcow2: encryption threads :
https://lists.gnu.org/archive/html/qemu-block/2018-11/msg00729.html)
But it's approach with multiplying the whole QCryptoBlock per thread was rejected. So, here is a solution to maintain multitasking inside QCryptoBlock.
Thanks, I've queued this series for when 4.0 opens up.
Regards,
Daniel
Signature · 3 lines
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|