#include "qapi/error.h"
#include "qemu/bswap.h"
-#include "crypto/block-luks.h"
+#include "block-luks.h"
#include "crypto/hash.h"
#include "crypto/afsplit.h"
#include "crypto/pbkdf.h"
#include "crypto/secret.h"
#include "crypto/random.h"
-
-#ifdef CONFIG_UUID
-#include <uuid/uuid.h>
-#endif
+#include "qemu/uuid.h"
#include "qemu/coroutine.h"
}
error_setg(errp, "Algorithm '%s' not supported",
- QCryptoCipherAlgorithm_lookup[alg]);
+ QCryptoCipherAlgorithm_str(alg));
return NULL;
}
/* XXX replace with qapi_enum_parse() in future, when we can
* make that function emit a more friendly error message */
static int qcrypto_block_luks_name_lookup(const char *name,
- const char *const *map,
- size_t maplen,
+ const QEnumLookup *map,
const char *type,
Error **errp)
{
- size_t i;
- for (i = 0; i < maplen; i++) {
- if (g_str_equal(map[i], name)) {
- return i;
- }
- }
+ int ret = qapi_enum_parse(map, name, -1, NULL);
- error_setg(errp, "%s %s not supported", type, name);
- return 0;
+ if (ret < 0) {
+ error_setg(errp, "%s %s not supported", type, name);
+ return 0;
+ }
+ return ret;
}
#define qcrypto_block_luks_cipher_mode_lookup(name, errp) \
qcrypto_block_luks_name_lookup(name, \
- QCryptoCipherMode_lookup, \
- QCRYPTO_CIPHER_MODE__MAX, \
+ &QCryptoCipherMode_lookup, \
"Cipher mode", \
errp)
#define qcrypto_block_luks_hash_name_lookup(name, errp) \
qcrypto_block_luks_name_lookup(name, \
- QCryptoHashAlgorithm_lookup, \
- QCRYPTO_HASH_ALG__MAX, \
+ &QCryptoHashAlgorithm_lookup, \
"Hash algorithm", \
errp)
#define qcrypto_block_luks_ivgen_name_lookup(name, errp) \
qcrypto_block_luks_name_lookup(name, \
- QCryptoIVGenAlgorithm_lookup, \
- QCRYPTO_IVGEN_ALG__MAX, \
+ &QCryptoIVGenAlgorithm_lookup, \
"IV generator", \
errp)
break;
default:
error_setg(errp, "Cipher %s not supported with essiv",
- QCryptoCipherAlgorithm_lookup[cipher]);
+ QCryptoCipherAlgorithm_str(cipher));
return 0;
}
}
rv = readfunc(block,
slot->key_offset * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
splitkey, splitkeylen,
- errp,
- opaque);
+ opaque,
+ errp);
if (rv < 0) {
goto cleanup;
}
* 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;
}
static int
qcrypto_block_luks_open(QCryptoBlock *block,
QCryptoBlockOpenOptions *options,
+ const char *optprefix,
QCryptoBlockReadFunc readfunc,
void *opaque,
unsigned int flags,
if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) {
if (!options->u.luks.key_secret) {
- error_setg(errp, "Parameter 'key-secret' is required for cipher");
+ error_setg(errp, "Parameter '%skey-secret' is required for cipher",
+ optprefix ? optprefix : "");
return -1;
}
password = qcrypto_secret_lookup_as_utf8(
rv = readfunc(block, 0,
(uint8_t *)&luks->header,
sizeof(luks->header),
- errp,
- opaque);
+ opaque,
+ errp);
if (rv < 0) {
ret = rv;
goto fail;
}
}
+ block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
block->payload_offset = luks->header.payload_offset *
- QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
+ block->sector_size;
luks->cipher_alg = cipheralg;
luks->cipher_mode = ciphermode;
}
-static int
-qcrypto_block_luks_uuid_gen(uint8_t *uuidstr, Error **errp)
+static void
+qcrypto_block_luks_uuid_gen(uint8_t *uuidstr)
{
-#ifdef CONFIG_UUID
- uuid_t uuid;
- uuid_generate(uuid);
- uuid_unparse(uuid, (char *)uuidstr);
- return 0;
-#else
- error_setg(errp, "Unable to generate uuids on this platform");
- return -1;
-#endif
+ QemuUUID uuid;
+ qemu_uuid_generate(&uuid);
+ qemu_uuid_unparse(&uuid, (char *)uuidstr);
}
static int
qcrypto_block_luks_create(QCryptoBlock *block,
QCryptoBlockCreateOptions *options,
+ const char *optprefix,
QCryptoBlockInitFunc initfunc,
QCryptoBlockWriteFunc writefunc,
void *opaque,
* be silently ignored, for compatibility with dm-crypt */
if (!options->u.luks.key_secret) {
- error_setg(errp, "Parameter 'key-secret' is required for cipher");
+ error_setg(errp, "Parameter '%skey-secret' is required for cipher",
+ optprefix ? optprefix : "");
return -1;
}
password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp);
* it out to disk
*/
luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION;
- if (qcrypto_block_luks_uuid_gen(luks->header.uuid,
- errp) < 0) {
- goto error;
- }
+ qcrypto_block_luks_uuid_gen(luks->header.uuid);
cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg,
errp);
goto error;
}
- cipher_mode = QCryptoCipherMode_lookup[luks_opts.cipher_mode];
- ivgen_alg = QCryptoIVGenAlgorithm_lookup[luks_opts.ivgen_alg];
+ cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode);
+ ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg);
if (luks_opts.has_ivgen_hash_alg) {
- ivgen_hash_alg = QCryptoHashAlgorithm_lookup[luks_opts.ivgen_hash_alg];
+ ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg);
cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg,
ivgen_hash_alg);
} else {
cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg);
}
- hash_alg = QCryptoHashAlgorithm_lookup[luks_opts.hash_alg];
+ hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg);
if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) {
/* 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;
}
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) *
QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
+ block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
block->payload_offset = luks->header.payload_offset *
- QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
+ block->sector_size;
/* Reserve header space to match payload offset */
- initfunc(block, block->payload_offset, &local_err, opaque);
+ initfunc(block, block->payload_offset, opaque, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto error;
writefunc(block, 0,
(const uint8_t *)&luks->header,
sizeof(luks->header),
- &local_err,
- opaque);
+ opaque,
+ &local_err);
/* Delay checking local_err until we've byte-swapped */
luks->header.key_slots[0].key_offset *
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
splitkey, splitkeylen,
- errp,
- opaque) != splitkeylen) {
+ opaque,
+ errp) != splitkeylen) {
goto error;
}
qcrypto_ivgen_free(ivgen);
qcrypto_cipher_free(cipher);
+ qcrypto_cipher_free(block->cipher);
+ qcrypto_ivgen_free(block->ivgen);
+
g_free(luks);
return -1;
}
static int
qcrypto_block_luks_decrypt(QCryptoBlock *block,
- uint64_t startsector,
+ uint64_t offset,
uint8_t *buf,
size_t len,
Error **errp)
{
- return qcrypto_block_decrypt_helper(block->cipher,
- block->niv, block->ivgen,
- QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
- startsector, buf, len, errp);
+ 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);
}
static int
qcrypto_block_luks_encrypt(QCryptoBlock *block,
- uint64_t startsector,
+ uint64_t offset,
uint8_t *buf,
size_t len,
Error **errp)
{
- return qcrypto_block_encrypt_helper(block->cipher,
- block->niv, block->ivgen,
- QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
- startsector, buf, len, errp);
+ 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);
}