qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 0/6] Qcrypto next patches
@ 2018-12-12 11:24 Daniel P. Berrangé
  2018-12-12 11:24 ` [Qemu-devel] [PULL 1/6] crypto: Fix defaults in QCryptoBlockCreateOptionsLUKS Daniel P. Berrangé
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Daniel P. Berrangé @ 2018-12-12 11:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Daniel P. Berrangé, Max Reitz, qemu-block,
	Peter Maydell

The following changes since commit bb9bf94b3e8926553290bc9a7cb84315af422086:

  Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging (2018-12-11 19:18:58 +0000)

are available in the Git repository at:

  https://github.com/berrange/qemu tags/qcrypto-next-pull-request

for you to fetch changes up to c972fa123c73501b4b0c6de7873754ea3205a5eb:

  crypto: support multiple threads accessing one QCryptoBlock (2018-12-12 11:16:49 +0000)

----------------------------------------------------------------
Merge crypto patches 2018/12/12

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

----------------------------------------------------------------

Alberto Garcia (1):
  crypto: Fix defaults in QCryptoBlockCreateOptionsLUKS

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

 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 +++++++++++++++++++++++++++++---------
 crypto/blockpriv.h        |  42 +++++--
 include/crypto/block.h    |   2 +
 qapi/crypto.json          |   6 +-
 tests/test-crypto-block.c |   3 +
 10 files changed, 260 insertions(+), 108 deletions(-)

-- 
2.19.2

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PULL 1/6] crypto: Fix defaults in QCryptoBlockCreateOptionsLUKS
  2018-12-12 11:24 [Qemu-devel] [PULL 0/6] Qcrypto next patches Daniel P. Berrangé
@ 2018-12-12 11:24 ` Daniel P. Berrangé
  2018-12-12 11:24 ` [Qemu-devel] [PULL 2/6] crypto/block-luks: fix memory leak in qcrypto_block_luks_create Daniel P. Berrangé
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Daniel P. Berrangé @ 2018-12-12 11:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Daniel P. Berrangé, Max Reitz, qemu-block,
	Peter Maydell, Alberto Garcia

From: Alberto Garcia <berto@igalia.com>

The values specified in the documentation don't match the actual
defaults set in qcrypto_block_luks_create().

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 qapi/crypto.json | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/qapi/crypto.json b/qapi/crypto.json
index a51b434412..b2a4cff683 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -181,11 +181,11 @@
 # The options that apply to LUKS encryption format initialization
 #
 # @cipher-alg: the cipher algorithm for data encryption
-#              Currently defaults to 'aes'.
+#              Currently defaults to 'aes-256'.
 # @cipher-mode: the cipher mode for data encryption
-#               Currently defaults to 'cbc'
+#               Currently defaults to 'xts'
 # @ivgen-alg: the initialization vector generator
-#             Currently defaults to 'essiv'
+#             Currently defaults to 'plain64'
 # @ivgen-hash-alg: the initialization vector generator hash
 #                  Currently defaults to 'sha256'
 # @hash-alg: the master key hash algorithm
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PULL 2/6] crypto/block-luks: fix memory leak in qcrypto_block_luks_create
  2018-12-12 11:24 [Qemu-devel] [PULL 0/6] Qcrypto next patches Daniel P. Berrangé
  2018-12-12 11:24 ` [Qemu-devel] [PULL 1/6] crypto: Fix defaults in QCryptoBlockCreateOptionsLUKS Daniel P. Berrangé
@ 2018-12-12 11:24 ` Daniel P. Berrangé
  2018-12-12 11:24 ` [Qemu-devel] [PULL 3/6] crypto/block: refactor qcrypto_block_*crypt_helper functions Daniel P. Berrangé
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Daniel P. Berrangé @ 2018-12-12 11:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Daniel P. Berrangé, Max Reitz, qemu-block,
	Peter Maydell, Vladimir Sementsov-Ogievskiy

From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

Free block->cipher and block->ivgen on error path.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 crypto/block-luks.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index 5738124773..51e24d23ca 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -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;
 }
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PULL 3/6] crypto/block: refactor qcrypto_block_*crypt_helper functions
  2018-12-12 11:24 [Qemu-devel] [PULL 0/6] Qcrypto next patches Daniel P. Berrangé
  2018-12-12 11:24 ` [Qemu-devel] [PULL 1/6] crypto: Fix defaults in QCryptoBlockCreateOptionsLUKS Daniel P. Berrangé
  2018-12-12 11:24 ` [Qemu-devel] [PULL 2/6] crypto/block-luks: fix memory leak in qcrypto_block_luks_create Daniel P. Berrangé
@ 2018-12-12 11:24 ` Daniel P. Berrangé
  2018-12-12 11:24 ` [Qemu-devel] [PULL 4/6] crypto/block: rename qcrypto_block_*crypt_helper Daniel P. Berrangé
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Daniel P. Berrangé @ 2018-12-12 11:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Daniel P. Berrangé, Max Reitz, qemu-block,
	Peter Maydell, Vladimir Sementsov-Ogievskiy

From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

qcrypto_block_encrypt_helper and qcrypto_block_decrypt_helper are
almost identical, let's reduce code duplication and simplify further
improvements.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 crypto/block.c | 81 +++++++++++++++++++-------------------------------
 1 file changed, 31 insertions(+), 50 deletions(-)

diff --git a/crypto/block.c b/crypto/block.c
index e59d1140fe..8d0e4bdbb2 100644
--- a/crypto/block.c
+++ b/crypto/block.c
@@ -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);
 }
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PULL 4/6] crypto/block: rename qcrypto_block_*crypt_helper
  2018-12-12 11:24 [Qemu-devel] [PULL 0/6] Qcrypto next patches Daniel P. Berrangé
                   ` (2 preceding siblings ...)
  2018-12-12 11:24 ` [Qemu-devel] [PULL 3/6] crypto/block: refactor qcrypto_block_*crypt_helper functions Daniel P. Berrangé
@ 2018-12-12 11:24 ` Daniel P. Berrangé
  2018-12-12 11:24 ` [Qemu-devel] [PULL 5/6] crypto/block: introduce qcrypto_block_*crypt_helper functions Daniel P. Berrangé
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Daniel P. Berrangé @ 2018-12-12 11:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Daniel P. Berrangé, Max Reitz, qemu-block,
	Peter Maydell, Vladimir Sementsov-Ogievskiy

From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

Rename qcrypto_block_*crypt_helper to qcrypto_block_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.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 crypto/block-luks.c | 44 ++++++++++++++--------------
 crypto/block-qcow.c | 16 +++++------
 crypto/block.c      | 70 +++++++++++++++++++++++----------------------
 crypto/blockpriv.h  | 34 +++++++++++-----------
 4 files changed, 83 insertions(+), 81 deletions(-)

diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index 51e24d23ca..353a400595 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -504,14 +504,14 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
      * to reset the encryption cipher every time the master
      * key crosses a sector boundary.
      */
-    if (qcrypto_block_decrypt_helper(cipher,
-                                     niv,
-                                     ivgen,
-                                     QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
-                                     0,
-                                     splitkey,
-                                     splitkeylen,
-                                     errp) < 0) {
+    if (qcrypto_block_cipher_decrypt_helper(cipher,
+                                            niv,
+                                            ivgen,
+                                            QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
+                                            0,
+                                            splitkey,
+                                            splitkeylen,
+                                            errp) < 0) {
         goto cleanup;
     }
 
@@ -1219,12 +1219,12 @@ qcrypto_block_luks_create(QCryptoBlock *block,
 
     /* Now we encrypt the split master key with the key generated
      * from the user's password, before storing it */
-    if (qcrypto_block_encrypt_helper(cipher, block->niv, ivgen,
-                                     QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
-                                     0,
-                                     splitkey,
-                                     splitkeylen,
-                                     errp) < 0) {
+    if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen,
+                                            QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
+                                            0,
+                                            splitkey,
+                                            splitkeylen,
+                                            errp) < 0) {
         goto error;
     }
 
@@ -1409,10 +1409,10 @@ 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_decrypt_helper(block->cipher,
-                                        block->niv, block->ivgen,
-                                        QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
-                                        offset, buf, len, errp);
+    return qcrypto_block_cipher_decrypt_helper(block->cipher,
+                                               block->niv, block->ivgen,
+                                               QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
+                                               offset, buf, len, errp);
 }
 
 
@@ -1425,10 +1425,10 @@ 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_encrypt_helper(block->cipher,
-                                        block->niv, block->ivgen,
-                                        QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
-                                        offset, buf, len, errp);
+    return qcrypto_block_cipher_encrypt_helper(block->cipher,
+                                               block->niv, block->ivgen,
+                                               QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
+                                               offset, buf, len, errp);
 }
 
 
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
index 7606231e79..3b6722deb0 100644
--- a/crypto/block-qcow.c
+++ b/crypto/block-qcow.c
@@ -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);
 }
 
 
diff --git a/crypto/block.c b/crypto/block.c
index 8d0e4bdbb2..d43139dbc7 100644
--- a/crypto/block.c
+++ b/crypto/block.c
@@ -191,20 +191,20 @@ void qcrypto_block_free(QCryptoBlock *block)
 
 
 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)
+                                        const void *in,
+                                        void *out,
+                                        size_t len,
+                                        Error **errp);
+
+static int do_qcrypto_block_cipher_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;
@@ -249,29 +249,31 @@ static int do_qcrypto_block_encdec(QCryptoCipher *cipher,
 }
 
 
-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_cipher_decrypt_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_decrypt, errp);
+    return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, sectorsize,
+                                          offset, buf, len,
+                                          qcrypto_cipher_decrypt, 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_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);
+    return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, sectorsize,
+                                          offset, buf, len,
+                                          qcrypto_cipher_encrypt, errp);
 }
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
index 41840abcec..54bbe1eb6a 100644
--- a/crypto/blockpriv.h
+++ b/crypto/blockpriv.h
@@ -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 */
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PULL 5/6] crypto/block: introduce qcrypto_block_*crypt_helper functions
  2018-12-12 11:24 [Qemu-devel] [PULL 0/6] Qcrypto next patches Daniel P. Berrangé
                   ` (3 preceding siblings ...)
  2018-12-12 11:24 ` [Qemu-devel] [PULL 4/6] crypto/block: rename qcrypto_block_*crypt_helper Daniel P. Berrangé
@ 2018-12-12 11:24 ` Daniel P. Berrangé
  2018-12-12 11:24 ` [Qemu-devel] [PULL 6/6] crypto: support multiple threads accessing one QCryptoBlock Daniel P. Berrangé
  2018-12-14  9:50 ` [Qemu-devel] [PULL 0/6] Qcrypto next patches Peter Maydell
  6 siblings, 0 replies; 8+ messages in thread
From: Daniel P. Berrangé @ 2018-12-12 11:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Daniel P. Berrangé, Max Reitz, qemu-block,
	Peter Maydell, Vladimir Sementsov-Ogievskiy

From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

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 <vsementsov@virtuozzo.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 crypto/block-luks.c | 14 ++++++--------
 crypto/block-qcow.c | 14 ++++++--------
 crypto/block.c      | 28 ++++++++++++++++++++++++++++
 crypto/blockpriv.h  | 14 ++++++++++++++
 4 files changed, 54 insertions(+), 16 deletions(-)

diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index 353a400595..e486e7ee94 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -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);
 }
 
 
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
index 3b6722deb0..36bf5f09b7 100644
--- a/crypto/block-qcow.c
+++ b/crypto/block-qcow.c
@@ -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);
 }
 
 
diff --git a/crypto/block.c b/crypto/block.c
index d43139dbc7..3fe3de2ef8 100644
--- a/crypto/block.c
+++ b/crypto/block.c
@@ -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);
+}
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
index 54bbe1eb6a..438c08bec2 100644
--- a/crypto/blockpriv.h
+++ b/crypto/blockpriv.h
@@ -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 */
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PULL 6/6] crypto: support multiple threads accessing one QCryptoBlock
  2018-12-12 11:24 [Qemu-devel] [PULL 0/6] Qcrypto next patches Daniel P. Berrangé
                   ` (4 preceding siblings ...)
  2018-12-12 11:24 ` [Qemu-devel] [PULL 5/6] crypto/block: introduce qcrypto_block_*crypt_helper functions Daniel P. Berrangé
@ 2018-12-12 11:24 ` Daniel P. Berrangé
  2018-12-14  9:50 ` [Qemu-devel] [PULL 0/6] Qcrypto next patches Peter Maydell
  6 siblings, 0 replies; 8+ messages in thread
From: Daniel P. Berrangé @ 2018-12-12 11:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Daniel P. Berrangé, Max Reitz, qemu-block,
	Peter Maydell, Vladimir Sementsov-Ogievskiy

From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

The 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.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 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 +++++++++++++++++++++++++++++++++-----
 crypto/blockpriv.h        |  16 ++++-
 include/crypto/block.h    |   2 +
 tests/test-crypto-block.c |   3 +
 9 files changed, 172 insertions(+), 44 deletions(-)

diff --git a/block/crypto.c b/block/crypto.c
index 33ee01bebd..f0a5f6b987 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -229,6 +229,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
                                        block_crypto_read_func,
                                        bs,
                                        cflags,
+                                       1,
                                        errp);
 
     if (!crypto->block) {
diff --git a/block/qcow.c b/block/qcow.c
index 4518cb4c35..0a235bf393 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -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;
diff --git a/block/qcow2.c b/block/qcow2.c
index 991d6ac91b..bc8868c36a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -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;
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index e486e7ee94..6bac79c3ab 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -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);
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
index 36bf5f09b7..cefb3b2a7b 100644
--- 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,
 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);
 }
 
 
diff --git a/crypto/block.c b/crypto/block.c
index 3fe3de2ef8..d70d401f87 100644
--- a/crypto/block.c
+++ b/crypto/block.c
@@ -52,6 +52,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
                                  QCryptoBlockReadFunc readfunc,
                                  void *opaque,
                                  unsigned int flags,
+                                 size_t n_threads,
                                  Error **errp)
 {
     QCryptoBlock *block = g_new0(QCryptoBlock, 1);
@@ -69,11 +70,14 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
     block->driver = qcrypto_block_drivers[options->format];
 
     if (block->driver->open(block, options, optprefix,
-                            readfunc, opaque, flags, errp) < 0) {
+                            readfunc, opaque, flags, n_threads, errp) < 0)
+    {
         g_free(block);
         return NULL;
     }
 
+    qemu_mutex_init(&block->mutex);
+
     return block;
 }
 
@@ -105,6 +109,8 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
         return NULL;
     }
 
+    qemu_mutex_init(&block->mutex);
+
     return block;
 }
 
@@ -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;
+}
+
+
+static QCryptoCipher *qcrypto_block_pop_cipher(QCryptoBlock *block)
+{
+    QCryptoCipher *cipher;
+
+    qemu_mutex_lock(&block->mutex);
+
+    assert(block->n_free_ciphers > 0);
+    block->n_free_ciphers--;
+    cipher = block->ciphers[block->n_free_ciphers];
+
+    qemu_mutex_unlock(&block->mutex);
+
+    return cipher;
+}
+
+
+static void qcrypto_block_push_cipher(QCryptoBlock *block,
+                                      QCryptoCipher *cipher)
+{
+    qemu_mutex_lock(&block->mutex);
+
+    assert(block->n_free_ciphers < block->n_ciphers);
+    block->ciphers[block->n_free_ciphers] = cipher;
+    block->n_free_ciphers++;
+
+    qemu_mutex_unlock(&block->mutex);
+}
+
+
+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);
+
+    for (i = 0; i < n_threads; i++) {
+        block->ciphers[i] = qcrypto_cipher_new(alg, mode, key, nkey, errp);
+        if (!block->ciphers[i]) {
+            qcrypto_block_free_cipher(block);
+            return -1;
+        }
+        block->n_ciphers++;
+        block->n_free_ciphers++;
+    }
+
+    return 0;
 }
 
 
+void qcrypto_block_free_cipher(QCryptoBlock *block)
+{
+    size_t i;
+
+    if (!block->ciphers) {
+        return;
+    }
+
+    assert(block->n_ciphers == block->n_free_ciphers);
+
+    for (i = 0; i < block->n_ciphers; i++) {
+        qcrypto_cipher_free(block->ciphers[i]);
+    }
+
+    g_free(block->ciphers);
+    block->ciphers = NULL;
+    block->n_ciphers = block->n_free_ciphers = 0;
+}
+
 QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block)
 {
+    /* ivgen should be accessed under mutex. However, this function is used only
+     * in test with one thread, so it's enough to assert it here:
+     */
+    assert(block->n_ciphers <= 1);
     return block->ivgen;
 }
 
@@ -184,8 +275,9 @@ void qcrypto_block_free(QCryptoBlock *block)
 
     block->driver->cleanup(block);
 
-    qcrypto_cipher_free(block->cipher);
+    qcrypto_block_free_cipher(block);
     qcrypto_ivgen_free(block->ivgen);
+    qemu_mutex_destroy(&block->mutex);
     g_free(block);
 }
 
@@ -199,6 +291,7 @@ typedef int (*QCryptoCipherEncDecFunc)(QCryptoCipher *cipher,
 static int do_qcrypto_block_cipher_encdec(QCryptoCipher *cipher,
                                           size_t niv,
                                           QCryptoIVGen *ivgen,
+                                          QemuMutex *ivgen_mutex,
                                           int sectorsize,
                                           uint64_t offset,
                                           uint8_t *buf,
@@ -218,10 +311,15 @@ static int do_qcrypto_block_cipher_encdec(QCryptoCipher *cipher,
     while (len > 0) {
         size_t nbytes;
         if (niv) {
-            if (qcrypto_ivgen_calculate(ivgen,
-                                        startsector,
-                                        iv, niv,
-                                        errp) < 0) {
+            if (ivgen_mutex) {
+                qemu_mutex_lock(ivgen_mutex);
+            }
+            ret = qcrypto_ivgen_calculate(ivgen, startsector, iv, niv, errp);
+            if (ivgen_mutex) {
+                qemu_mutex_unlock(ivgen_mutex);
+            }
+
+            if (ret < 0) {
                 goto cleanup;
             }
 
@@ -258,7 +356,7 @@ int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher,
                                         size_t len,
                                         Error **errp)
 {
-    return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, sectorsize,
+    return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
                                           offset, buf, len,
                                           qcrypto_cipher_decrypt, errp);
 }
@@ -273,12 +371,11 @@ int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher,
                                         size_t len,
                                         Error **errp)
 {
-    return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, sectorsize,
+    return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
                                           offset, buf, len,
                                           qcrypto_cipher_encrypt, errp);
 }
 
-
 int qcrypto_block_decrypt_helper(QCryptoBlock *block,
                                  int sectorsize,
                                  uint64_t offset,
@@ -286,12 +383,17 @@ int qcrypto_block_decrypt_helper(QCryptoBlock *block,
                                  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 ret;
+    QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
 
+    ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
+                                         &block->mutex, sectorsize, offset, buf,
+                                         len, qcrypto_cipher_decrypt, errp);
+
+    qcrypto_block_push_cipher(block, cipher);
+
+    return ret;
+}
 
 int qcrypto_block_encrypt_helper(QCryptoBlock *block,
                                  int sectorsize,
@@ -300,8 +402,14 @@ int qcrypto_block_encrypt_helper(QCryptoBlock *block,
                                  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);
+    int ret;
+    QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
+
+    ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
+                                         &block->mutex, sectorsize, offset, buf,
+                                         len, qcrypto_cipher_encrypt, errp);
+
+    qcrypto_block_push_cipher(block, cipher);
+
+    return ret;
 }
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
index 438c08bec2..5438e822fd 100644
--- a/crypto/blockpriv.h
+++ b/crypto/blockpriv.h
@@ -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 */
diff --git a/include/crypto/block.h b/include/crypto/block.h
index cd18f46d56..e729d5bd66 100644
--- a/include/crypto/block.h
+++ b/include/crypto/block.h
@@ -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);
 
 /**
diff --git a/tests/test-crypto-block.c b/tests/test-crypto-block.c
index fae4ffc453..d309d044ef 100644
--- a/tests/test-crypto-block.c
+++ b/tests/test-crypto-block.c
@@ -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);
 
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PULL 0/6] Qcrypto next patches
  2018-12-12 11:24 [Qemu-devel] [PULL 0/6] Qcrypto next patches Daniel P. Berrangé
                   ` (5 preceding siblings ...)
  2018-12-12 11:24 ` [Qemu-devel] [PULL 6/6] crypto: support multiple threads accessing one QCryptoBlock Daniel P. Berrangé
@ 2018-12-14  9:50 ` Peter Maydell
  6 siblings, 0 replies; 8+ messages in thread
From: Peter Maydell @ 2018-12-14  9:50 UTC (permalink / raw)
  To: Daniel P. Berrange; +Cc: QEMU Developers, Kevin Wolf, Max Reitz, Qemu-block

On Wed, 12 Dec 2018 at 11:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> The following changes since commit bb9bf94b3e8926553290bc9a7cb84315af422086:
>
>   Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging (2018-12-11 19:18:58 +0000)
>
> are available in the Git repository at:
>
>   https://github.com/berrange/qemu tags/qcrypto-next-pull-request
>
> for you to fetch changes up to c972fa123c73501b4b0c6de7873754ea3205a5eb:
>
>   crypto: support multiple threads accessing one QCryptoBlock (2018-12-12 11:16:49 +0000)
>
> ----------------------------------------------------------------
> Merge crypto patches 2018/12/12
>
>  - Fix documentation about default LUKS algorithms
>  - Support for multi-threaded block crypto
>
> ----------------------------------------------------------------
>

Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/4.0
for any user-visible changes.

-- PMM

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-12-14  9:50 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-12-12 11:24 [Qemu-devel] [PULL 0/6] Qcrypto next patches Daniel P. Berrangé
2018-12-12 11:24 ` [Qemu-devel] [PULL 1/6] crypto: Fix defaults in QCryptoBlockCreateOptionsLUKS Daniel P. Berrangé
2018-12-12 11:24 ` [Qemu-devel] [PULL 2/6] crypto/block-luks: fix memory leak in qcrypto_block_luks_create Daniel P. Berrangé
2018-12-12 11:24 ` [Qemu-devel] [PULL 3/6] crypto/block: refactor qcrypto_block_*crypt_helper functions Daniel P. Berrangé
2018-12-12 11:24 ` [Qemu-devel] [PULL 4/6] crypto/block: rename qcrypto_block_*crypt_helper Daniel P. Berrangé
2018-12-12 11:24 ` [Qemu-devel] [PULL 5/6] crypto/block: introduce qcrypto_block_*crypt_helper functions Daniel P. Berrangé
2018-12-12 11:24 ` [Qemu-devel] [PULL 6/6] crypto: support multiple threads accessing one QCryptoBlock Daniel P. Berrangé
2018-12-14  9:50 ` [Qemu-devel] [PULL 0/6] Qcrypto next patches Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).