qcrypto-luks: use the parsed encryption settings in QCryptoBlockLUKS

Prior to that patch, the parsed encryption settings
were already stored into the QCryptoBlockLUKS but not
used anywhere but in qcrypto_block_luks_get_info

Using them simplifies the code

Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Maxim Levitsky 2019-09-26 00:35:20 +03:00 committed by Daniel P. Berrangé
parent 7e60a6f53d
commit 9d80e59d50

View file

@ -199,13 +199,25 @@ QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSHeader) != 592);
struct QCryptoBlockLUKS { struct QCryptoBlockLUKS {
QCryptoBlockLUKSHeader header; QCryptoBlockLUKSHeader header;
/* Cache parsed versions of what's in header fields, /* Main encryption algorithm used for encryption*/
* as we can't rely on QCryptoBlock.cipher being
* non-NULL */
QCryptoCipherAlgorithm cipher_alg; QCryptoCipherAlgorithm cipher_alg;
/* Mode of encryption for the selected encryption algorithm */
QCryptoCipherMode cipher_mode; QCryptoCipherMode cipher_mode;
/* Initialization vector generation algorithm */
QCryptoIVGenAlgorithm ivgen_alg; QCryptoIVGenAlgorithm ivgen_alg;
/* Hash algorithm used for IV generation*/
QCryptoHashAlgorithm ivgen_hash_alg; QCryptoHashAlgorithm ivgen_hash_alg;
/*
* Encryption algorithm used for IV generation.
* Usually the same as main encryption algorithm
*/
QCryptoCipherAlgorithm ivgen_cipher_alg;
/* Hash algorithm used in pbkdf2 function */
QCryptoHashAlgorithm hash_alg; QCryptoHashAlgorithm hash_alg;
}; };
@ -412,12 +424,6 @@ static int
qcrypto_block_luks_load_key(QCryptoBlock *block, qcrypto_block_luks_load_key(QCryptoBlock *block,
size_t slot_idx, size_t slot_idx,
const char *password, const char *password,
QCryptoCipherAlgorithm cipheralg,
QCryptoCipherMode ciphermode,
QCryptoHashAlgorithm hash,
QCryptoIVGenAlgorithm ivalg,
QCryptoCipherAlgorithm ivcipheralg,
QCryptoHashAlgorithm ivhash,
uint8_t *masterkey, uint8_t *masterkey,
QCryptoBlockReadFunc readfunc, QCryptoBlockReadFunc readfunc,
void *opaque, void *opaque,
@ -449,7 +455,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
* the key is correct and validate the results of * the key is correct and validate the results of
* decryption later. * decryption later.
*/ */
if (qcrypto_pbkdf2(hash, if (qcrypto_pbkdf2(luks->hash_alg,
(const uint8_t *)password, strlen(password), (const uint8_t *)password, strlen(password),
slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN, slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN,
slot->iterations, slot->iterations,
@ -477,19 +483,23 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
/* Setup the cipher/ivgen that we'll use to try to decrypt /* Setup the cipher/ivgen that we'll use to try to decrypt
* the split master key material */ * the split master key material */
cipher = qcrypto_cipher_new(cipheralg, ciphermode, cipher = qcrypto_cipher_new(luks->cipher_alg,
possiblekey, luks->header.master_key_len, luks->cipher_mode,
possiblekey,
luks->header.master_key_len,
errp); errp);
if (!cipher) { if (!cipher) {
return -1; return -1;
} }
niv = qcrypto_cipher_get_iv_len(cipheralg, niv = qcrypto_cipher_get_iv_len(luks->cipher_alg,
ciphermode); luks->cipher_mode);
ivgen = qcrypto_ivgen_new(ivalg,
ivcipheralg, ivgen = qcrypto_ivgen_new(luks->ivgen_alg,
ivhash, luks->ivgen_cipher_alg,
possiblekey, luks->header.master_key_len, luks->ivgen_hash_alg,
possiblekey,
luks->header.master_key_len,
errp); errp);
if (!ivgen) { if (!ivgen) {
return -1; return -1;
@ -518,7 +528,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
* Now we've decrypted the split master key, join * Now we've decrypted the split master key, join
* it back together to get the actual master key. * it back together to get the actual master key.
*/ */
if (qcrypto_afsplit_decode(hash, if (qcrypto_afsplit_decode(luks->hash_alg,
luks->header.master_key_len, luks->header.master_key_len,
slot->stripes, slot->stripes,
splitkey, splitkey,
@ -536,7 +546,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
* then comparing that to the hash stored in the key slot * then comparing that to the hash stored in the key slot
* header * header
*/ */
if (qcrypto_pbkdf2(hash, if (qcrypto_pbkdf2(luks->hash_alg,
masterkey, masterkey,
luks->header.master_key_len, luks->header.master_key_len,
luks->header.master_key_salt, luks->header.master_key_salt,
@ -570,12 +580,6 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
static int static int
qcrypto_block_luks_find_key(QCryptoBlock *block, qcrypto_block_luks_find_key(QCryptoBlock *block,
const char *password, const char *password,
QCryptoCipherAlgorithm cipheralg,
QCryptoCipherMode ciphermode,
QCryptoHashAlgorithm hash,
QCryptoIVGenAlgorithm ivalg,
QCryptoCipherAlgorithm ivcipheralg,
QCryptoHashAlgorithm ivhash,
uint8_t *masterkey, uint8_t *masterkey,
QCryptoBlockReadFunc readfunc, QCryptoBlockReadFunc readfunc,
void *opaque, void *opaque,
@ -588,12 +592,6 @@ qcrypto_block_luks_find_key(QCryptoBlock *block,
rv = qcrypto_block_luks_load_key(block, rv = qcrypto_block_luks_load_key(block,
i, i,
password, password,
cipheralg,
ciphermode,
hash,
ivalg,
ivcipheralg,
ivhash,
masterkey, masterkey,
readfunc, readfunc,
opaque, opaque,
@ -607,7 +605,6 @@ qcrypto_block_luks_find_key(QCryptoBlock *block,
} }
error_setg(errp, "Invalid password, cannot unlock any keyslot"); error_setg(errp, "Invalid password, cannot unlock any keyslot");
error: error:
return -1; return -1;
} }
@ -623,19 +620,13 @@ qcrypto_block_luks_open(QCryptoBlock *block,
size_t n_threads, size_t n_threads,
Error **errp) Error **errp)
{ {
QCryptoBlockLUKS *luks; QCryptoBlockLUKS *luks = NULL;
Error *local_err = NULL; Error *local_err = NULL;
int ret = 0; int ret = 0;
size_t i; size_t i;
ssize_t rv; ssize_t rv;
g_autofree uint8_t *masterkey = NULL; g_autofree uint8_t *masterkey = NULL;
char *ivgen_name, *ivhash_name; char *ivgen_name, *ivhash_name;
QCryptoCipherMode ciphermode;
QCryptoCipherAlgorithm cipheralg;
QCryptoIVGenAlgorithm ivalg;
QCryptoCipherAlgorithm ivcipheralg;
QCryptoHashAlgorithm hash;
QCryptoHashAlgorithm ivhash;
g_autofree char *password = NULL; g_autofree char *password = NULL;
g_autofree char *cipher_mode = NULL; g_autofree char *cipher_mode = NULL;
@ -716,12 +707,12 @@ qcrypto_block_luks_open(QCryptoBlock *block,
ivhash_name = strchr(ivgen_name, ':'); ivhash_name = strchr(ivgen_name, ':');
if (!ivhash_name) { if (!ivhash_name) {
ivhash = 0; luks->ivgen_hash_alg = 0;
} else { } else {
*ivhash_name = '\0'; *ivhash_name = '\0';
ivhash_name++; ivhash_name++;
ivhash = qcrypto_block_luks_hash_name_lookup(ivhash_name, luks->ivgen_hash_alg = qcrypto_block_luks_hash_name_lookup(ivhash_name,
&local_err); &local_err);
if (local_err) { if (local_err) {
ret = -ENOTSUP; ret = -ENOTSUP;
@ -730,7 +721,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
} }
} }
ciphermode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode, luks->cipher_mode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode,
&local_err); &local_err);
if (local_err) { if (local_err) {
ret = -ENOTSUP; ret = -ENOTSUP;
@ -738,9 +729,9 @@ qcrypto_block_luks_open(QCryptoBlock *block,
goto fail; goto fail;
} }
cipheralg = luks->cipher_alg =
qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name, qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name,
ciphermode, luks->cipher_mode,
luks->header.master_key_len, luks->header.master_key_len,
&local_err); &local_err);
if (local_err) { if (local_err) {
@ -749,7 +740,8 @@ qcrypto_block_luks_open(QCryptoBlock *block,
goto fail; goto fail;
} }
hash = qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec, luks->hash_alg =
qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec,
&local_err); &local_err);
if (local_err) { if (local_err) {
ret = -ENOTSUP; ret = -ENOTSUP;
@ -757,7 +749,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
goto fail; goto fail;
} }
ivalg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name, luks->ivgen_alg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name,
&local_err); &local_err);
if (local_err) { if (local_err) {
ret = -ENOTSUP; ret = -ENOTSUP;
@ -765,14 +757,15 @@ qcrypto_block_luks_open(QCryptoBlock *block,
goto fail; goto fail;
} }
if (ivalg == QCRYPTO_IVGEN_ALG_ESSIV) { if (luks->ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
if (!ivhash_name) { if (!ivhash_name) {
ret = -EINVAL; ret = -EINVAL;
error_setg(errp, "Missing IV generator hash specification"); error_setg(errp, "Missing IV generator hash specification");
goto fail; goto fail;
} }
ivcipheralg = qcrypto_block_luks_essiv_cipher(cipheralg, luks->ivgen_cipher_alg =
ivhash, qcrypto_block_luks_essiv_cipher(luks->cipher_alg,
luks->ivgen_hash_alg,
&local_err); &local_err);
if (local_err) { if (local_err) {
ret = -ENOTSUP; ret = -ENOTSUP;
@ -787,7 +780,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
* ignore hash names with these ivgens rather than report * ignore hash names with these ivgens rather than report
* an error about the invalid usage * an error about the invalid usage
*/ */
ivcipheralg = cipheralg; luks->ivgen_cipher_alg = luks->cipher_alg;
} }
if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) {
@ -799,11 +792,6 @@ qcrypto_block_luks_open(QCryptoBlock *block,
if (qcrypto_block_luks_find_key(block, if (qcrypto_block_luks_find_key(block,
password, password,
cipheralg, ciphermode,
hash,
ivalg,
ivcipheralg,
ivhash,
masterkey, masterkey,
readfunc, opaque, readfunc, opaque,
errp) < 0) { errp) < 0) {
@ -814,12 +802,13 @@ qcrypto_block_luks_open(QCryptoBlock *block,
/* We have a valid master key now, so can setup the /* We have a valid master key now, so can setup the
* block device payload decryption objects * block device payload decryption objects
*/ */
block->kdfhash = hash; block->kdfhash = luks->hash_alg;
block->niv = qcrypto_cipher_get_iv_len(cipheralg, block->niv = qcrypto_cipher_get_iv_len(luks->cipher_alg,
ciphermode); luks->cipher_mode);
block->ivgen = qcrypto_ivgen_new(ivalg,
ivcipheralg, block->ivgen = qcrypto_ivgen_new(luks->ivgen_alg,
ivhash, luks->ivgen_cipher_alg,
luks->ivgen_hash_alg,
masterkey, masterkey,
luks->header.master_key_len, luks->header.master_key_len,
errp); errp);
@ -828,7 +817,9 @@ qcrypto_block_luks_open(QCryptoBlock *block,
goto fail; goto fail;
} }
ret = qcrypto_block_init_cipher(block, cipheralg, ciphermode, ret = qcrypto_block_init_cipher(block,
luks->cipher_alg,
luks->cipher_mode,
masterkey, masterkey,
luks->header.master_key_len, luks->header.master_key_len,
n_threads, n_threads,
@ -843,11 +834,6 @@ qcrypto_block_luks_open(QCryptoBlock *block,
block->payload_offset = luks->header.payload_offset_sector * block->payload_offset = luks->header.payload_offset_sector *
block->sector_size; block->sector_size;
luks->cipher_alg = cipheralg;
luks->cipher_mode = ciphermode;
luks->ivgen_alg = ivalg;
luks->ivgen_hash_alg = ivhash;
luks->hash_alg = hash;
return 0; return 0;
@ -893,7 +879,6 @@ qcrypto_block_luks_create(QCryptoBlock *block,
const char *ivgen_hash_alg = NULL; const char *ivgen_hash_alg = NULL;
const char *hash_alg; const char *hash_alg;
g_autofree char *cipher_mode_spec = NULL; g_autofree char *cipher_mode_spec = NULL;
QCryptoCipherAlgorithm ivcipheralg = 0;
uint64_t iters; uint64_t iters;
memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts));
@ -918,6 +903,17 @@ qcrypto_block_luks_create(QCryptoBlock *block,
luks_opts.has_ivgen_hash_alg = true; luks_opts.has_ivgen_hash_alg = true;
} }
} }
luks = g_new0(QCryptoBlockLUKS, 1);
block->opaque = luks;
luks->cipher_alg = luks_opts.cipher_alg;
luks->cipher_mode = luks_opts.cipher_mode;
luks->ivgen_alg = luks_opts.ivgen_alg;
luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg;
luks->hash_alg = luks_opts.hash_alg;
/* Note we're allowing ivgen_hash_alg to be set even for /* Note we're allowing ivgen_hash_alg to be set even for
* non-essiv iv generators that don't need a hash. It will * non-essiv iv generators that don't need a hash. It will
* be silently ignored, for compatibility with dm-crypt */ * be silently ignored, for compatibility with dm-crypt */
@ -925,15 +921,13 @@ qcrypto_block_luks_create(QCryptoBlock *block,
if (!options->u.luks.key_secret) { if (!options->u.luks.key_secret) {
error_setg(errp, "Parameter '%skey-secret' is required for cipher", error_setg(errp, "Parameter '%skey-secret' is required for cipher",
optprefix ? optprefix : ""); optprefix ? optprefix : "");
return -1; goto error;
} }
password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp);
if (!password) { if (!password) {
return -1; goto error;
} }
luks = g_new0(QCryptoBlockLUKS, 1);
block->opaque = luks;
memcpy(luks->header.magic, qcrypto_block_luks_magic, memcpy(luks->header.magic, qcrypto_block_luks_magic,
QCRYPTO_BLOCK_LUKS_MAGIC_LEN); QCRYPTO_BLOCK_LUKS_MAGIC_LEN);
@ -980,7 +974,8 @@ qcrypto_block_luks_create(QCryptoBlock *block,
} }
if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
ivcipheralg = qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg, luks->ivgen_cipher_alg =
qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg,
luks_opts.ivgen_hash_alg, luks_opts.ivgen_hash_alg,
&local_err); &local_err);
if (local_err) { if (local_err) {
@ -988,7 +983,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
goto error; goto error;
} }
} else { } else {
ivcipheralg = luks_opts.cipher_alg; luks->ivgen_cipher_alg = luks_opts.cipher_alg;
} }
strcpy(luks->header.cipher_name, cipher_alg); strcpy(luks->header.cipher_name, cipher_alg);
@ -1030,7 +1025,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg, block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg,
luks_opts.cipher_mode); luks_opts.cipher_mode);
block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg,
ivcipheralg, luks->ivgen_cipher_alg,
luks_opts.ivgen_hash_alg, luks_opts.ivgen_hash_alg,
masterkey, luks->header.master_key_len, masterkey, luks->header.master_key_len,
errp); errp);
@ -1183,7 +1178,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
} }
ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg,
ivcipheralg, luks->ivgen_cipher_alg,
luks_opts.ivgen_hash_alg, luks_opts.ivgen_hash_alg,
slotkey, luks->header.master_key_len, slotkey, luks->header.master_key_len,
errp); errp);
@ -1294,12 +1289,6 @@ qcrypto_block_luks_create(QCryptoBlock *block,
goto error; goto error;
} }
luks->cipher_alg = luks_opts.cipher_alg;
luks->cipher_mode = luks_opts.cipher_mode;
luks->ivgen_alg = luks_opts.ivgen_alg;
luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg;
luks->hash_alg = luks_opts.hash_alg;
memset(masterkey, 0, luks->header.master_key_len); memset(masterkey, 0, luks->header.master_key_len);
memset(slotkey, 0, luks->header.master_key_len); memset(slotkey, 0, luks->header.master_key_len);