- LUKS support for detached headers
- Update x86 CPU model docs and script - Add missing close of chardev QIOChannel - More trace events o nTKS handshake - Drop unsafe VNC constants - Increase NOFILE limit during startup -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE2vOm/bJrYpEtDo4/vobrtBUQT98FAmXGMNUACgkQvobrtBUQ T998JQ//SqQ3L/AZmhE5cIwZ1XipSMMZ/yEoVIyniA3tL41S7Oimj3O9XvY68TEG nnj9Oh+zOlVLxauTHAczveJ7z+XfonQZS3HrbGRUTHU+ezGVjyM618e/h9pSQtYI +CCkrjtey1NoT42/um4D/bKg/B2XQeulS+pD12Z9l5zbqEZiw0R9+UwVIJ52G811 5UQgIjJ7GNFzalxqiMCkGc0nTyU8keEXQJcdZ4droo42DnU4pZeQWGDimzP61JnW 1Crm6aZSuUriUbVmxJde+2eEdPSR4rr/yQ4Pw06hoi1QJALSgGYtOTo8+qsyumHd us/2ouMrxOMdsIk4ViAkSTiaje9agPj84VE1Z229Y/uqZcEAuX572n730/kkzqUv ZDKxMz0v3rzpkjFmsgj5D4yqJaQp4zn1zYm98ld7HWJVIOf3GSvpaNg9J6jwN7Gi HKKkvYns9pxg3OSx++gqnM32HV6nnMDFiddipl/hTiUsnNlnWyTDSvJoNxIUU5+l /uEbbdt8xnxx1JP0LiOhgmz6N6FU7oOpaPuJ5CD8xO2RO8D1uBRvmpFcdOTDAfv0 uYdjhKBI+quKjE64p7gNWYCoqZtipRIJ6AY2VaPU8XHx8GvGFwBLX64oLYiYtrBG gkv3NTHRkMhQw9cGQcZIgZ+OLU+1eNF+m9EV7LUjuKl0HWC3Vjs= =61zI -----END PGP SIGNATURE----- Merge tag 'misc-fixes-pull-request' of https://gitlab.com/berrange/qemu into staging - LUKS support for detached headers - Update x86 CPU model docs and script - Add missing close of chardev QIOChannel - More trace events o nTKS handshake - Drop unsafe VNC constants - Increase NOFILE limit during startup # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEE2vOm/bJrYpEtDo4/vobrtBUQT98FAmXGMNUACgkQvobrtBUQ # T998JQ//SqQ3L/AZmhE5cIwZ1XipSMMZ/yEoVIyniA3tL41S7Oimj3O9XvY68TEG # nnj9Oh+zOlVLxauTHAczveJ7z+XfonQZS3HrbGRUTHU+ezGVjyM618e/h9pSQtYI # +CCkrjtey1NoT42/um4D/bKg/B2XQeulS+pD12Z9l5zbqEZiw0R9+UwVIJ52G811 # 5UQgIjJ7GNFzalxqiMCkGc0nTyU8keEXQJcdZ4droo42DnU4pZeQWGDimzP61JnW # 1Crm6aZSuUriUbVmxJde+2eEdPSR4rr/yQ4Pw06hoi1QJALSgGYtOTo8+qsyumHd # us/2ouMrxOMdsIk4ViAkSTiaje9agPj84VE1Z229Y/uqZcEAuX572n730/kkzqUv # ZDKxMz0v3rzpkjFmsgj5D4yqJaQp4zn1zYm98ld7HWJVIOf3GSvpaNg9J6jwN7Gi # HKKkvYns9pxg3OSx++gqnM32HV6nnMDFiddipl/hTiUsnNlnWyTDSvJoNxIUU5+l # /uEbbdt8xnxx1JP0LiOhgmz6N6FU7oOpaPuJ5CD8xO2RO8D1uBRvmpFcdOTDAfv0 # uYdjhKBI+quKjE64p7gNWYCoqZtipRIJ6AY2VaPU8XHx8GvGFwBLX64oLYiYtrBG # gkv3NTHRkMhQw9cGQcZIgZ+OLU+1eNF+m9EV7LUjuKl0HWC3Vjs= # =61zI # -----END PGP SIGNATURE----- # gpg: Signature made Fri 09 Feb 2024 14:04:05 GMT # gpg: using RSA key DAF3A6FDB26B62912D0E8E3FBE86EBB415104FDF # gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" [full] # gpg: aka "Daniel P. Berrange <berrange@redhat.com>" [full] # Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E 8E3F BE86 EBB4 1510 4FDF * tag 'misc-fixes-pull-request' of https://gitlab.com/berrange/qemu: tests: Add case for LUKS volume with detached header crypto: Introduce 'detached-header' field in QCryptoBlockInfoLUKS block: Support detached LUKS header creation using qemu-img block: Support detached LUKS header creation using blockdev-create crypto: Modify the qcrypto_block_create to support creation flags qapi: Make parameter 'file' optional for BlockdevCreateOptionsLUKS crypto: Support LUKS volume with detached header io: add trace event when cancelling TLS handshake chardev: close QIOChannel before unref'ing docs: re-generate x86_64 ABI compatibility CSV docs: fix highlighting of CPU ABI header rows scripts: drop comment about autogenerated CPU API file softmmu: remove obsolete comment about libvirt timeouts ui: drop VNC feature _MASK constants qemu_init: increase NOFILE soft limit on POSIX crypto: Introduce SM4 symmetric cipher algorithm meson: sort C warning flags alphabetically Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
15dbbeaff3
|
@ -3402,6 +3402,11 @@ F: migration/dirtyrate.c
|
||||||
F: migration/dirtyrate.h
|
F: migration/dirtyrate.h
|
||||||
F: include/sysemu/dirtyrate.h
|
F: include/sysemu/dirtyrate.h
|
||||||
|
|
||||||
|
Detached LUKS header
|
||||||
|
M: Hyman Huang <yong.huang@smartx.com>
|
||||||
|
S: Maintained
|
||||||
|
F: tests/qemu-iotests/tests/luks-detached-header
|
||||||
|
|
||||||
D-Bus
|
D-Bus
|
||||||
M: Marc-André Lureau <marcandre.lureau@redhat.com>
|
M: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
5
block.c
5
block.c
|
@ -7357,7 +7357,10 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == -1) {
|
/* Parameter 'size' is not needed for detached LUKS header */
|
||||||
|
if (size == -1 &&
|
||||||
|
!(!strcmp(fmt, "luks") &&
|
||||||
|
qemu_opt_get_bool(opts, "detached-header", false))) {
|
||||||
error_setg(errp, "Image creation needs a size parameter");
|
error_setg(errp, "Image creation needs a size parameter");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
144
block/crypto.c
144
block/crypto.c
|
@ -39,6 +39,7 @@ typedef struct BlockCrypto BlockCrypto;
|
||||||
struct BlockCrypto {
|
struct BlockCrypto {
|
||||||
QCryptoBlock *block;
|
QCryptoBlock *block;
|
||||||
bool updating_keys;
|
bool updating_keys;
|
||||||
|
BdrvChild *header; /* Reference to the detached LUKS header */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,12 +64,14 @@ static int block_crypto_read_func(QCryptoBlock *block,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = opaque;
|
BlockDriverState *bs = opaque;
|
||||||
|
BlockCrypto *crypto = bs->opaque;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||||
|
|
||||||
ret = bdrv_pread(bs->file, offset, buflen, buf, 0);
|
ret = bdrv_pread(crypto->header ? crypto->header : bs->file,
|
||||||
|
offset, buflen, buf, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg_errno(errp, -ret, "Could not read encryption header");
|
error_setg_errno(errp, -ret, "Could not read encryption header");
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -84,12 +87,14 @@ static int block_crypto_write_func(QCryptoBlock *block,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = opaque;
|
BlockDriverState *bs = opaque;
|
||||||
|
BlockCrypto *crypto = bs->opaque;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||||
|
|
||||||
ret = bdrv_pwrite(bs->file, offset, buflen, buf, 0);
|
ret = bdrv_pwrite(crypto->header ? crypto->header : bs->file,
|
||||||
|
offset, buflen, buf, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg_errno(errp, -ret, "Could not write encryption header");
|
error_setg_errno(errp, -ret, "Could not write encryption header");
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -157,6 +162,48 @@ error:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int coroutine_fn GRAPH_UNLOCKED
|
||||||
|
block_crypto_co_format_luks_payload(BlockdevCreateOptionsLUKS *luks_opts,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
BlockDriverState *bs = NULL;
|
||||||
|
BlockBackend *blk = NULL;
|
||||||
|
Error *local_error = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (luks_opts->size > INT64_MAX) {
|
||||||
|
return -EFBIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
bs = bdrv_co_open_blockdev_ref(luks_opts->file, errp);
|
||||||
|
if (bs == NULL) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
blk = blk_co_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE,
|
||||||
|
BLK_PERM_ALL, errp);
|
||||||
|
if (!blk) {
|
||||||
|
ret = -EPERM;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = blk_truncate(blk, luks_opts->size, true,
|
||||||
|
luks_opts->preallocation, 0, &local_error);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (ret == -EFBIG) {
|
||||||
|
/* Replace the error message with a better one */
|
||||||
|
error_free(local_error);
|
||||||
|
error_setg(errp, "The requested file size is too large");
|
||||||
|
}
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
bdrv_co_unref(bs);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static QemuOptsList block_crypto_runtime_opts_luks = {
|
static QemuOptsList block_crypto_runtime_opts_luks = {
|
||||||
.name = "crypto",
|
.name = "crypto",
|
||||||
|
@ -184,6 +231,7 @@ static QemuOptsList block_crypto_create_opts_luks = {
|
||||||
BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(""),
|
BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(""),
|
||||||
BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(""),
|
BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(""),
|
||||||
BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""),
|
BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""),
|
||||||
|
BLOCK_CRYPTO_OPT_DEF_LUKS_DETACHED_HEADER(""),
|
||||||
{ /* end of list */ }
|
{ /* end of list */ }
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -262,6 +310,8 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
|
||||||
int flags,
|
int flags,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
ERRP_GUARD();
|
||||||
|
|
||||||
BlockCrypto *crypto = bs->opaque;
|
BlockCrypto *crypto = bs->opaque;
|
||||||
QemuOpts *opts = NULL;
|
QemuOpts *opts = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -276,6 +326,13 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crypto->header = bdrv_open_child(NULL, options, "header", bs,
|
||||||
|
&child_of_bds, BDRV_CHILD_METADATA,
|
||||||
|
true, errp);
|
||||||
|
if (*errp != NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||||
|
|
||||||
bs->supported_write_flags = BDRV_REQ_FUA &
|
bs->supported_write_flags = BDRV_REQ_FUA &
|
||||||
|
@ -299,6 +356,9 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
|
||||||
if (flags & BDRV_O_NO_IO) {
|
if (flags & BDRV_O_NO_IO) {
|
||||||
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
|
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
|
||||||
}
|
}
|
||||||
|
if (crypto->header != NULL) {
|
||||||
|
cflags |= QCRYPTO_BLOCK_OPEN_DETACHED;
|
||||||
|
}
|
||||||
crypto->block = qcrypto_block_open(open_opts, NULL,
|
crypto->block = qcrypto_block_open(open_opts, NULL,
|
||||||
block_crypto_read_func,
|
block_crypto_read_func,
|
||||||
bs,
|
bs,
|
||||||
|
@ -324,7 +384,9 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
|
||||||
static int coroutine_fn GRAPH_UNLOCKED
|
static int coroutine_fn GRAPH_UNLOCKED
|
||||||
block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
|
block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
|
||||||
QCryptoBlockCreateOptions *opts,
|
QCryptoBlockCreateOptions *opts,
|
||||||
PreallocMode prealloc, Error **errp)
|
PreallocMode prealloc,
|
||||||
|
unsigned int flags,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
|
@ -344,7 +406,7 @@ block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
|
||||||
|
|
||||||
data = (struct BlockCryptoCreateData) {
|
data = (struct BlockCryptoCreateData) {
|
||||||
.blk = blk,
|
.blk = blk,
|
||||||
.size = size,
|
.size = flags & QCRYPTO_BLOCK_CREATE_DETACHED ? 0 : size,
|
||||||
.prealloc = prealloc,
|
.prealloc = prealloc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -352,6 +414,7 @@ block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
|
||||||
block_crypto_create_init_func,
|
block_crypto_create_init_func,
|
||||||
block_crypto_create_write_func,
|
block_crypto_create_write_func,
|
||||||
&data,
|
&data,
|
||||||
|
flags,
|
||||||
errp);
|
errp);
|
||||||
|
|
||||||
if (!crypto) {
|
if (!crypto) {
|
||||||
|
@ -638,17 +701,27 @@ static int coroutine_fn GRAPH_UNLOCKED
|
||||||
block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
|
block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
|
||||||
{
|
{
|
||||||
BlockdevCreateOptionsLUKS *luks_opts;
|
BlockdevCreateOptionsLUKS *luks_opts;
|
||||||
|
BlockDriverState *hdr_bs = NULL;
|
||||||
BlockDriverState *bs = NULL;
|
BlockDriverState *bs = NULL;
|
||||||
QCryptoBlockCreateOptions create_opts;
|
QCryptoBlockCreateOptions create_opts;
|
||||||
PreallocMode preallocation = PREALLOC_MODE_OFF;
|
PreallocMode preallocation = PREALLOC_MODE_OFF;
|
||||||
|
unsigned int cflags = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
assert(create_options->driver == BLOCKDEV_DRIVER_LUKS);
|
assert(create_options->driver == BLOCKDEV_DRIVER_LUKS);
|
||||||
luks_opts = &create_options->u.luks;
|
luks_opts = &create_options->u.luks;
|
||||||
|
|
||||||
bs = bdrv_co_open_blockdev_ref(luks_opts->file, errp);
|
if (luks_opts->header == NULL && luks_opts->file == NULL) {
|
||||||
if (bs == NULL) {
|
error_setg(errp, "Either the parameter 'header' or 'file' must "
|
||||||
return -EIO;
|
"be specified");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((luks_opts->preallocation != PREALLOC_MODE_OFF) &&
|
||||||
|
(luks_opts->file == NULL)) {
|
||||||
|
error_setg(errp, "Parameter 'preallocation' requires 'file' to be "
|
||||||
|
"specified for formatting LUKS disk");
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
create_opts = (QCryptoBlockCreateOptions) {
|
create_opts = (QCryptoBlockCreateOptions) {
|
||||||
|
@ -660,15 +733,52 @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
|
||||||
preallocation = luks_opts->preallocation;
|
preallocation = luks_opts->preallocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = block_crypto_co_create_generic(bs, luks_opts->size, &create_opts,
|
if (luks_opts->header) {
|
||||||
preallocation, errp);
|
/* LUKS volume with detached header */
|
||||||
if (ret < 0) {
|
hdr_bs = bdrv_co_open_blockdev_ref(luks_opts->header, errp);
|
||||||
goto fail;
|
if (hdr_bs == NULL) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
cflags |= QCRYPTO_BLOCK_CREATE_DETACHED;
|
||||||
|
|
||||||
|
/* Format the LUKS header node */
|
||||||
|
ret = block_crypto_co_create_generic(hdr_bs, 0, &create_opts,
|
||||||
|
PREALLOC_MODE_OFF, cflags, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Format the LUKS payload node */
|
||||||
|
if (luks_opts->file) {
|
||||||
|
ret = block_crypto_co_format_luks_payload(luks_opts, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (luks_opts->file) {
|
||||||
|
/* LUKS volume with none-detached header */
|
||||||
|
bs = bdrv_co_open_blockdev_ref(luks_opts->file, errp);
|
||||||
|
if (bs == NULL) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = block_crypto_co_create_generic(bs, luks_opts->size, &create_opts,
|
||||||
|
preallocation, cflags, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
fail:
|
fail:
|
||||||
bdrv_co_unref(bs);
|
if (hdr_bs != NULL) {
|
||||||
|
bdrv_co_unref(hdr_bs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bs != NULL) {
|
||||||
|
bdrv_co_unref(bs);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,6 +792,9 @@ block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename,
|
||||||
PreallocMode prealloc;
|
PreallocMode prealloc;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
int64_t size;
|
int64_t size;
|
||||||
|
bool detached_hdr =
|
||||||
|
qemu_opt_get_bool(opts, "detached-header", false);
|
||||||
|
unsigned int cflags = 0;
|
||||||
int ret;
|
int ret;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
@ -721,8 +834,13 @@ block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (detached_hdr) {
|
||||||
|
cflags |= QCRYPTO_BLOCK_CREATE_DETACHED;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create format layer */
|
/* Create format layer */
|
||||||
ret = block_crypto_co_create_generic(bs, size, create_opts, prealloc, errp);
|
ret = block_crypto_co_create_generic(bs, size, create_opts,
|
||||||
|
prealloc, cflags, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-alg"
|
#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-alg"
|
||||||
#define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg"
|
#define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg"
|
||||||
#define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
|
#define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
|
||||||
|
#define BLOCK_CRYPTO_OPT_LUKS_DETACHED_HEADER "detached-header"
|
||||||
#define BLOCK_CRYPTO_OPT_LUKS_KEYSLOT "keyslot"
|
#define BLOCK_CRYPTO_OPT_LUKS_KEYSLOT "keyslot"
|
||||||
#define BLOCK_CRYPTO_OPT_LUKS_STATE "state"
|
#define BLOCK_CRYPTO_OPT_LUKS_STATE "state"
|
||||||
#define BLOCK_CRYPTO_OPT_LUKS_OLD_SECRET "old-secret"
|
#define BLOCK_CRYPTO_OPT_LUKS_OLD_SECRET "old-secret"
|
||||||
|
@ -100,6 +101,13 @@
|
||||||
.help = "Select new state of affected keyslots (active/inactive)",\
|
.help = "Select new state of affected keyslots (active/inactive)",\
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BLOCK_CRYPTO_OPT_DEF_LUKS_DETACHED_HEADER(prefix) \
|
||||||
|
{ \
|
||||||
|
.name = prefix BLOCK_CRYPTO_OPT_LUKS_DETACHED_HEADER, \
|
||||||
|
.type = QEMU_OPT_BOOL, \
|
||||||
|
.help = "Create a detached LUKS header", \
|
||||||
|
}
|
||||||
|
|
||||||
#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEYSLOT(prefix) \
|
#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEYSLOT(prefix) \
|
||||||
{ \
|
{ \
|
||||||
.name = prefix BLOCK_CRYPTO_OPT_LUKS_KEYSLOT, \
|
.name = prefix BLOCK_CRYPTO_OPT_LUKS_KEYSLOT, \
|
||||||
|
|
|
@ -885,7 +885,7 @@ qcow_co_create(BlockdevCreateOptions *opts, Error **errp)
|
||||||
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
|
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
|
||||||
|
|
||||||
crypto = qcrypto_block_create(qcow_opts->encrypt, "encrypt.",
|
crypto = qcrypto_block_create(qcow_opts->encrypt, "encrypt.",
|
||||||
NULL, NULL, NULL, errp);
|
NULL, NULL, NULL, 0, errp);
|
||||||
if (!crypto) {
|
if (!crypto) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
|
@ -3216,7 +3216,7 @@ qcow2_set_up_encryption(BlockDriverState *bs,
|
||||||
crypto = qcrypto_block_create(cryptoopts, "encrypt.",
|
crypto = qcrypto_block_create(cryptoopts, "encrypt.",
|
||||||
qcow2_crypto_hdr_init_func,
|
qcow2_crypto_hdr_init_func,
|
||||||
qcow2_crypto_hdr_write_func,
|
qcow2_crypto_hdr_write_func,
|
||||||
bs, errp);
|
bs, 0, errp);
|
||||||
if (!crypto) {
|
if (!crypto) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -378,6 +378,10 @@ static void tcp_chr_free_connection(Chardev *chr)
|
||||||
char_socket_yank_iochannel,
|
char_socket_yank_iochannel,
|
||||||
QIO_CHANNEL(s->sioc));
|
QIO_CHANNEL(s->sioc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->ioc) {
|
||||||
|
qio_channel_close(s->ioc, NULL);
|
||||||
|
}
|
||||||
object_unref(OBJECT(s->sioc));
|
object_unref(OBJECT(s->sioc));
|
||||||
s->sioc = NULL;
|
s->sioc = NULL;
|
||||||
object_unref(OBJECT(s->ioc));
|
object_unref(OBJECT(s->ioc));
|
||||||
|
|
|
@ -95,12 +95,23 @@ qcrypto_block_luks_cipher_size_map_twofish[] = {
|
||||||
{ 0, 0 },
|
{ 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_CRYPTO_SM4
|
||||||
|
static const QCryptoBlockLUKSCipherSizeMap
|
||||||
|
qcrypto_block_luks_cipher_size_map_sm4[] = {
|
||||||
|
{ 16, QCRYPTO_CIPHER_ALG_SM4},
|
||||||
|
{ 0, 0 },
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static const QCryptoBlockLUKSCipherNameMap
|
static const QCryptoBlockLUKSCipherNameMap
|
||||||
qcrypto_block_luks_cipher_name_map[] = {
|
qcrypto_block_luks_cipher_name_map[] = {
|
||||||
{ "aes", qcrypto_block_luks_cipher_size_map_aes },
|
{ "aes", qcrypto_block_luks_cipher_size_map_aes },
|
||||||
{ "cast5", qcrypto_block_luks_cipher_size_map_cast5 },
|
{ "cast5", qcrypto_block_luks_cipher_size_map_cast5 },
|
||||||
{ "serpent", qcrypto_block_luks_cipher_size_map_serpent },
|
{ "serpent", qcrypto_block_luks_cipher_size_map_serpent },
|
||||||
{ "twofish", qcrypto_block_luks_cipher_size_map_twofish },
|
{ "twofish", qcrypto_block_luks_cipher_size_map_twofish },
|
||||||
|
#ifdef CONFIG_CRYPTO_SM4
|
||||||
|
{ "sm4", qcrypto_block_luks_cipher_size_map_sm4},
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48);
|
QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48);
|
||||||
|
@ -457,12 +468,15 @@ qcrypto_block_luks_load_header(QCryptoBlock *block,
|
||||||
* Does basic sanity checks on the LUKS header
|
* Does basic sanity checks on the LUKS header
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, Error **errp)
|
qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks,
|
||||||
|
unsigned int flags,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
|
|
||||||
unsigned int header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
|
unsigned int header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
|
||||||
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
|
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
|
||||||
|
bool detached = flags & QCRYPTO_BLOCK_OPEN_DETACHED;
|
||||||
|
|
||||||
if (memcmp(luks->header.magic, qcrypto_block_luks_magic,
|
if (memcmp(luks->header.magic, qcrypto_block_luks_magic,
|
||||||
QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) {
|
QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) {
|
||||||
|
@ -494,7 +508,7 @@ qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, Error **errp)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (luks->header.payload_offset_sector <
|
if (!detached && luks->header.payload_offset_sector <
|
||||||
DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET,
|
DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET,
|
||||||
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) {
|
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) {
|
||||||
error_setg(errp, "LUKS payload is overlapping with the header");
|
error_setg(errp, "LUKS payload is overlapping with the header");
|
||||||
|
@ -543,7 +557,7 @@ qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, Error **errp)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start1 + len1 > luks->header.payload_offset_sector) {
|
if (!detached && start1 + len1 > luks->header.payload_offset_sector) {
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"Keyslot %zu is overlapping with the encrypted payload",
|
"Keyslot %zu is overlapping with the encrypted payload",
|
||||||
i);
|
i);
|
||||||
|
@ -1203,7 +1217,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qcrypto_block_luks_check_header(luks, errp) < 0) {
|
if (qcrypto_block_luks_check_header(luks, flags, errp) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1257,6 +1271,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
|
||||||
block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
|
block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
|
||||||
block->payload_offset = luks->header.payload_offset_sector *
|
block->payload_offset = luks->header.payload_offset_sector *
|
||||||
block->sector_size;
|
block->sector_size;
|
||||||
|
block->detached_header = (block->payload_offset == 0) ? true : false;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1301,6 +1316,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
|
||||||
const char *hash_alg;
|
const char *hash_alg;
|
||||||
g_autofree char *cipher_mode_spec = NULL;
|
g_autofree char *cipher_mode_spec = NULL;
|
||||||
uint64_t iters;
|
uint64_t iters;
|
||||||
|
uint64_t detached_header_size;
|
||||||
|
|
||||||
memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts));
|
memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts));
|
||||||
if (!luks_opts.has_iter_time) {
|
if (!luks_opts.has_iter_time) {
|
||||||
|
@ -1529,19 +1545,32 @@ qcrypto_block_luks_create(QCryptoBlock *block,
|
||||||
slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES;
|
slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The total size of the LUKS headers is the partition header + key
|
if (block->detached_header) {
|
||||||
* slot headers, rounded up to the nearest sector, combined with
|
/*
|
||||||
* the size of each master key material region, also rounded up
|
* For a detached LUKS header image, set the payload_offset_sector
|
||||||
* to the nearest sector */
|
* to 0 to specify the starting point for read/write
|
||||||
luks->header.payload_offset_sector = header_sectors +
|
*/
|
||||||
QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors;
|
luks->header.payload_offset_sector = 0;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* The total size of the LUKS headers is the partition header + key
|
||||||
|
* slot headers, rounded up to the nearest sector, combined with
|
||||||
|
* the size of each master key material region, also rounded up
|
||||||
|
* to the nearest sector
|
||||||
|
*/
|
||||||
|
luks->header.payload_offset_sector = header_sectors +
|
||||||
|
QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors;
|
||||||
|
}
|
||||||
|
|
||||||
block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
|
block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
|
||||||
block->payload_offset = luks->header.payload_offset_sector *
|
block->payload_offset = luks->header.payload_offset_sector *
|
||||||
block->sector_size;
|
block->sector_size;
|
||||||
|
detached_header_size =
|
||||||
|
(header_sectors + QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS *
|
||||||
|
split_key_sectors) * block->sector_size;
|
||||||
|
|
||||||
/* Reserve header space to match payload offset */
|
/* Reserve header space to match payload offset */
|
||||||
initfunc(block, block->payload_offset, opaque, &local_err);
|
initfunc(block, detached_header_size, opaque, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1867,6 +1896,7 @@ static int qcrypto_block_luks_get_info(QCryptoBlock *block,
|
||||||
info->u.luks.master_key_iters = luks->header.master_key_iterations;
|
info->u.luks.master_key_iters = luks->header.master_key_iterations;
|
||||||
info->u.luks.uuid = g_strndup((const char *)luks->header.uuid,
|
info->u.luks.uuid = g_strndup((const char *)luks->header.uuid,
|
||||||
sizeof(luks->header.uuid));
|
sizeof(luks->header.uuid));
|
||||||
|
info->u.luks.detached_header = block->detached_header;
|
||||||
|
|
||||||
for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
|
for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
|
||||||
slot = g_new0(QCryptoBlockInfoLUKSSlot, 1);
|
slot = g_new0(QCryptoBlockInfoLUKSSlot, 1);
|
||||||
|
|
|
@ -87,6 +87,7 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
|
||||||
QCryptoBlockInitFunc initfunc,
|
QCryptoBlockInitFunc initfunc,
|
||||||
QCryptoBlockWriteFunc writefunc,
|
QCryptoBlockWriteFunc writefunc,
|
||||||
void *opaque,
|
void *opaque,
|
||||||
|
unsigned int flags,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoBlock *block = g_new0(QCryptoBlock, 1);
|
QCryptoBlock *block = g_new0(QCryptoBlock, 1);
|
||||||
|
@ -102,6 +103,7 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
|
||||||
}
|
}
|
||||||
|
|
||||||
block->driver = qcrypto_block_drivers[options->format];
|
block->driver = qcrypto_block_drivers[options->format];
|
||||||
|
block->detached_header = flags & QCRYPTO_BLOCK_CREATE_DETACHED;
|
||||||
|
|
||||||
if (block->driver->create(block, options, optprefix, initfunc,
|
if (block->driver->create(block, options, optprefix, initfunc,
|
||||||
writefunc, opaque, errp) < 0) {
|
writefunc, opaque, errp) < 0) {
|
||||||
|
@ -146,7 +148,7 @@ qcrypto_block_calculate_payload_offset(QCryptoBlockCreateOptions *create_opts,
|
||||||
qcrypto_block_create(create_opts, optprefix,
|
qcrypto_block_create(create_opts, optprefix,
|
||||||
qcrypto_block_headerlen_hdr_init_func,
|
qcrypto_block_headerlen_hdr_init_func,
|
||||||
qcrypto_block_headerlen_hdr_write_func,
|
qcrypto_block_headerlen_hdr_write_func,
|
||||||
len, errp);
|
len, 0, errp);
|
||||||
return crypto != NULL;
|
return crypto != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@ struct QCryptoBlock {
|
||||||
size_t niv;
|
size_t niv;
|
||||||
uint64_t payload_offset; /* In bytes */
|
uint64_t payload_offset; /* In bytes */
|
||||||
uint64_t sector_size; /* In bytes */
|
uint64_t sector_size; /* In bytes */
|
||||||
|
|
||||||
|
bool detached_header; /* True if disk has a detached LUKS header */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QCryptoBlockDriver {
|
struct QCryptoBlockDriver {
|
||||||
|
|
|
@ -35,6 +35,9 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
|
||||||
case QCRYPTO_CIPHER_ALG_SERPENT_256:
|
case QCRYPTO_CIPHER_ALG_SERPENT_256:
|
||||||
case QCRYPTO_CIPHER_ALG_TWOFISH_128:
|
case QCRYPTO_CIPHER_ALG_TWOFISH_128:
|
||||||
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
|
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
|
||||||
|
#ifdef CONFIG_CRYPTO_SM4
|
||||||
|
case QCRYPTO_CIPHER_ALG_SM4:
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -219,6 +222,11 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||||
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
|
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
|
||||||
gcryalg = GCRY_CIPHER_TWOFISH;
|
gcryalg = GCRY_CIPHER_TWOFISH;
|
||||||
break;
|
break;
|
||||||
|
#ifdef CONFIG_CRYPTO_SM4
|
||||||
|
case QCRYPTO_CIPHER_ALG_SM4:
|
||||||
|
gcryalg = GCRY_CIPHER_SM4;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
error_setg(errp, "Unsupported cipher algorithm %s",
|
error_setg(errp, "Unsupported cipher algorithm %s",
|
||||||
QCryptoCipherAlgorithm_str(alg));
|
QCryptoCipherAlgorithm_str(alg));
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
#ifndef CONFIG_QEMU_PRIVATE_XTS
|
#ifndef CONFIG_QEMU_PRIVATE_XTS
|
||||||
#include <nettle/xts.h>
|
#include <nettle/xts.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_CRYPTO_SM4
|
||||||
|
#include <nettle/sm4.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline bool qcrypto_length_check(size_t len, size_t blocksize,
|
static inline bool qcrypto_length_check(size_t len, size_t blocksize,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
|
@ -426,6 +429,30 @@ DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_twofish,
|
||||||
QCryptoNettleTwofish, TWOFISH_BLOCK_SIZE,
|
QCryptoNettleTwofish, TWOFISH_BLOCK_SIZE,
|
||||||
twofish_encrypt_native, twofish_decrypt_native)
|
twofish_encrypt_native, twofish_decrypt_native)
|
||||||
|
|
||||||
|
#ifdef CONFIG_CRYPTO_SM4
|
||||||
|
typedef struct QCryptoNettleSm4 {
|
||||||
|
QCryptoCipher base;
|
||||||
|
struct sm4_ctx key[2];
|
||||||
|
} QCryptoNettleSm4;
|
||||||
|
|
||||||
|
static void sm4_encrypt_native(void *ctx, size_t length,
|
||||||
|
uint8_t *dst, const uint8_t *src)
|
||||||
|
{
|
||||||
|
struct sm4_ctx *keys = ctx;
|
||||||
|
sm4_crypt(&keys[0], length, dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sm4_decrypt_native(void *ctx, size_t length,
|
||||||
|
uint8_t *dst, const uint8_t *src)
|
||||||
|
{
|
||||||
|
struct sm4_ctx *keys = ctx;
|
||||||
|
sm4_crypt(&keys[1], length, dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ECB(qcrypto_nettle_sm4,
|
||||||
|
QCryptoNettleSm4, SM4_BLOCK_SIZE,
|
||||||
|
sm4_encrypt_native, sm4_decrypt_native)
|
||||||
|
#endif
|
||||||
|
|
||||||
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
|
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
|
||||||
QCryptoCipherMode mode)
|
QCryptoCipherMode mode)
|
||||||
|
@ -443,6 +470,9 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
|
||||||
case QCRYPTO_CIPHER_ALG_TWOFISH_128:
|
case QCRYPTO_CIPHER_ALG_TWOFISH_128:
|
||||||
case QCRYPTO_CIPHER_ALG_TWOFISH_192:
|
case QCRYPTO_CIPHER_ALG_TWOFISH_192:
|
||||||
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
|
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
|
||||||
|
#ifdef CONFIG_CRYPTO_SM4
|
||||||
|
case QCRYPTO_CIPHER_ALG_SM4:
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -701,6 +731,25 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||||
|
|
||||||
return &ctx->base;
|
return &ctx->base;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_CRYPTO_SM4
|
||||||
|
case QCRYPTO_CIPHER_ALG_SM4:
|
||||||
|
{
|
||||||
|
QCryptoNettleSm4 *ctx = g_new0(QCryptoNettleSm4, 1);
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case QCRYPTO_CIPHER_MODE_ECB:
|
||||||
|
ctx->base.driver = &qcrypto_nettle_sm4_driver_ecb;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto bad_cipher_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
sm4_set_encrypt_key(&ctx->key[0], key);
|
||||||
|
sm4_set_decrypt_key(&ctx->key[1], key);
|
||||||
|
|
||||||
|
return &ctx->base;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error_setg(errp, "Unsupported cipher algorithm %s",
|
error_setg(errp, "Unsupported cipher algorithm %s",
|
||||||
|
|
|
@ -38,6 +38,9 @@ static const size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
|
||||||
[QCRYPTO_CIPHER_ALG_TWOFISH_128] = 16,
|
[QCRYPTO_CIPHER_ALG_TWOFISH_128] = 16,
|
||||||
[QCRYPTO_CIPHER_ALG_TWOFISH_192] = 24,
|
[QCRYPTO_CIPHER_ALG_TWOFISH_192] = 24,
|
||||||
[QCRYPTO_CIPHER_ALG_TWOFISH_256] = 32,
|
[QCRYPTO_CIPHER_ALG_TWOFISH_256] = 32,
|
||||||
|
#ifdef CONFIG_CRYPTO_SM4
|
||||||
|
[QCRYPTO_CIPHER_ALG_SM4] = 16,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
|
static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
|
||||||
|
@ -53,6 +56,9 @@ static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
|
||||||
[QCRYPTO_CIPHER_ALG_TWOFISH_128] = 16,
|
[QCRYPTO_CIPHER_ALG_TWOFISH_128] = 16,
|
||||||
[QCRYPTO_CIPHER_ALG_TWOFISH_192] = 16,
|
[QCRYPTO_CIPHER_ALG_TWOFISH_192] = 16,
|
||||||
[QCRYPTO_CIPHER_ALG_TWOFISH_256] = 16,
|
[QCRYPTO_CIPHER_ALG_TWOFISH_256] = 16,
|
||||||
|
#ifdef CONFIG_CRYPTO_SM4
|
||||||
|
[QCRYPTO_CIPHER_ALG_SM4] = 16,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = {
|
static const bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = {
|
||||||
|
|
|
@ -8,27 +8,37 @@ Cascadelake-Server-v1,✅,✅,✅,✅
|
||||||
Cascadelake-Server-v2,✅,✅,✅,✅
|
Cascadelake-Server-v2,✅,✅,✅,✅
|
||||||
Cascadelake-Server-v3,✅,✅,✅,✅
|
Cascadelake-Server-v3,✅,✅,✅,✅
|
||||||
Cascadelake-Server-v4,✅,✅,✅,✅
|
Cascadelake-Server-v4,✅,✅,✅,✅
|
||||||
|
Cascadelake-Server-v5,✅,✅,✅,✅
|
||||||
Conroe-v1,✅,,,
|
Conroe-v1,✅,,,
|
||||||
Cooperlake-v1,✅,✅,✅,✅
|
Cooperlake-v1,✅,✅,✅,✅
|
||||||
|
Cooperlake-v2,✅,✅,✅,✅
|
||||||
Denverton-v1,✅,✅,,
|
Denverton-v1,✅,✅,,
|
||||||
Denverton-v2,✅,✅,,
|
Denverton-v2,✅,✅,,
|
||||||
|
Denverton-v3,✅,✅,,
|
||||||
Dhyana-v1,✅,✅,✅,
|
Dhyana-v1,✅,✅,✅,
|
||||||
|
Dhyana-v2,✅,✅,✅,
|
||||||
|
EPYC-Genoa-v1,✅,✅,✅,✅
|
||||||
EPYC-Milan-v1,✅,✅,✅,
|
EPYC-Milan-v1,✅,✅,✅,
|
||||||
|
EPYC-Milan-v2,✅,✅,✅,
|
||||||
EPYC-Rome-v1,✅,✅,✅,
|
EPYC-Rome-v1,✅,✅,✅,
|
||||||
EPYC-Rome-v2,✅,✅,✅,
|
EPYC-Rome-v2,✅,✅,✅,
|
||||||
|
EPYC-Rome-v3,✅,✅,✅,
|
||||||
|
EPYC-Rome-v4,✅,✅,✅,
|
||||||
EPYC-v1,✅,✅,✅,
|
EPYC-v1,✅,✅,✅,
|
||||||
EPYC-v2,✅,✅,✅,
|
EPYC-v2,✅,✅,✅,
|
||||||
EPYC-v3,✅,✅,✅,
|
EPYC-v3,✅,✅,✅,
|
||||||
|
EPYC-v4,✅,✅,✅,
|
||||||
|
GraniteRapids-v1,✅,✅,✅,✅
|
||||||
Haswell-v1,✅,✅,✅,
|
Haswell-v1,✅,✅,✅,
|
||||||
Haswell-v2,✅,✅,✅,
|
Haswell-v2,✅,✅,✅,
|
||||||
Haswell-v3,✅,✅,✅,
|
Haswell-v3,✅,✅,✅,
|
||||||
Haswell-v4,✅,✅,✅,
|
Haswell-v4,✅,✅,✅,
|
||||||
Icelake-Client-v1,✅,✅,✅,
|
|
||||||
Icelake-Client-v2,✅,✅,✅,
|
|
||||||
Icelake-Server-v1,✅,✅,✅,✅
|
Icelake-Server-v1,✅,✅,✅,✅
|
||||||
Icelake-Server-v2,✅,✅,✅,✅
|
Icelake-Server-v2,✅,✅,✅,✅
|
||||||
Icelake-Server-v3,✅,✅,✅,✅
|
Icelake-Server-v3,✅,✅,✅,✅
|
||||||
Icelake-Server-v4,✅,✅,✅,✅
|
Icelake-Server-v4,✅,✅,✅,✅
|
||||||
|
Icelake-Server-v5,✅,✅,✅,✅
|
||||||
|
Icelake-Server-v6,✅,✅,✅,✅
|
||||||
IvyBridge-v1,✅,✅,,
|
IvyBridge-v1,✅,✅,,
|
||||||
IvyBridge-v2,✅,✅,,
|
IvyBridge-v2,✅,✅,,
|
||||||
KnightsMill-v1,✅,✅,✅,
|
KnightsMill-v1,✅,✅,✅,
|
||||||
|
@ -42,15 +52,21 @@ Opteron_G5-v1,✅,✅,,
|
||||||
Penryn-v1,✅,,,
|
Penryn-v1,✅,,,
|
||||||
SandyBridge-v1,✅,✅,,
|
SandyBridge-v1,✅,✅,,
|
||||||
SandyBridge-v2,✅,✅,,
|
SandyBridge-v2,✅,✅,,
|
||||||
|
SapphireRapids-v1,✅,✅,✅,✅
|
||||||
|
SapphireRapids-v2,✅,✅,✅,✅
|
||||||
Skylake-Client-v1,✅,✅,✅,
|
Skylake-Client-v1,✅,✅,✅,
|
||||||
Skylake-Client-v2,✅,✅,✅,
|
Skylake-Client-v2,✅,✅,✅,
|
||||||
Skylake-Client-v3,✅,✅,✅,
|
Skylake-Client-v3,✅,✅,✅,
|
||||||
|
Skylake-Client-v4,✅,✅,✅,
|
||||||
Skylake-Server-v1,✅,✅,✅,✅
|
Skylake-Server-v1,✅,✅,✅,✅
|
||||||
Skylake-Server-v2,✅,✅,✅,✅
|
Skylake-Server-v2,✅,✅,✅,✅
|
||||||
Skylake-Server-v3,✅,✅,✅,✅
|
Skylake-Server-v3,✅,✅,✅,✅
|
||||||
Skylake-Server-v4,✅,✅,✅,✅
|
Skylake-Server-v4,✅,✅,✅,✅
|
||||||
|
Skylake-Server-v5,✅,✅,✅,✅
|
||||||
Snowridge-v1,✅,✅,,
|
Snowridge-v1,✅,✅,,
|
||||||
Snowridge-v2,✅,✅,,
|
Snowridge-v2,✅,✅,,
|
||||||
|
Snowridge-v3,✅,✅,,
|
||||||
|
Snowridge-v4,✅,✅,,
|
||||||
Westmere-v1,✅,✅,,
|
Westmere-v1,✅,✅,,
|
||||||
Westmere-v2,✅,✅,,
|
Westmere-v2,✅,✅,,
|
||||||
athlon-v1,,,,
|
athlon-v1,,,,
|
||||||
|
|
|
|
@ -58,7 +58,7 @@ depending on the machine type is in use.
|
||||||
.. csv-table:: x86-64 ABI compatibility levels
|
.. csv-table:: x86-64 ABI compatibility levels
|
||||||
:file: cpu-models-x86-abi.csv
|
:file: cpu-models-x86-abi.csv
|
||||||
:widths: 40,15,15,15,15
|
:widths: 40,15,15,15,15
|
||||||
:header-rows: 2
|
:header-rows: 1
|
||||||
|
|
||||||
|
|
||||||
Preferred CPU models for Intel x86 hosts
|
Preferred CPU models for Intel x86 hosts
|
||||||
|
|
|
@ -66,6 +66,7 @@ bool qcrypto_block_has_format(QCryptoBlockFormat format,
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
QCRYPTO_BLOCK_OPEN_NO_IO = (1 << 0),
|
QCRYPTO_BLOCK_OPEN_NO_IO = (1 << 0),
|
||||||
|
QCRYPTO_BLOCK_OPEN_DETACHED = (1 << 1),
|
||||||
} QCryptoBlockOpenFlags;
|
} QCryptoBlockOpenFlags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -95,6 +96,10 @@ typedef enum {
|
||||||
* metadata such as the payload offset. There will be
|
* metadata such as the payload offset. There will be
|
||||||
* no cipher or ivgen objects available.
|
* no cipher or ivgen objects available.
|
||||||
*
|
*
|
||||||
|
* If @flags contains QCRYPTO_BLOCK_OPEN_DETACHED then
|
||||||
|
* the open process will be optimized to skip the LUKS
|
||||||
|
* payload overlap check.
|
||||||
|
*
|
||||||
* If any part of initializing the encryption context
|
* If any part of initializing the encryption context
|
||||||
* fails an error will be returned. This could be due
|
* fails an error will be returned. This could be due
|
||||||
* to the volume being in the wrong format, a cipher
|
* to the volume being in the wrong format, a cipher
|
||||||
|
@ -111,6 +116,10 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
size_t n_threads,
|
size_t n_threads,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
QCRYPTO_BLOCK_CREATE_DETACHED = (1 << 0),
|
||||||
|
} QCryptoBlockCreateFlags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qcrypto_block_create:
|
* qcrypto_block_create:
|
||||||
* @options: the encryption options
|
* @options: the encryption options
|
||||||
|
@ -118,6 +127,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
* @initfunc: callback for initializing volume header
|
* @initfunc: callback for initializing volume header
|
||||||
* @writefunc: callback for writing data to the volume header
|
* @writefunc: callback for writing data to the volume header
|
||||||
* @opaque: data to pass to @initfunc and @writefunc
|
* @opaque: data to pass to @initfunc and @writefunc
|
||||||
|
* @flags: bitmask of QCryptoBlockCreateFlags values
|
||||||
* @errp: pointer to a NULL-initialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Create a new block encryption object for initializing
|
* Create a new block encryption object for initializing
|
||||||
|
@ -129,6 +139,11 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
* generating new master keys, etc as required. Any existing
|
* generating new master keys, etc as required. Any existing
|
||||||
* data present on the volume will be irrevocably destroyed.
|
* data present on the volume will be irrevocably destroyed.
|
||||||
*
|
*
|
||||||
|
* If @flags contains QCRYPTO_BLOCK_CREATE_DETACHED then
|
||||||
|
* the open process will set the payload_offset_sector to 0
|
||||||
|
* to specify the starting point for the read/write of a
|
||||||
|
* detached LUKS header image.
|
||||||
|
*
|
||||||
* If any part of initializing the encryption context
|
* If any part of initializing the encryption context
|
||||||
* fails an error will be returned. This could be due
|
* fails an error will be returned. This could be due
|
||||||
* to the volume being in the wrong format, a cipher
|
* to the volume being in the wrong format, a cipher
|
||||||
|
@ -142,6 +157,7 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
|
||||||
QCryptoBlockInitFunc initfunc,
|
QCryptoBlockInitFunc initfunc,
|
||||||
QCryptoBlockWriteFunc writefunc,
|
QCryptoBlockWriteFunc writefunc,
|
||||||
void *opaque,
|
void *opaque,
|
||||||
|
unsigned int flags,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -51,6 +51,7 @@ bool is_daemonized(void);
|
||||||
void os_daemonize(void);
|
void os_daemonize(void);
|
||||||
bool os_set_runas(const char *user_id);
|
bool os_set_runas(const char *user_id);
|
||||||
void os_set_chroot(const char *path);
|
void os_set_chroot(const char *path);
|
||||||
|
void os_setup_limits(void);
|
||||||
void os_setup_post(void);
|
void os_setup_post(void);
|
||||||
int os_mlock(void);
|
int os_mlock(void);
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,11 @@ static inline int os_mlock(void)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void os_setup_limits(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#define fsync _commit
|
#define fsync _commit
|
||||||
|
|
||||||
#if !defined(lseek)
|
#if !defined(lseek)
|
||||||
|
|
|
@ -381,6 +381,7 @@ static int qio_channel_tls_close(QIOChannel *ioc,
|
||||||
QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
|
QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
|
||||||
|
|
||||||
if (tioc->hs_ioc_tag) {
|
if (tioc->hs_ioc_tag) {
|
||||||
|
trace_qio_channel_tls_handshake_cancel(ioc);
|
||||||
g_clear_handle_id(&tioc->hs_ioc_tag, g_source_remove);
|
g_clear_handle_id(&tioc->hs_ioc_tag, g_source_remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ qio_channel_tls_handshake_start(void *ioc) "TLS handshake start ioc=%p"
|
||||||
qio_channel_tls_handshake_pending(void *ioc, int status) "TLS handshake pending ioc=%p status=%d"
|
qio_channel_tls_handshake_pending(void *ioc, int status) "TLS handshake pending ioc=%p status=%d"
|
||||||
qio_channel_tls_handshake_fail(void *ioc) "TLS handshake fail ioc=%p"
|
qio_channel_tls_handshake_fail(void *ioc) "TLS handshake fail ioc=%p"
|
||||||
qio_channel_tls_handshake_complete(void *ioc) "TLS handshake complete ioc=%p"
|
qio_channel_tls_handshake_complete(void *ioc) "TLS handshake complete ioc=%p"
|
||||||
|
qio_channel_tls_handshake_cancel(void *ioc) "TLS handshake cancel ioc=%p"
|
||||||
qio_channel_tls_credentials_allow(void *ioc) "TLS credentials allow ioc=%p"
|
qio_channel_tls_credentials_allow(void *ioc) "TLS credentials allow ioc=%p"
|
||||||
qio_channel_tls_credentials_deny(void *ioc) "TLS credentials deny ioc=%p"
|
qio_channel_tls_credentials_deny(void *ioc) "TLS credentials deny ioc=%p"
|
||||||
|
|
||||||
|
|
66
meson.build
66
meson.build
|
@ -571,36 +571,38 @@ qemu_common_flags += cc.get_supported_arguments(hardening_flags)
|
||||||
add_global_arguments(qemu_common_flags, native: false, language: all_languages)
|
add_global_arguments(qemu_common_flags, native: false, language: all_languages)
|
||||||
add_global_link_arguments(qemu_ldflags, native: false, language: all_languages)
|
add_global_link_arguments(qemu_ldflags, native: false, language: all_languages)
|
||||||
|
|
||||||
# Collect warnings that we want to enable
|
# Collect warning flags we want to set, sorted alphabetically
|
||||||
|
|
||||||
warn_flags = [
|
warn_flags = [
|
||||||
'-Wundef',
|
# First enable interesting warnings
|
||||||
'-Wwrite-strings',
|
|
||||||
'-Wmissing-prototypes',
|
|
||||||
'-Wstrict-prototypes',
|
|
||||||
'-Wredundant-decls',
|
|
||||||
'-Wold-style-declaration',
|
|
||||||
'-Wold-style-definition',
|
|
||||||
'-Wtype-limits',
|
|
||||||
'-Wformat-security',
|
|
||||||
'-Wformat-y2k',
|
|
||||||
'-Winit-self',
|
|
||||||
'-Wignored-qualifiers',
|
|
||||||
'-Wempty-body',
|
'-Wempty-body',
|
||||||
'-Wnested-externs',
|
|
||||||
'-Wendif-labels',
|
'-Wendif-labels',
|
||||||
'-Wexpansion-to-defined',
|
'-Wexpansion-to-defined',
|
||||||
|
'-Wformat-security',
|
||||||
|
'-Wformat-y2k',
|
||||||
|
'-Wignored-qualifiers',
|
||||||
'-Wimplicit-fallthrough=2',
|
'-Wimplicit-fallthrough=2',
|
||||||
|
'-Winit-self',
|
||||||
'-Wmissing-format-attribute',
|
'-Wmissing-format-attribute',
|
||||||
|
'-Wmissing-prototypes',
|
||||||
|
'-Wnested-externs',
|
||||||
|
'-Wold-style-declaration',
|
||||||
|
'-Wold-style-definition',
|
||||||
|
'-Wredundant-decls',
|
||||||
|
'-Wshadow=local',
|
||||||
|
'-Wstrict-prototypes',
|
||||||
|
'-Wtype-limits',
|
||||||
|
'-Wundef',
|
||||||
|
'-Wwrite-strings',
|
||||||
|
|
||||||
|
# Then disable some undesirable warnings
|
||||||
|
'-Wno-gnu-variable-sized-type-not-at-end',
|
||||||
'-Wno-initializer-overrides',
|
'-Wno-initializer-overrides',
|
||||||
'-Wno-missing-include-dirs',
|
'-Wno-missing-include-dirs',
|
||||||
|
'-Wno-psabi',
|
||||||
'-Wno-shift-negative-value',
|
'-Wno-shift-negative-value',
|
||||||
'-Wno-string-plus-int',
|
'-Wno-string-plus-int',
|
||||||
'-Wno-typedef-redefinition',
|
|
||||||
'-Wno-tautological-type-limit-compare',
|
'-Wno-tautological-type-limit-compare',
|
||||||
'-Wno-psabi',
|
'-Wno-typedef-redefinition',
|
||||||
'-Wno-gnu-variable-sized-type-not-at-end',
|
|
||||||
'-Wshadow=local',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
if host_os != 'darwin'
|
if host_os != 'darwin'
|
||||||
|
@ -1631,6 +1633,7 @@ endif
|
||||||
gcrypt = not_found
|
gcrypt = not_found
|
||||||
nettle = not_found
|
nettle = not_found
|
||||||
hogweed = not_found
|
hogweed = not_found
|
||||||
|
crypto_sm4 = not_found
|
||||||
xts = 'none'
|
xts = 'none'
|
||||||
|
|
||||||
if get_option('nettle').enabled() and get_option('gcrypt').enabled()
|
if get_option('nettle').enabled() and get_option('gcrypt').enabled()
|
||||||
|
@ -1656,6 +1659,17 @@ if not gnutls_crypto.found()
|
||||||
cc.find_library('gpg-error', required: true)],
|
cc.find_library('gpg-error', required: true)],
|
||||||
version: gcrypt.version())
|
version: gcrypt.version())
|
||||||
endif
|
endif
|
||||||
|
crypto_sm4 = gcrypt
|
||||||
|
# SM4 ALG is available in libgcrypt >= 1.9
|
||||||
|
if gcrypt.found() and not cc.links('''
|
||||||
|
#include <gcrypt.h>
|
||||||
|
int main(void) {
|
||||||
|
gcry_cipher_hd_t handler;
|
||||||
|
gcry_cipher_open(&handler, GCRY_CIPHER_SM4, GCRY_CIPHER_MODE_ECB, 0);
|
||||||
|
return 0;
|
||||||
|
}''', dependencies: gcrypt)
|
||||||
|
crypto_sm4 = not_found
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
|
if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
|
||||||
nettle = dependency('nettle', version: '>=3.4',
|
nettle = dependency('nettle', version: '>=3.4',
|
||||||
|
@ -1664,6 +1678,18 @@ if not gnutls_crypto.found()
|
||||||
if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle)
|
if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle)
|
||||||
xts = 'private'
|
xts = 'private'
|
||||||
endif
|
endif
|
||||||
|
crypto_sm4 = nettle
|
||||||
|
# SM4 ALG is available in nettle >= 3.9
|
||||||
|
if nettle.found() and not cc.links('''
|
||||||
|
#include <nettle/sm4.h>
|
||||||
|
int main(void) {
|
||||||
|
struct sm4_ctx ctx;
|
||||||
|
unsigned char key[16] = {0};
|
||||||
|
sm4_set_encrypt_key(&ctx, key);
|
||||||
|
return 0;
|
||||||
|
}''', dependencies: nettle)
|
||||||
|
crypto_sm4 = not_found
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -2265,6 +2291,7 @@ config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
|
||||||
config_host_data.set('CONFIG_TASN1', tasn1.found())
|
config_host_data.set('CONFIG_TASN1', tasn1.found())
|
||||||
config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
|
config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
|
||||||
config_host_data.set('CONFIG_NETTLE', nettle.found())
|
config_host_data.set('CONFIG_NETTLE', nettle.found())
|
||||||
|
config_host_data.set('CONFIG_CRYPTO_SM4', crypto_sm4.found())
|
||||||
config_host_data.set('CONFIG_HOGWEED', hogweed.found())
|
config_host_data.set('CONFIG_HOGWEED', hogweed.found())
|
||||||
config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
|
config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
|
||||||
config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
|
config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
|
||||||
|
@ -4304,6 +4331,7 @@ summary_info += {'nettle': nettle}
|
||||||
if nettle.found()
|
if nettle.found()
|
||||||
summary_info += {' XTS': xts != 'private'}
|
summary_info += {' XTS': xts != 'private'}
|
||||||
endif
|
endif
|
||||||
|
summary_info += {'SM4 ALG support': crypto_sm4}
|
||||||
summary_info += {'AF_ALG support': have_afalg}
|
summary_info += {'AF_ALG support': have_afalg}
|
||||||
summary_info += {'rng-none': get_option('rng_none')}
|
summary_info += {'rng-none': get_option('rng_none')}
|
||||||
summary_info += {'Linux keyring': have_keyring}
|
summary_info += {'Linux keyring': have_keyring}
|
||||||
|
|
22
os-posix.c
22
os-posix.c
|
@ -24,6 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
@ -256,6 +257,27 @@ void os_daemonize(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void os_setup_limits(void)
|
||||||
|
{
|
||||||
|
struct rlimit nofile;
|
||||||
|
|
||||||
|
if (getrlimit(RLIMIT_NOFILE, &nofile) < 0) {
|
||||||
|
warn_report("unable to query NOFILE limit: %s", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nofile.rlim_cur == nofile.rlim_max) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nofile.rlim_cur = nofile.rlim_max;
|
||||||
|
|
||||||
|
if (setrlimit(RLIMIT_NOFILE, &nofile) < 0) {
|
||||||
|
warn_report("unable to set NOFILE limit: %s", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void os_setup_post(void)
|
void os_setup_post(void)
|
||||||
{
|
{
|
||||||
int fd = 0;
|
int fd = 0;
|
||||||
|
|
|
@ -3365,11 +3365,14 @@
|
||||||
# decryption key (since 2.6). Mandatory except when doing a
|
# decryption key (since 2.6). Mandatory except when doing a
|
||||||
# metadata-only probe of the image.
|
# metadata-only probe of the image.
|
||||||
#
|
#
|
||||||
|
# @header: block device holding a detached LUKS header. (since 9.0)
|
||||||
|
#
|
||||||
# Since: 2.9
|
# Since: 2.9
|
||||||
##
|
##
|
||||||
{ 'struct': 'BlockdevOptionsLUKS',
|
{ 'struct': 'BlockdevOptionsLUKS',
|
||||||
'base': 'BlockdevOptionsGenericFormat',
|
'base': 'BlockdevOptionsGenericFormat',
|
||||||
'data': { '*key-secret': 'str' } }
|
'data': { '*key-secret': 'str',
|
||||||
|
'*header': 'BlockdevRef'} }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @BlockdevOptionsGenericCOWFormat:
|
# @BlockdevOptionsGenericCOWFormat:
|
||||||
|
@ -4952,7 +4955,10 @@
|
||||||
#
|
#
|
||||||
# Driver specific image creation options for LUKS.
|
# Driver specific image creation options for LUKS.
|
||||||
#
|
#
|
||||||
# @file: Node to create the image format on
|
# @file: Node to create the image format on, mandatory except when
|
||||||
|
# 'preallocation' is not requested
|
||||||
|
#
|
||||||
|
# @header: Block device holding a detached LUKS header. (since 9.0)
|
||||||
#
|
#
|
||||||
# @size: Size of the virtual disk in bytes
|
# @size: Size of the virtual disk in bytes
|
||||||
#
|
#
|
||||||
|
@ -4963,7 +4969,8 @@
|
||||||
##
|
##
|
||||||
{ 'struct': 'BlockdevCreateOptionsLUKS',
|
{ 'struct': 'BlockdevCreateOptionsLUKS',
|
||||||
'base': 'QCryptoBlockCreateOptionsLUKS',
|
'base': 'QCryptoBlockCreateOptionsLUKS',
|
||||||
'data': { 'file': 'BlockdevRef',
|
'data': { '*file': 'BlockdevRef',
|
||||||
|
'*header': 'BlockdevRef',
|
||||||
'size': 'size',
|
'size': 'size',
|
||||||
'*preallocation': 'PreallocMode' } }
|
'*preallocation': 'PreallocMode' } }
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,8 @@
|
||||||
#
|
#
|
||||||
# @twofish-256: Twofish with 256 bit / 32 byte keys
|
# @twofish-256: Twofish with 256 bit / 32 byte keys
|
||||||
#
|
#
|
||||||
|
# @sm4: SM4 with 128 bit / 16 byte keys (since 9.0)
|
||||||
|
#
|
||||||
# Since: 2.6
|
# Since: 2.6
|
||||||
##
|
##
|
||||||
{ 'enum': 'QCryptoCipherAlgorithm',
|
{ 'enum': 'QCryptoCipherAlgorithm',
|
||||||
|
@ -102,7 +104,8 @@
|
||||||
'des', '3des',
|
'des', '3des',
|
||||||
'cast5-128',
|
'cast5-128',
|
||||||
'serpent-128', 'serpent-192', 'serpent-256',
|
'serpent-128', 'serpent-192', 'serpent-256',
|
||||||
'twofish-128', 'twofish-192', 'twofish-256']}
|
'twofish-128', 'twofish-192', 'twofish-256',
|
||||||
|
'sm4']}
|
||||||
|
|
||||||
##
|
##
|
||||||
# @QCryptoCipherMode:
|
# @QCryptoCipherMode:
|
||||||
|
@ -223,6 +226,8 @@
|
||||||
# @iter-time: number of milliseconds to spend in PBKDF passphrase
|
# @iter-time: number of milliseconds to spend in PBKDF passphrase
|
||||||
# processing. Currently defaults to 2000. (since 2.8)
|
# processing. Currently defaults to 2000. (since 2.8)
|
||||||
#
|
#
|
||||||
|
# @detached-header: create a detached LUKS header. (since 9.0)
|
||||||
|
#
|
||||||
# Since: 2.6
|
# Since: 2.6
|
||||||
##
|
##
|
||||||
{ 'struct': 'QCryptoBlockCreateOptionsLUKS',
|
{ 'struct': 'QCryptoBlockCreateOptionsLUKS',
|
||||||
|
@ -232,7 +237,8 @@
|
||||||
'*ivgen-alg': 'QCryptoIVGenAlgorithm',
|
'*ivgen-alg': 'QCryptoIVGenAlgorithm',
|
||||||
'*ivgen-hash-alg': 'QCryptoHashAlgorithm',
|
'*ivgen-hash-alg': 'QCryptoHashAlgorithm',
|
||||||
'*hash-alg': 'QCryptoHashAlgorithm',
|
'*hash-alg': 'QCryptoHashAlgorithm',
|
||||||
'*iter-time': 'int'}}
|
'*iter-time': 'int',
|
||||||
|
'*detached-header': 'bool'}}
|
||||||
|
|
||||||
##
|
##
|
||||||
# @QCryptoBlockOpenOptions:
|
# @QCryptoBlockOpenOptions:
|
||||||
|
@ -311,6 +317,8 @@
|
||||||
#
|
#
|
||||||
# @hash-alg: the master key hash algorithm
|
# @hash-alg: the master key hash algorithm
|
||||||
#
|
#
|
||||||
|
# @detached-header: whether the LUKS header is detached (Since 9.0)
|
||||||
|
#
|
||||||
# @payload-offset: offset to the payload data in bytes
|
# @payload-offset: offset to the payload data in bytes
|
||||||
#
|
#
|
||||||
# @master-key-iters: number of PBKDF2 iterations for key material
|
# @master-key-iters: number of PBKDF2 iterations for key material
|
||||||
|
@ -327,6 +335,7 @@
|
||||||
'ivgen-alg': 'QCryptoIVGenAlgorithm',
|
'ivgen-alg': 'QCryptoIVGenAlgorithm',
|
||||||
'*ivgen-hash-alg': 'QCryptoHashAlgorithm',
|
'*ivgen-hash-alg': 'QCryptoHashAlgorithm',
|
||||||
'hash-alg': 'QCryptoHashAlgorithm',
|
'hash-alg': 'QCryptoHashAlgorithm',
|
||||||
|
'detached-header': 'bool',
|
||||||
'payload-offset': 'int',
|
'payload-offset': 'int',
|
||||||
'master-key-iters': 'int',
|
'master-key-iters': 'int',
|
||||||
'uuid': 'str',
|
'uuid': 'str',
|
||||||
|
|
|
@ -179,7 +179,6 @@ for level in range(len(abi_models)):
|
||||||
models[name]["delta"][level] = delta
|
models[name]["delta"][level] = delta
|
||||||
|
|
||||||
def print_uarch_abi_csv():
|
def print_uarch_abi_csv():
|
||||||
print("# Automatically generated from '%s'" % __file__)
|
|
||||||
print("Model,baseline,v2,v3,v4")
|
print("Model,baseline,v2,v3,v4")
|
||||||
for name in models.keys():
|
for name in models.keys():
|
||||||
print(name, end="")
|
print(name, end="")
|
||||||
|
|
|
@ -1914,7 +1914,6 @@ static bool object_create_early(const char *type)
|
||||||
* Allocation of large amounts of memory may delay
|
* Allocation of large amounts of memory may delay
|
||||||
* chardev initialization for too long, and trigger timeouts
|
* chardev initialization for too long, and trigger timeouts
|
||||||
* on software that waits for a monitor socket to be created
|
* on software that waits for a monitor socket to be created
|
||||||
* (e.g. libvirt).
|
|
||||||
*/
|
*/
|
||||||
if (g_str_has_prefix(type, "memory-backend-")) {
|
if (g_str_has_prefix(type, "memory-backend-")) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -2778,6 +2777,8 @@ void qemu_init(int argc, char **argv)
|
||||||
error_init(argv[0]);
|
error_init(argv[0]);
|
||||||
qemu_init_exec_dir(argv[0]);
|
qemu_init_exec_dir(argv[0]);
|
||||||
|
|
||||||
|
os_setup_limits();
|
||||||
|
|
||||||
qemu_init_arch_modules();
|
qemu_init_arch_modules();
|
||||||
|
|
||||||
qemu_init_subsystems();
|
qemu_init_subsystems();
|
||||||
|
|
|
@ -18,6 +18,7 @@ virtual size: 128 MiB (134217728 bytes)
|
||||||
encrypted: yes
|
encrypted: yes
|
||||||
Format specific information:
|
Format specific information:
|
||||||
ivgen alg: plain64
|
ivgen alg: plain64
|
||||||
|
detached header: false
|
||||||
hash alg: sha256
|
hash alg: sha256
|
||||||
cipher alg: aes-256
|
cipher alg: aes-256
|
||||||
uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||||
|
@ -70,6 +71,7 @@ virtual size: 64 MiB (67108864 bytes)
|
||||||
encrypted: yes
|
encrypted: yes
|
||||||
Format specific information:
|
Format specific information:
|
||||||
ivgen alg: plain64
|
ivgen alg: plain64
|
||||||
|
detached header: false
|
||||||
hash alg: sha1
|
hash alg: sha1
|
||||||
cipher alg: aes-128
|
cipher alg: aes-128
|
||||||
uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||||
|
@ -125,6 +127,7 @@ virtual size: 0 B (0 bytes)
|
||||||
encrypted: yes
|
encrypted: yes
|
||||||
Format specific information:
|
Format specific information:
|
||||||
ivgen alg: plain64
|
ivgen alg: plain64
|
||||||
|
detached header: false
|
||||||
hash alg: sha256
|
hash alg: sha256
|
||||||
cipher alg: aes-256
|
cipher alg: aes-256
|
||||||
uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||||
|
@ -195,6 +198,7 @@ virtual size: 0 B (0 bytes)
|
||||||
encrypted: yes
|
encrypted: yes
|
||||||
Format specific information:
|
Format specific information:
|
||||||
ivgen alg: plain64
|
ivgen alg: plain64
|
||||||
|
detached header: false
|
||||||
hash alg: sha256
|
hash alg: sha256
|
||||||
cipher alg: aes-256
|
cipher alg: aes-256
|
||||||
uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||||
|
|
|
@ -0,0 +1,316 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# group: rw auto
|
||||||
|
#
|
||||||
|
# Test LUKS volume with detached header
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024 SmartX Inc.
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# Hyman Huang <yong.huang@smartx.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import iotests
|
||||||
|
from iotests import (
|
||||||
|
imgfmt,
|
||||||
|
qemu_img_create,
|
||||||
|
qemu_img_info,
|
||||||
|
QMPTestCase,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
image_size = 128 * 1024 * 1024
|
||||||
|
|
||||||
|
luks_img = os.path.join(iotests.test_dir, "luks.img")
|
||||||
|
detached_header_img1 = os.path.join(iotests.test_dir, "detached_header.img1")
|
||||||
|
detached_header_img2 = os.path.join(iotests.test_dir, "detached_header.img2")
|
||||||
|
detached_payload_raw_img = os.path.join(
|
||||||
|
iotests.test_dir, "detached_payload_raw.img"
|
||||||
|
)
|
||||||
|
detached_payload_qcow2_img = os.path.join(
|
||||||
|
iotests.test_dir, "detached_payload_qcow2.img"
|
||||||
|
)
|
||||||
|
detached_header_raw_img = "json:" + json.dumps(
|
||||||
|
{
|
||||||
|
"driver": "luks",
|
||||||
|
"file": {"filename": detached_payload_raw_img},
|
||||||
|
"header": {
|
||||||
|
"filename": detached_header_img1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
detached_header_qcow2_img = "json:" + json.dumps(
|
||||||
|
{
|
||||||
|
"driver": "luks",
|
||||||
|
"file": {"filename": detached_payload_qcow2_img},
|
||||||
|
"header": {"filename": detached_header_img2},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
secret_obj = "secret,id=sec0,data=foo"
|
||||||
|
luks_opts = "key-secret=sec0"
|
||||||
|
|
||||||
|
|
||||||
|
class TestDetachedLUKSHeader(QMPTestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
self.vm = iotests.VM()
|
||||||
|
self.vm.add_object(secret_obj)
|
||||||
|
self.vm.launch()
|
||||||
|
|
||||||
|
# 1. Create the normal LUKS disk with 128M size
|
||||||
|
self.vm.blockdev_create(
|
||||||
|
{"driver": "file", "filename": luks_img, "size": 0}
|
||||||
|
)
|
||||||
|
self.vm.qmp_log(
|
||||||
|
"blockdev-add",
|
||||||
|
driver="file",
|
||||||
|
filename=luks_img,
|
||||||
|
node_name="luks-1-storage",
|
||||||
|
)
|
||||||
|
result = self.vm.blockdev_create(
|
||||||
|
{
|
||||||
|
"driver": imgfmt,
|
||||||
|
"file": "luks-1-storage",
|
||||||
|
"key-secret": "sec0",
|
||||||
|
"size": image_size,
|
||||||
|
"iter-time": 10,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# None is expected
|
||||||
|
self.assertEqual(result, None)
|
||||||
|
|
||||||
|
# 2. Create the LUKS disk with detached header (raw)
|
||||||
|
|
||||||
|
# Create detached LUKS header
|
||||||
|
self.vm.blockdev_create(
|
||||||
|
{"driver": "file", "filename": detached_header_img1, "size": 0}
|
||||||
|
)
|
||||||
|
self.vm.qmp_log(
|
||||||
|
"blockdev-add",
|
||||||
|
driver="file",
|
||||||
|
filename=detached_header_img1,
|
||||||
|
node_name="luks-2-header-storage",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create detached LUKS raw payload
|
||||||
|
self.vm.blockdev_create(
|
||||||
|
{"driver": "file", "filename": detached_payload_raw_img, "size": 0}
|
||||||
|
)
|
||||||
|
self.vm.qmp_log(
|
||||||
|
"blockdev-add",
|
||||||
|
driver="file",
|
||||||
|
filename=detached_payload_raw_img,
|
||||||
|
node_name="luks-2-payload-storage",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Format LUKS disk with detached header
|
||||||
|
result = self.vm.blockdev_create(
|
||||||
|
{
|
||||||
|
"driver": imgfmt,
|
||||||
|
"header": "luks-2-header-storage",
|
||||||
|
"file": "luks-2-payload-storage",
|
||||||
|
"key-secret": "sec0",
|
||||||
|
"preallocation": "full",
|
||||||
|
"size": image_size,
|
||||||
|
"iter-time": 10,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assertEqual(result, None)
|
||||||
|
|
||||||
|
self.vm.shutdown()
|
||||||
|
|
||||||
|
# 3. Create the LUKS disk with detached header (qcow2)
|
||||||
|
|
||||||
|
# Create detached LUKS header using qemu-img
|
||||||
|
res = qemu_img_create(
|
||||||
|
"-f",
|
||||||
|
"luks",
|
||||||
|
"--object",
|
||||||
|
secret_obj,
|
||||||
|
"-o",
|
||||||
|
luks_opts,
|
||||||
|
"-o",
|
||||||
|
"detached-header=true",
|
||||||
|
detached_header_img2,
|
||||||
|
)
|
||||||
|
assert res.returncode == 0
|
||||||
|
|
||||||
|
# Create detached LUKS qcow2 payload
|
||||||
|
res = qemu_img_create(
|
||||||
|
"-f", "qcow2", detached_payload_qcow2_img, str(image_size)
|
||||||
|
)
|
||||||
|
assert res.returncode == 0
|
||||||
|
|
||||||
|
def tearDown(self) -> None:
|
||||||
|
os.remove(luks_img)
|
||||||
|
os.remove(detached_header_img1)
|
||||||
|
os.remove(detached_header_img2)
|
||||||
|
os.remove(detached_payload_raw_img)
|
||||||
|
os.remove(detached_payload_qcow2_img)
|
||||||
|
|
||||||
|
# Check if there was any qemu-io run that failed
|
||||||
|
if "Pattern verification failed" in self.vm.get_log():
|
||||||
|
print("ERROR: Pattern verification failed:")
|
||||||
|
print(self.vm.get_log())
|
||||||
|
self.fail("qemu-io pattern verification failed")
|
||||||
|
|
||||||
|
def test_img_creation(self) -> None:
|
||||||
|
# Check if the images created above are expected
|
||||||
|
|
||||||
|
data = qemu_img_info(luks_img)["format-specific"]
|
||||||
|
self.assertEqual(data["type"], imgfmt)
|
||||||
|
self.assertEqual(data["data"]["detached-header"], False)
|
||||||
|
|
||||||
|
data = qemu_img_info(detached_header_raw_img)["format-specific"]
|
||||||
|
self.assertEqual(data["type"], imgfmt)
|
||||||
|
self.assertEqual(data["data"]["detached-header"], True)
|
||||||
|
|
||||||
|
data = qemu_img_info(detached_header_qcow2_img)["format-specific"]
|
||||||
|
self.assertEqual(data["type"], imgfmt)
|
||||||
|
self.assertEqual(data["data"]["detached-header"], True)
|
||||||
|
|
||||||
|
# Check if preallocation works
|
||||||
|
size = qemu_img_info(detached_payload_raw_img)["actual-size"]
|
||||||
|
self.assertGreaterEqual(size, image_size)
|
||||||
|
|
||||||
|
def test_detached_luks_header(self) -> None:
|
||||||
|
self.vm.launch()
|
||||||
|
|
||||||
|
# 1. Add the disk created above
|
||||||
|
|
||||||
|
# Add normal LUKS disk
|
||||||
|
self.vm.qmp_log(
|
||||||
|
"blockdev-add",
|
||||||
|
driver="file",
|
||||||
|
filename=luks_img,
|
||||||
|
node_name="luks-1-storage",
|
||||||
|
)
|
||||||
|
result = self.vm.qmp_log(
|
||||||
|
"blockdev-add",
|
||||||
|
driver="luks",
|
||||||
|
file="luks-1-storage",
|
||||||
|
key_secret="sec0",
|
||||||
|
node_name="luks-1-format",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Expected result{ "return": {} }
|
||||||
|
self.assert_qmp(result, "return", {})
|
||||||
|
|
||||||
|
# Add detached LUKS header with raw payload
|
||||||
|
self.vm.qmp_log(
|
||||||
|
"blockdev-add",
|
||||||
|
driver="file",
|
||||||
|
filename=detached_header_img1,
|
||||||
|
node_name="luks-header1-storage",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.vm.qmp_log(
|
||||||
|
"blockdev-add",
|
||||||
|
driver="file",
|
||||||
|
filename=detached_payload_raw_img,
|
||||||
|
node_name="luks-2-payload-raw-storage",
|
||||||
|
)
|
||||||
|
|
||||||
|
result = self.vm.qmp_log(
|
||||||
|
"blockdev-add",
|
||||||
|
driver=imgfmt,
|
||||||
|
header="luks-header1-storage",
|
||||||
|
file="luks-2-payload-raw-storage",
|
||||||
|
key_secret="sec0",
|
||||||
|
node_name="luks-2-payload-raw-format",
|
||||||
|
)
|
||||||
|
self.assert_qmp(result, "return", {})
|
||||||
|
|
||||||
|
# Add detached LUKS header with qcow2 payload
|
||||||
|
self.vm.qmp_log(
|
||||||
|
"blockdev-add",
|
||||||
|
driver="file",
|
||||||
|
filename=detached_header_img2,
|
||||||
|
node_name="luks-header2-storage",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.vm.qmp_log(
|
||||||
|
"blockdev-add",
|
||||||
|
driver="file",
|
||||||
|
filename=detached_payload_qcow2_img,
|
||||||
|
node_name="luks-3-payload-qcow2-storage",
|
||||||
|
)
|
||||||
|
|
||||||
|
result = self.vm.qmp_log(
|
||||||
|
"blockdev-add",
|
||||||
|
driver=imgfmt,
|
||||||
|
header="luks-header2-storage",
|
||||||
|
file="luks-3-payload-qcow2-storage",
|
||||||
|
key_secret="sec0",
|
||||||
|
node_name="luks-3-payload-qcow2-format",
|
||||||
|
)
|
||||||
|
self.assert_qmp(result, "return", {})
|
||||||
|
|
||||||
|
# 2. Do I/O test
|
||||||
|
|
||||||
|
# Do some I/O to the image to see whether it still works
|
||||||
|
# (Pattern verification will be checked by tearDown())
|
||||||
|
|
||||||
|
# Normal LUKS disk
|
||||||
|
result = self.vm.qmp_log(
|
||||||
|
"human-monitor-command",
|
||||||
|
command_line='qemu-io luks-1-format "write -P 40 0 64k"',
|
||||||
|
)
|
||||||
|
self.assert_qmp(result, "return", "")
|
||||||
|
|
||||||
|
result = self.vm.qmp_log(
|
||||||
|
"human-monitor-command",
|
||||||
|
command_line='qemu-io luks-1-format "read -P 40 0 64k"',
|
||||||
|
)
|
||||||
|
self.assert_qmp(result, "return", "")
|
||||||
|
|
||||||
|
# Detached LUKS header with raw payload
|
||||||
|
cmd = 'qemu-io luks-2-payload-raw-format "write -P 41 0 64k"'
|
||||||
|
result = self.vm.qmp(
|
||||||
|
"human-monitor-command",
|
||||||
|
command_line=cmd
|
||||||
|
)
|
||||||
|
self.assert_qmp(result, "return", "")
|
||||||
|
|
||||||
|
cmd = 'qemu-io luks-2-payload-raw-format "read -P 41 0 64k"'
|
||||||
|
result = self.vm.qmp(
|
||||||
|
"human-monitor-command",
|
||||||
|
command_line=cmd
|
||||||
|
)
|
||||||
|
self.assert_qmp(result, "return", "")
|
||||||
|
|
||||||
|
# Detached LUKS header with qcow2 payload
|
||||||
|
cmd = 'qemu-io luks-3-payload-qcow2-format "write -P 42 0 64k"'
|
||||||
|
result = self.vm.qmp(
|
||||||
|
"human-monitor-command",
|
||||||
|
command_line=cmd
|
||||||
|
)
|
||||||
|
self.assert_qmp(result, "return", "")
|
||||||
|
|
||||||
|
cmd = 'qemu-io luks-3-payload-qcow2-format "read -P 42 0 64k"'
|
||||||
|
result = self.vm.qmp(
|
||||||
|
"human-monitor-command",
|
||||||
|
command_line=cmd
|
||||||
|
)
|
||||||
|
self.assert_qmp(result, "return", "")
|
||||||
|
|
||||||
|
self.vm.shutdown()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Test image creation and I/O
|
||||||
|
iotests.main(supported_fmts=["luks"], supported_protocols=["file"])
|
|
@ -0,0 +1,5 @@
|
||||||
|
..
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Ran 2 tests
|
||||||
|
|
||||||
|
OK
|
|
@ -283,6 +283,7 @@ static void test_block(gconstpointer opaque)
|
||||||
test_block_init_func,
|
test_block_init_func,
|
||||||
test_block_write_func,
|
test_block_write_func,
|
||||||
&header,
|
&header,
|
||||||
|
0,
|
||||||
&error_abort);
|
&error_abort);
|
||||||
g_assert(blk);
|
g_assert(blk);
|
||||||
|
|
||||||
|
@ -362,6 +363,7 @@ test_luks_bad_header(gconstpointer data)
|
||||||
test_block_init_func,
|
test_block_init_func,
|
||||||
test_block_write_func,
|
test_block_write_func,
|
||||||
&buf,
|
&buf,
|
||||||
|
0,
|
||||||
&error_abort);
|
&error_abort);
|
||||||
g_assert(blk);
|
g_assert(blk);
|
||||||
|
|
||||||
|
|
|
@ -382,6 +382,19 @@ static QCryptoCipherTestData test_data[] = {
|
||||||
.plaintext = "90afe91bb288544f2c32dc239b2635e6",
|
.plaintext = "90afe91bb288544f2c32dc239b2635e6",
|
||||||
.ciphertext = "6cb4561c40bf0a9705931cb6d408e7fa",
|
.ciphertext = "6cb4561c40bf0a9705931cb6d408e7fa",
|
||||||
},
|
},
|
||||||
|
#ifdef CONFIG_CRYPTO_SM4
|
||||||
|
{
|
||||||
|
/* SM4, GB/T 32907-2016, Appendix A.1 */
|
||||||
|
.path = "/crypto/cipher/sm4",
|
||||||
|
.alg = QCRYPTO_CIPHER_ALG_SM4,
|
||||||
|
.mode = QCRYPTO_CIPHER_MODE_ECB,
|
||||||
|
.key = "0123456789abcdeffedcba9876543210",
|
||||||
|
.plaintext =
|
||||||
|
"0123456789abcdeffedcba9876543210",
|
||||||
|
.ciphertext =
|
||||||
|
"681edf34d206965e86b3e94f536e4246",
|
||||||
|
},
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* #1 32 byte key, 32 byte PTX */
|
/* #1 32 byte key, 32 byte PTX */
|
||||||
.path = "/crypto/cipher/aes-xts-128-1",
|
.path = "/crypto/cipher/aes-xts-128-1",
|
||||||
|
|
34
ui/vnc.c
34
ui/vnc.c
|
@ -2144,16 +2144,16 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
|
||||||
vs->vnc_encoding = enc;
|
vs->vnc_encoding = enc;
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_HEXTILE:
|
case VNC_ENCODING_HEXTILE:
|
||||||
vs->features |= VNC_FEATURE_HEXTILE_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_HEXTILE);
|
||||||
vs->vnc_encoding = enc;
|
vs->vnc_encoding = enc;
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_TIGHT:
|
case VNC_ENCODING_TIGHT:
|
||||||
vs->features |= VNC_FEATURE_TIGHT_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_TIGHT);
|
||||||
vs->vnc_encoding = enc;
|
vs->vnc_encoding = enc;
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_PNG
|
#ifdef CONFIG_PNG
|
||||||
case VNC_ENCODING_TIGHT_PNG:
|
case VNC_ENCODING_TIGHT_PNG:
|
||||||
vs->features |= VNC_FEATURE_TIGHT_PNG_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_TIGHT_PNG);
|
||||||
vs->vnc_encoding = enc;
|
vs->vnc_encoding = enc;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2163,57 +2163,57 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
|
||||||
* So prioritize ZRLE, even if the client hints that it prefers
|
* So prioritize ZRLE, even if the client hints that it prefers
|
||||||
* ZLIB.
|
* ZLIB.
|
||||||
*/
|
*/
|
||||||
if ((vs->features & VNC_FEATURE_ZRLE_MASK) == 0) {
|
if (!vnc_has_feature(vs, VNC_FEATURE_ZRLE)) {
|
||||||
vs->features |= VNC_FEATURE_ZLIB_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_ZLIB);
|
||||||
vs->vnc_encoding = enc;
|
vs->vnc_encoding = enc;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_ZRLE:
|
case VNC_ENCODING_ZRLE:
|
||||||
vs->features |= VNC_FEATURE_ZRLE_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_ZRLE);
|
||||||
vs->vnc_encoding = enc;
|
vs->vnc_encoding = enc;
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_ZYWRLE:
|
case VNC_ENCODING_ZYWRLE:
|
||||||
vs->features |= VNC_FEATURE_ZYWRLE_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_ZYWRLE);
|
||||||
vs->vnc_encoding = enc;
|
vs->vnc_encoding = enc;
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_DESKTOPRESIZE:
|
case VNC_ENCODING_DESKTOPRESIZE:
|
||||||
vs->features |= VNC_FEATURE_RESIZE_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_RESIZE);
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_DESKTOP_RESIZE_EXT:
|
case VNC_ENCODING_DESKTOP_RESIZE_EXT:
|
||||||
vs->features |= VNC_FEATURE_RESIZE_EXT_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_RESIZE_EXT);
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_POINTER_TYPE_CHANGE:
|
case VNC_ENCODING_POINTER_TYPE_CHANGE:
|
||||||
vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE);
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_RICH_CURSOR:
|
case VNC_ENCODING_RICH_CURSOR:
|
||||||
vs->features |= VNC_FEATURE_RICH_CURSOR_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_RICH_CURSOR);
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_ALPHA_CURSOR:
|
case VNC_ENCODING_ALPHA_CURSOR:
|
||||||
vs->features |= VNC_FEATURE_ALPHA_CURSOR_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_ALPHA_CURSOR);
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_EXT_KEY_EVENT:
|
case VNC_ENCODING_EXT_KEY_EVENT:
|
||||||
send_ext_key_event_ack(vs);
|
send_ext_key_event_ack(vs);
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_AUDIO:
|
case VNC_ENCODING_AUDIO:
|
||||||
if (vs->vd->audio_state) {
|
if (vs->vd->audio_state) {
|
||||||
vs->features |= VNC_FEATURE_AUDIO_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_AUDIO);
|
||||||
send_ext_audio_ack(vs);
|
send_ext_audio_ack(vs);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_WMVi:
|
case VNC_ENCODING_WMVi:
|
||||||
vs->features |= VNC_FEATURE_WMVI_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_WMVI);
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_LED_STATE:
|
case VNC_ENCODING_LED_STATE:
|
||||||
vs->features |= VNC_FEATURE_LED_STATE_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_LED_STATE);
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_XVP:
|
case VNC_ENCODING_XVP:
|
||||||
if (vs->vd->power_control) {
|
if (vs->vd->power_control) {
|
||||||
vs->features |= VNC_FEATURE_XVP_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_XVP);
|
||||||
send_xvp_message(vs, VNC_XVP_CODE_INIT);
|
send_xvp_message(vs, VNC_XVP_CODE_INIT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_CLIPBOARD_EXT:
|
case VNC_ENCODING_CLIPBOARD_EXT:
|
||||||
vs->features |= VNC_FEATURE_CLIPBOARD_EXT_MASK;
|
vnc_set_feature(vs, VNC_FEATURE_CLIPBOARD_EXT);
|
||||||
vnc_server_cut_text_caps(vs);
|
vnc_server_cut_text_caps(vs);
|
||||||
break;
|
break;
|
||||||
case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9:
|
case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9:
|
||||||
|
|
22
ui/vnc.h
22
ui/vnc.h
|
@ -467,23 +467,6 @@ enum VncFeatures {
|
||||||
VNC_FEATURE_AUDIO,
|
VNC_FEATURE_AUDIO,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define VNC_FEATURE_RESIZE_MASK (1 << VNC_FEATURE_RESIZE)
|
|
||||||
#define VNC_FEATURE_RESIZE_EXT_MASK (1 << VNC_FEATURE_RESIZE_EXT)
|
|
||||||
#define VNC_FEATURE_HEXTILE_MASK (1 << VNC_FEATURE_HEXTILE)
|
|
||||||
#define VNC_FEATURE_POINTER_TYPE_CHANGE_MASK (1 << VNC_FEATURE_POINTER_TYPE_CHANGE)
|
|
||||||
#define VNC_FEATURE_WMVI_MASK (1 << VNC_FEATURE_WMVI)
|
|
||||||
#define VNC_FEATURE_TIGHT_MASK (1 << VNC_FEATURE_TIGHT)
|
|
||||||
#define VNC_FEATURE_ZLIB_MASK (1 << VNC_FEATURE_ZLIB)
|
|
||||||
#define VNC_FEATURE_RICH_CURSOR_MASK (1 << VNC_FEATURE_RICH_CURSOR)
|
|
||||||
#define VNC_FEATURE_ALPHA_CURSOR_MASK (1 << VNC_FEATURE_ALPHA_CURSOR)
|
|
||||||
#define VNC_FEATURE_TIGHT_PNG_MASK (1 << VNC_FEATURE_TIGHT_PNG)
|
|
||||||
#define VNC_FEATURE_ZRLE_MASK (1 << VNC_FEATURE_ZRLE)
|
|
||||||
#define VNC_FEATURE_ZYWRLE_MASK (1 << VNC_FEATURE_ZYWRLE)
|
|
||||||
#define VNC_FEATURE_LED_STATE_MASK (1 << VNC_FEATURE_LED_STATE)
|
|
||||||
#define VNC_FEATURE_XVP_MASK (1 << VNC_FEATURE_XVP)
|
|
||||||
#define VNC_FEATURE_CLIPBOARD_EXT_MASK (1 << VNC_FEATURE_CLIPBOARD_EXT)
|
|
||||||
#define VNC_FEATURE_AUDIO_MASK (1 << VNC_FEATURE_AUDIO)
|
|
||||||
|
|
||||||
|
|
||||||
/* Client -> Server message IDs */
|
/* Client -> Server message IDs */
|
||||||
#define VNC_MSG_CLIENT_SET_PIXEL_FORMAT 0
|
#define VNC_MSG_CLIENT_SET_PIXEL_FORMAT 0
|
||||||
|
@ -599,6 +582,11 @@ static inline uint32_t vnc_has_feature(VncState *vs, int feature) {
|
||||||
return (vs->features & (1 << feature));
|
return (vs->features & (1 << feature));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void vnc_set_feature(VncState *vs, enum VncFeatures feature)
|
||||||
|
{
|
||||||
|
vs->features |= (1 << feature);
|
||||||
|
}
|
||||||
|
|
||||||
/* Framebuffer */
|
/* Framebuffer */
|
||||||
void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
|
void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
|
||||||
int32_t encoding);
|
int32_t encoding);
|
||||||
|
|
Loading…
Reference in New Issue