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>
This commit is contained in:
Peter Maydell 2018-12-13 18:45:18 +00:00
commit d8d5fefd86
10 changed files with 264 additions and 112 deletions

View file

@ -229,6 +229,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
block_crypto_read_func, block_crypto_read_func,
bs, bs,
cflags, cflags,
1,
errp); errp);
if (!crypto->block) { if (!crypto->block) {

View file

@ -213,7 +213,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO; cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
} }
s->crypto = qcrypto_block_open(crypto_opts, "encrypt.", s->crypto = qcrypto_block_open(crypto_opts, "encrypt.",
NULL, NULL, cflags, errp); NULL, NULL, cflags, 1, errp);
if (!s->crypto) { if (!s->crypto) {
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;

View file

@ -294,7 +294,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
} }
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.", s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
qcow2_crypto_hdr_read_func, qcow2_crypto_hdr_read_func,
bs, cflags, errp); bs, cflags, 1, errp);
if (!s->crypto) { if (!s->crypto) {
return -EINVAL; return -EINVAL;
} }
@ -1445,7 +1445,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO; cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
} }
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.", s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
NULL, NULL, cflags, errp); NULL, NULL, cflags, 1, errp);
if (!s->crypto) { if (!s->crypto) {
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;

View file

@ -504,7 +504,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
* to reset the encryption cipher every time the master * to reset the encryption cipher every time the master
* key crosses a sector boundary. * key crosses a sector boundary.
*/ */
if (qcrypto_block_decrypt_helper(cipher, if (qcrypto_block_cipher_decrypt_helper(cipher,
niv, niv,
ivgen, ivgen,
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
@ -636,6 +636,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
QCryptoBlockReadFunc readfunc, QCryptoBlockReadFunc readfunc,
void *opaque, void *opaque,
unsigned int flags, unsigned int flags,
size_t n_threads,
Error **errp) Error **errp)
{ {
QCryptoBlockLUKS *luks; QCryptoBlockLUKS *luks;
@ -836,11 +837,10 @@ qcrypto_block_luks_open(QCryptoBlock *block,
goto fail; goto fail;
} }
block->cipher = qcrypto_cipher_new(cipheralg, ret = qcrypto_block_init_cipher(block, cipheralg, ciphermode,
ciphermode, masterkey, masterkeylen, n_threads,
masterkey, masterkeylen,
errp); errp);
if (!block->cipher) { if (ret < 0) {
ret = -ENOTSUP; ret = -ENOTSUP;
goto fail; goto fail;
} }
@ -863,7 +863,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
fail: fail:
g_free(masterkey); g_free(masterkey);
qcrypto_cipher_free(block->cipher); qcrypto_block_free_cipher(block);
qcrypto_ivgen_free(block->ivgen); qcrypto_ivgen_free(block->ivgen);
g_free(luks); g_free(luks);
g_free(password); g_free(password);
@ -1030,11 +1030,9 @@ qcrypto_block_luks_create(QCryptoBlock *block,
/* Setup the block device payload encryption objects */ /* Setup the block device payload encryption objects */
block->cipher = qcrypto_cipher_new(luks_opts.cipher_alg, if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg,
luks_opts.cipher_mode, luks_opts.cipher_mode, masterkey,
masterkey, luks->header.key_bytes, luks->header.key_bytes, 1, errp) < 0) {
errp);
if (!block->cipher) {
goto error; goto error;
} }
@ -1219,7 +1217,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
/* Now we encrypt the split master key with the key generated /* Now we encrypt the split master key with the key generated
* from the user's password, before storing it */ * from the user's password, before storing it */
if (qcrypto_block_encrypt_helper(cipher, block->niv, ivgen, if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen,
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
0, 0,
splitkey, splitkey,
@ -1341,6 +1339,9 @@ qcrypto_block_luks_create(QCryptoBlock *block,
qcrypto_ivgen_free(ivgen); qcrypto_ivgen_free(ivgen);
qcrypto_cipher_free(cipher); qcrypto_cipher_free(cipher);
qcrypto_block_free_cipher(block);
qcrypto_ivgen_free(block->ivgen);
g_free(luks); g_free(luks);
return -1; return -1;
} }
@ -1406,8 +1407,7 @@ qcrypto_block_luks_decrypt(QCryptoBlock *block,
{ {
assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
return qcrypto_block_decrypt_helper(block->cipher, return qcrypto_block_decrypt_helper(block,
block->niv, block->ivgen,
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
offset, buf, len, errp); offset, buf, len, errp);
} }
@ -1422,8 +1422,7 @@ qcrypto_block_luks_encrypt(QCryptoBlock *block,
{ {
assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
return qcrypto_block_encrypt_helper(block->cipher, return qcrypto_block_encrypt_helper(block,
block->niv, block->ivgen,
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
offset, buf, len, errp); offset, buf, len, errp);
} }

View file

@ -44,6 +44,7 @@ qcrypto_block_qcow_has_format(const uint8_t *buf G_GNUC_UNUSED,
static int static int
qcrypto_block_qcow_init(QCryptoBlock *block, qcrypto_block_qcow_init(QCryptoBlock *block,
const char *keysecret, const char *keysecret,
size_t n_threads,
Error **errp) Error **errp)
{ {
char *password; char *password;
@ -71,11 +72,11 @@ qcrypto_block_qcow_init(QCryptoBlock *block,
goto fail; goto fail;
} }
block->cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_128, ret = qcrypto_block_init_cipher(block, QCRYPTO_CIPHER_ALG_AES_128,
QCRYPTO_CIPHER_MODE_CBC, QCRYPTO_CIPHER_MODE_CBC,
keybuf, G_N_ELEMENTS(keybuf), keybuf, G_N_ELEMENTS(keybuf),
errp); n_threads, errp);
if (!block->cipher) { if (ret < 0) {
ret = -ENOTSUP; ret = -ENOTSUP;
goto fail; goto fail;
} }
@ -86,7 +87,7 @@ qcrypto_block_qcow_init(QCryptoBlock *block,
return 0; return 0;
fail: fail:
qcrypto_cipher_free(block->cipher); qcrypto_block_free_cipher(block);
qcrypto_ivgen_free(block->ivgen); qcrypto_ivgen_free(block->ivgen);
return ret; return ret;
} }
@ -99,6 +100,7 @@ qcrypto_block_qcow_open(QCryptoBlock *block,
QCryptoBlockReadFunc readfunc G_GNUC_UNUSED, QCryptoBlockReadFunc readfunc G_GNUC_UNUSED,
void *opaque G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED,
unsigned int flags, unsigned int flags,
size_t n_threads,
Error **errp) Error **errp)
{ {
if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) { if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
@ -112,8 +114,8 @@ qcrypto_block_qcow_open(QCryptoBlock *block,
optprefix ? optprefix : ""); optprefix ? optprefix : "");
return -1; return -1;
} }
return qcrypto_block_qcow_init(block, return qcrypto_block_qcow_init(block, options->u.qcow.key_secret,
options->u.qcow.key_secret, errp); n_threads, errp);
} }
} }
@ -133,7 +135,7 @@ qcrypto_block_qcow_create(QCryptoBlock *block,
return -1; return -1;
} }
/* QCow2 has no special header, since everything is hardwired */ /* 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);
} }
@ -152,8 +154,7 @@ qcrypto_block_qcow_decrypt(QCryptoBlock *block,
{ {
assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE));
assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE));
return qcrypto_block_decrypt_helper(block->cipher, return qcrypto_block_decrypt_helper(block,
block->niv, block->ivgen,
QCRYPTO_BLOCK_QCOW_SECTOR_SIZE, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE,
offset, buf, len, errp); offset, buf, len, errp);
} }
@ -168,8 +169,7 @@ qcrypto_block_qcow_encrypt(QCryptoBlock *block,
{ {
assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE));
assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE));
return qcrypto_block_encrypt_helper(block->cipher, return qcrypto_block_encrypt_helper(block,
block->niv, block->ivgen,
QCRYPTO_BLOCK_QCOW_SECTOR_SIZE, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE,
offset, buf, len, errp); offset, buf, len, errp);
} }

View file

@ -52,6 +52,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
QCryptoBlockReadFunc readfunc, QCryptoBlockReadFunc readfunc,
void *opaque, void *opaque,
unsigned int flags, unsigned int flags,
size_t n_threads,
Error **errp) Error **errp)
{ {
QCryptoBlock *block = g_new0(QCryptoBlock, 1); QCryptoBlock *block = g_new0(QCryptoBlock, 1);
@ -69,11 +70,14 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
block->driver = qcrypto_block_drivers[options->format]; block->driver = qcrypto_block_drivers[options->format];
if (block->driver->open(block, options, optprefix, if (block->driver->open(block, options, optprefix,
readfunc, opaque, flags, errp) < 0) { readfunc, opaque, flags, n_threads, errp) < 0)
{
g_free(block); g_free(block);
return NULL; return NULL;
} }
qemu_mutex_init(&block->mutex);
return block; return block;
} }
@ -105,6 +109,8 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
return NULL; return NULL;
} }
qemu_mutex_init(&block->mutex);
return block; return block;
} }
@ -148,12 +154,97 @@ int qcrypto_block_encrypt(QCryptoBlock *block,
QCryptoCipher *qcrypto_block_get_cipher(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) 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; return block->ivgen;
} }
@ -184,19 +275,28 @@ void qcrypto_block_free(QCryptoBlock *block)
block->driver->cleanup(block); block->driver->cleanup(block);
qcrypto_cipher_free(block->cipher); qcrypto_block_free_cipher(block);
qcrypto_ivgen_free(block->ivgen); qcrypto_ivgen_free(block->ivgen);
qemu_mutex_destroy(&block->mutex);
g_free(block); g_free(block);
} }
int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, typedef int (*QCryptoCipherEncDecFunc)(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp);
static int do_qcrypto_block_cipher_encdec(QCryptoCipher *cipher,
size_t niv, size_t niv,
QCryptoIVGen *ivgen, QCryptoIVGen *ivgen,
QemuMutex *ivgen_mutex,
int sectorsize, int sectorsize,
uint64_t offset, uint64_t offset,
uint8_t *buf, uint8_t *buf,
size_t len, size_t len,
QCryptoCipherEncDecFunc func,
Error **errp) Error **errp)
{ {
uint8_t *iv; uint8_t *iv;
@ -211,10 +311,15 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
while (len > 0) { while (len > 0) {
size_t nbytes; size_t nbytes;
if (niv) { if (niv) {
if (qcrypto_ivgen_calculate(ivgen, if (ivgen_mutex) {
startsector, qemu_mutex_lock(ivgen_mutex);
iv, niv, }
errp) < 0) { ret = qcrypto_ivgen_calculate(ivgen, startsector, iv, niv, errp);
if (ivgen_mutex) {
qemu_mutex_unlock(ivgen_mutex);
}
if (ret < 0) {
goto cleanup; goto cleanup;
} }
@ -226,8 +331,7 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
} }
nbytes = len > sectorsize ? sectorsize : len; nbytes = len > sectorsize ? sectorsize : len;
if (qcrypto_cipher_decrypt(cipher, buf, buf, if (func(cipher, buf, buf, nbytes, errp) < 0) {
nbytes, errp) < 0) {
goto cleanup; goto cleanup;
} }
@ -243,7 +347,7 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
} }
int qcrypto_block_encrypt_helper(QCryptoCipher *cipher, int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher,
size_t niv, size_t niv,
QCryptoIVGen *ivgen, QCryptoIVGen *ivgen,
int sectorsize, int sectorsize,
@ -252,45 +356,60 @@ int qcrypto_block_encrypt_helper(QCryptoCipher *cipher,
size_t len, size_t len,
Error **errp) Error **errp)
{ {
uint8_t *iv; return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
int ret = -1; offset, buf, len,
uint64_t startsector = offset / sectorsize; qcrypto_cipher_decrypt, errp);
}
assert(QEMU_IS_ALIGNED(offset, sectorsize));
assert(QEMU_IS_ALIGNED(len, sectorsize));
iv = niv ? g_new0(uint8_t, niv) : NULL; 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_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
offset, buf, len,
qcrypto_cipher_encrypt, errp);
}
while (len > 0) { int qcrypto_block_decrypt_helper(QCryptoBlock *block,
size_t nbytes; int sectorsize,
if (niv) { uint64_t offset,
if (qcrypto_ivgen_calculate(ivgen, uint8_t *buf,
startsector, size_t len,
iv, niv, Error **errp)
errp) < 0) { {
goto cleanup; int ret;
} QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
if (qcrypto_cipher_setiv(cipher, ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
iv, niv, &block->mutex, sectorsize, offset, buf,
errp) < 0) { len, qcrypto_cipher_decrypt, errp);
goto cleanup;
}
}
nbytes = len > sectorsize ? sectorsize : len; qcrypto_block_push_cipher(block, cipher);
if (qcrypto_cipher_encrypt(cipher, buf, buf,
nbytes, errp) < 0) { return ret;
goto cleanup; }
}
int qcrypto_block_encrypt_helper(QCryptoBlock *block,
int sectorsize,
uint64_t offset,
uint8_t *buf,
size_t len,
Error **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);
startsector++;
buf += nbytes;
len -= nbytes;
}
ret = 0;
cleanup:
g_free(iv);
return ret; return ret;
} }

View file

@ -22,6 +22,7 @@
#define QCRYPTO_BLOCKPRIV_H #define QCRYPTO_BLOCKPRIV_H
#include "crypto/block.h" #include "crypto/block.h"
#include "qemu/thread.h"
typedef struct QCryptoBlockDriver QCryptoBlockDriver; typedef struct QCryptoBlockDriver QCryptoBlockDriver;
@ -31,8 +32,12 @@ struct QCryptoBlock {
const QCryptoBlockDriver *driver; const QCryptoBlockDriver *driver;
void *opaque; void *opaque;
QCryptoCipher *cipher; QCryptoCipher **ciphers;
size_t n_ciphers;
size_t n_free_ciphers;
QCryptoIVGen *ivgen; QCryptoIVGen *ivgen;
QemuMutex mutex;
QCryptoHashAlgorithm kdfhash; QCryptoHashAlgorithm kdfhash;
size_t niv; size_t niv;
uint64_t payload_offset; /* In bytes */ uint64_t payload_offset; /* In bytes */
@ -46,6 +51,7 @@ struct QCryptoBlockDriver {
QCryptoBlockReadFunc readfunc, QCryptoBlockReadFunc readfunc,
void *opaque, void *opaque,
unsigned int flags, unsigned int flags,
size_t n_threads,
Error **errp); Error **errp);
int (*create)(QCryptoBlock *block, int (*create)(QCryptoBlock *block,
@ -78,7 +84,7 @@ struct QCryptoBlockDriver {
}; };
int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher,
size_t niv, size_t niv,
QCryptoIVGen *ivgen, QCryptoIVGen *ivgen,
int sectorsize, int sectorsize,
@ -87,7 +93,7 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
size_t len, size_t len,
Error **errp); Error **errp);
int qcrypto_block_encrypt_helper(QCryptoCipher *cipher, int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher,
size_t niv, size_t niv,
QCryptoIVGen *ivgen, QCryptoIVGen *ivgen,
int sectorsize, int sectorsize,
@ -96,4 +102,26 @@ int qcrypto_block_encrypt_helper(QCryptoCipher *cipher,
size_t len, size_t len,
Error **errp); 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);
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 */ #endif /* QCRYPTO_BLOCKPRIV_H */

View file

@ -75,6 +75,7 @@ typedef enum {
* @readfunc: callback for reading data from the volume * @readfunc: callback for reading data from the volume
* @opaque: data to pass to @readfunc * @opaque: data to pass to @readfunc
* @flags: bitmask of QCryptoBlockOpenFlags values * @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 * @errp: pointer to a NULL-initialized error object
* *
* Create a new block encryption object for an existing * Create a new block encryption object for an existing
@ -107,6 +108,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
QCryptoBlockReadFunc readfunc, QCryptoBlockReadFunc readfunc,
void *opaque, void *opaque,
unsigned int flags, unsigned int flags,
size_t n_threads,
Error **errp); Error **errp);
/** /**

View file

@ -181,11 +181,11 @@
# The options that apply to LUKS encryption format initialization # The options that apply to LUKS encryption format initialization
# #
# @cipher-alg: the cipher algorithm for data encryption # @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 # @cipher-mode: the cipher mode for data encryption
# Currently defaults to 'cbc' # Currently defaults to 'xts'
# @ivgen-alg: the initialization vector generator # @ivgen-alg: the initialization vector generator
# Currently defaults to 'essiv' # Currently defaults to 'plain64'
# @ivgen-hash-alg: the initialization vector generator hash # @ivgen-hash-alg: the initialization vector generator hash
# Currently defaults to 'sha256' # Currently defaults to 'sha256'
# @hash-alg: the master key hash algorithm # @hash-alg: the master key hash algorithm

View file

@ -305,6 +305,7 @@ static void test_block(gconstpointer opaque)
test_block_read_func, test_block_read_func,
&header, &header,
0, 0,
1,
NULL); NULL);
g_assert(blk == NULL); g_assert(blk == NULL);
@ -313,6 +314,7 @@ static void test_block(gconstpointer opaque)
test_block_read_func, test_block_read_func,
&header, &header,
QCRYPTO_BLOCK_OPEN_NO_IO, QCRYPTO_BLOCK_OPEN_NO_IO,
1,
&error_abort); &error_abort);
g_assert(qcrypto_block_get_cipher(blk) == NULL); g_assert(qcrypto_block_get_cipher(blk) == NULL);
@ -327,6 +329,7 @@ static void test_block(gconstpointer opaque)
test_block_read_func, test_block_read_func,
&header, &header,
0, 0,
1,
&error_abort); &error_abort);
g_assert(blk); g_assert(blk);