From: "Daniel P. Berrange" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Cc: qemu-block@nongnu.org
Subject: [Qemu-devel] [PATCH v1 05/15] crypto: add block encryption framework
Date: Tue, 12 Jan 2016 18:56:12 +0000 [thread overview]
Message-ID: <1452624982-19332-6-git-send-email-berrange@redhat.com> (raw)
In-Reply-To: <1452624982-19332-1-git-send-email-berrange@redhat.com>
Add a generic framework for support different block encryption
formats. Upon instantiating a QCryptoBlock object, it will read
the encryption header and extract the encryption keys. It is
then possible to call methods to encrypt/decrypt data buffers.
There is also a mode whereby it will create/initialize a new
encryption header on a previously unformatted volume.
The initial framework comes with support for the legacy QCow
AES based encryption. This enables code in the QCow driver to
be consolidated later.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
crypto/Makefile.objs | 2 +
crypto/block-qcowaes.c | 165 ++++++++++++++++++++++++++++++++
crypto/block-qcowaes.h | 28 ++++++
crypto/block.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++
crypto/blockpriv.h | 89 +++++++++++++++++
include/crypto/block.h | 222 ++++++++++++++++++++++++++++++++++++++++++
qapi/crypto.json | 65 +++++++++++++
7 files changed, 825 insertions(+)
create mode 100644 crypto/block-qcowaes.c
create mode 100644 crypto/block-qcowaes.h
create mode 100644 crypto/block.c
create mode 100644 crypto/blockpriv.h
create mode 100644 include/crypto/block.h
diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
index 1e08a3a..b5b32a6 100644
--- a/crypto/Makefile.objs
+++ b/crypto/Makefile.objs
@@ -15,6 +15,8 @@ crypto-obj-y += ivgen-essiv.o
crypto-obj-y += ivgen-plain.o
crypto-obj-y += ivgen-plain64.o
crypto-obj-y += afsplit.o
+crypto-obj-y += block.o
+crypto-obj-y += block-qcowaes.o
# Let the userspace emulators avoid linking gnutls/etc
crypto-aes-obj-y = aes.o
diff --git a/crypto/block-qcowaes.c b/crypto/block-qcowaes.c
new file mode 100644
index 0000000..cf8ff50
--- /dev/null
+++ b/crypto/block-qcowaes.c
@@ -0,0 +1,165 @@
+/*
+ * QEMU Crypto block device encryption QCOWAES format
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config-host.h"
+
+#include "crypto/block-qcowaes.h"
+#include "crypto/secret.h"
+
+static gboolean
+qcrypto_block_qcowaes_has_format(const uint8_t *buf G_GNUC_UNUSED,
+ size_t buf_size G_GNUC_UNUSED)
+{
+ return false;
+}
+
+
+static int
+qcrypto_block_qcowaes_init(QCryptoBlock *block,
+ const char *keyid,
+ Error **errp)
+{
+ char *password;
+ int ret;
+ uint8_t keybuf[16];
+ int len, i;
+
+ memset(keybuf, 0, 16);
+
+ password = qcrypto_secret_lookup_as_utf8(keyid, errp);
+ if (!password) {
+ return -1;
+ }
+
+ len = strlen(password);
+ if (len > 16) {
+ len = 16;
+ }
+ for (i = 0; i < len; i++) {
+ keybuf[i] = password[i];
+ }
+ g_free(password);
+
+ block->niv = qcrypto_cipher_get_iv_len(QCRYPTO_CIPHER_ALG_AES_128,
+ QCRYPTO_CIPHER_MODE_CBC);
+ block->ivgen = qcrypto_ivgen_new(QCRYPTO_IVGEN_ALG_PLAIN64,
+ 0, 0, NULL, 0, errp);
+ if (!block->ivgen) {
+ ret = -ENOTSUP;
+ goto fail;
+ }
+
+ block->cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_128,
+ QCRYPTO_CIPHER_MODE_CBC,
+ keybuf, G_N_ELEMENTS(keybuf),
+ errp);
+ if (!block->cipher) {
+ ret = -ENOTSUP;
+ goto fail;
+ }
+
+ block->payload_offset = 0;
+
+ return 0;
+
+ fail:
+ qcrypto_cipher_free(block->cipher);
+ qcrypto_ivgen_free(block->ivgen);
+ return ret;
+}
+
+
+static int
+qcrypto_block_qcowaes_open(QCryptoBlock *block,
+ QCryptoBlockOpenOptions *options,
+ QCryptoBlockReadFunc readfunc G_GNUC_UNUSED,
+ void *opaque G_GNUC_UNUSED,
+ unsigned int flags,
+ Error **errp)
+{
+ if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
+ return 0;
+ } else {
+ if (!options->u.qcowaes->key_id) {
+ error_setg(errp, "Parameter 'key-id' is required to initialize cipher");
+ return -1;
+ }
+ return qcrypto_block_qcowaes_init(block, options->u.qcowaes->key_id, errp);
+ }
+}
+
+
+static int
+qcrypto_block_qcowaes_create(QCryptoBlock *block,
+ QCryptoBlockCreateOptions *options,
+ QCryptoBlockInitFunc initfunc G_GNUC_UNUSED,
+ QCryptoBlockWriteFunc writefunc G_GNUC_UNUSED,
+ void *opaque G_GNUC_UNUSED,
+ Error **errp)
+{
+ if (!options->u.qcowaes->key_id) {
+ error_setg(errp, "Parameter 'key-id' is required to initialize cipher");
+ return -1;
+ }
+ /* QCow2 has no special header, since everything is hardwired */
+ return qcrypto_block_qcowaes_init(block, options->u.qcowaes->key_id, errp);
+}
+
+
+static void
+qcrypto_block_qcowaes_cleanup(QCryptoBlock *block)
+{
+}
+
+
+static int
+qcrypto_block_qcowaes_decrypt(QCryptoBlock *block,
+ uint64_t startsector,
+ uint8_t *buf,
+ size_t len,
+ Error **errp)
+{
+ return qcrypto_block_decrypt_helper(block->cipher,
+ block->niv, block->ivgen,
+ startsector, buf, len, errp);
+}
+
+
+static int
+qcrypto_block_qcowaes_encrypt(QCryptoBlock *block,
+ uint64_t startsector,
+ uint8_t *buf,
+ size_t len,
+ Error **errp)
+{
+ return qcrypto_block_encrypt_helper(block->cipher,
+ block->niv, block->ivgen,
+ startsector, buf, len, errp);
+}
+
+
+const QCryptoBlockDriver qcrypto_block_driver_qcowaes = {
+ .open = qcrypto_block_qcowaes_open,
+ .create = qcrypto_block_qcowaes_create,
+ .cleanup = qcrypto_block_qcowaes_cleanup,
+ .decrypt = qcrypto_block_qcowaes_decrypt,
+ .encrypt = qcrypto_block_qcowaes_encrypt,
+ .has_format = qcrypto_block_qcowaes_has_format,
+};
diff --git a/crypto/block-qcowaes.h b/crypto/block-qcowaes.h
new file mode 100644
index 0000000..e43b7e5
--- /dev/null
+++ b/crypto/block-qcowaes.h
@@ -0,0 +1,28 @@
+/*
+ * QEMU Crypto block device encryption QCow AES format
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QCRYPTO_BLOCK_QCOWAES_H__
+#define QCRYPTO_BLOCK_QCOWAES_H__
+
+#include "crypto/blockpriv.h"
+
+extern const QCryptoBlockDriver qcrypto_block_driver_qcowaes;
+
+#endif /* QCRYPTO_BLOCK_QCOWAES_H__ */
diff --git a/crypto/block.c b/crypto/block.c
new file mode 100644
index 0000000..657f4a9
--- /dev/null
+++ b/crypto/block.c
@@ -0,0 +1,254 @@
+/*
+ * QEMU Crypto block device encryption
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "crypto/blockpriv.h"
+#include "crypto/block-qcowaes.h"
+
+static const QCryptoBlockDriver *qcrypto_block_drivers[] = {
+ [Q_CRYPTO_BLOCK_FORMAT_QCOWAES] = &qcrypto_block_driver_qcowaes,
+};
+
+
+gboolean qcrypto_block_has_format(QCryptoBlockFormat format,
+ const uint8_t *buf,
+ size_t len)
+{
+ const QCryptoBlockDriver *driver;
+
+ if (format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
+ !qcrypto_block_drivers[format]) {
+ return false;
+ }
+
+ driver = qcrypto_block_drivers[format];
+
+ return driver->has_format(buf, len);
+}
+
+
+QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
+ QCryptoBlockReadFunc readfunc,
+ void *opaque,
+ unsigned int flags,
+ Error **errp)
+{
+ QCryptoBlock *block = g_new0(QCryptoBlock, 1);
+
+ block->format = options->format;
+
+ if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
+ !qcrypto_block_drivers[options->format]) {
+ error_setg(errp, "Unsupported block driver %d", options->format);
+ g_free(block);
+ return NULL;
+ }
+
+ block->driver = qcrypto_block_drivers[options->format];
+
+ if (block->driver->open(block, options, readfunc, opaque, flags, errp) < 0) {
+ g_free(block);
+ return NULL;
+ }
+
+ return block;
+}
+
+
+QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
+ QCryptoBlockInitFunc initfunc,
+ QCryptoBlockWriteFunc writefunc,
+ void *opaque,
+ Error **errp)
+{
+ QCryptoBlock *block = g_new0(QCryptoBlock, 1);
+
+ block->format = options->format;
+
+ if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
+ !qcrypto_block_drivers[options->format]) {
+ error_setg(errp, "Unsupported block driver %d", options->format);
+ g_free(block);
+ return NULL;
+ }
+
+ block->driver = qcrypto_block_drivers[options->format];
+
+ if (block->driver->create(block, options, initfunc,
+ writefunc, opaque, errp) < 0) {
+ g_free(block);
+ return NULL;
+ }
+
+ return block;
+}
+
+
+int qcrypto_block_decrypt(QCryptoBlock *block,
+ uint64_t startsector,
+ uint8_t *buf,
+ size_t len,
+ Error **errp)
+{
+ return block->driver->decrypt(block, startsector, buf, len, errp);
+}
+
+
+int qcrypto_block_encrypt(QCryptoBlock *block,
+ uint64_t startsector,
+ uint8_t *buf,
+ size_t len,
+ Error **errp)
+{
+ return block->driver->encrypt(block, startsector, buf, len, errp);
+}
+
+
+QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block)
+{
+ return block->cipher;
+}
+
+
+QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block)
+{
+ return block->ivgen;
+}
+
+
+uint64_t qcrypto_block_get_payload_offset(QCryptoBlock *block)
+{
+ return block->payload_offset;
+}
+
+
+void qcrypto_block_free(QCryptoBlock *block)
+{
+ if (!block) {
+ return;
+ }
+
+ block->driver->cleanup(block);
+
+ g_free(block);
+}
+
+
+int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
+ size_t niv,
+ QCryptoIVGen *ivgen,
+ uint64_t startsector,
+ uint8_t *buf,
+ size_t len,
+ Error **errp)
+{
+ size_t nsectors = len / 512;
+ size_t i;
+ uint8_t *iv;
+ int ret = -1;
+
+ if (len % 512) {
+ error_setg(errp, "Length %zu must be a multiple of sector size",
+ len);
+ return -1;
+ }
+
+ iv = niv ? g_new0(uint8_t, niv) : NULL;
+
+ for (i = 0; i < nsectors; i++) {
+ if (niv) {
+ if (qcrypto_ivgen_calculate(ivgen,
+ startsector + i,
+ iv, niv,
+ errp) < 0) {
+ goto cleanup;
+ }
+
+ if (qcrypto_cipher_setiv(cipher,
+ iv, niv,
+ errp) < 0) {
+ goto cleanup;
+ }
+ }
+ if (qcrypto_cipher_decrypt(cipher,
+ buf + (i * 512),
+ buf + (i * 512),
+ 512,
+ errp) < 0) {
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+ cleanup:
+ g_free(iv);
+ return ret;
+}
+
+
+int qcrypto_block_encrypt_helper(QCryptoCipher *cipher,
+ size_t niv,
+ QCryptoIVGen *ivgen,
+ uint64_t startsector,
+ uint8_t *buf,
+ size_t len,
+ Error **errp)
+{
+ size_t nsectors = len / 512;
+ size_t i;
+ uint8_t *iv;
+ int ret = -1;
+
+ if (len % 512) {
+ error_setg(errp, "Length %zu must be a multiple of sector size",
+ len);
+ return -1;
+ }
+
+ iv = niv ? g_new0(uint8_t, niv) : NULL;
+
+ for (i = 0; i < nsectors; i++) {
+ if (niv) {
+ if (qcrypto_ivgen_calculate(ivgen,
+ startsector + i,
+ iv, niv,
+ errp) < 0) {
+ goto cleanup;
+ }
+
+ if (qcrypto_cipher_setiv(cipher,
+ iv, niv,
+ errp) < 0) {
+ goto cleanup;
+ }
+ }
+ if (qcrypto_cipher_encrypt(cipher,
+ buf + (i * 512),
+ buf + (i * 512),
+ 512,
+ errp) < 0) {
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+ cleanup:
+ g_free(iv);
+ return ret;
+}
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
new file mode 100644
index 0000000..7ca42c5
--- /dev/null
+++ b/crypto/blockpriv.h
@@ -0,0 +1,89 @@
+/*
+ * QEMU Crypto block device encryption
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QCRYPTO_BLOCK_PRIV_H__
+#define QCRYPTO_BLOCK_PRIV_H__
+
+#include "crypto/block.h"
+
+typedef struct QCryptoBlockDriver QCryptoBlockDriver;
+
+struct QCryptoBlock {
+ QCryptoBlockFormat format;
+
+ const QCryptoBlockDriver *driver;
+ void *opaque;
+
+ QCryptoCipher *cipher;
+ QCryptoIVGen *ivgen;
+ size_t niv;
+ uint64_t payload_offset; /* In 512 byte sectors */
+};
+
+struct QCryptoBlockDriver {
+ int (*open)(QCryptoBlock *block,
+ QCryptoBlockOpenOptions *options,
+ QCryptoBlockReadFunc readfunc,
+ void *opaque,
+ unsigned int flags,
+ Error **errp);
+
+ int (*create)(QCryptoBlock *block,
+ QCryptoBlockCreateOptions *options,
+ QCryptoBlockInitFunc initfunc,
+ QCryptoBlockWriteFunc writefunc,
+ void *opaque,
+ Error **errp);
+
+ void (*cleanup)(QCryptoBlock *block);
+
+ int (*encrypt)(QCryptoBlock *block,
+ uint64_t startsector,
+ uint8_t *buf,
+ size_t len,
+ Error **errp);
+ int (*decrypt)(QCryptoBlock *block,
+ uint64_t startsector,
+ uint8_t *buf,
+ size_t len,
+ Error **errp);
+
+ gboolean (*has_format)(const uint8_t *buf,
+ size_t buflen);
+};
+
+
+int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
+ size_t niv,
+ QCryptoIVGen *ivgen,
+ uint64_t startsector,
+ uint8_t *buf,
+ size_t len,
+ Error **errp);
+
+int qcrypto_block_encrypt_helper(QCryptoCipher *cipher,
+ size_t niv,
+ QCryptoIVGen *ivgen,
+ uint64_t startsector,
+ uint8_t *buf,
+ size_t len,
+ Error **errp);
+
+#endif /* QCRYPTO_BLOCK_PRIV_H__ */
diff --git a/include/crypto/block.h b/include/crypto/block.h
new file mode 100644
index 0000000..e4834b3
--- /dev/null
+++ b/include/crypto/block.h
@@ -0,0 +1,222 @@
+/*
+ * QEMU Crypto block device encryption
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QCRYPTO_BLOCK_H__
+#define QCRYPTO_BLOCK_H__
+
+#include "crypto/cipher.h"
+#include "crypto/ivgen.h"
+
+typedef struct QCryptoBlock QCryptoBlock;
+
+/* See also QCryptoBlockFormat, QCryptoBlockCreateOptions
+ * and QCryptoBlockOpenOptions in qapi/crypto.json */
+
+typedef ssize_t (*QCryptoBlockReadFunc)(QCryptoBlock *block,
+ size_t offset,
+ uint8_t *buf,
+ size_t buflen,
+ Error **errp,
+ void *opaque);
+
+typedef ssize_t (*QCryptoBlockInitFunc)(QCryptoBlock *block,
+ size_t headerlen,
+ Error **errp,
+ void *opaque);
+
+typedef ssize_t (*QCryptoBlockWriteFunc)(QCryptoBlock *block,
+ size_t offset,
+ const uint8_t *buf,
+ size_t buflen,
+ Error **errp,
+ void *opaque);
+
+/**
+ * qcrypto_block_has_format:
+ * @format: the encryption format
+ * @buf: the data from head of the volume
+ * @len: the length of @buf in bytes
+ *
+ * Given @len bytes of data from the head of a storage volume
+ * in @buf, probe to determine if the volume has the encryption
+ * format specified in @format.
+ *
+ * Returns: true if the data in @buf matches @format
+ */
+gboolean qcrypto_block_has_format(QCryptoBlockFormat format,
+ const uint8_t *buf,
+ size_t buflen);
+
+typedef enum {
+ QCRYPTO_BLOCK_OPEN_NO_IO = (1 << 0),
+} QCryptoBlockOpenFlags;
+
+/**
+ * qcrypto_block_open:
+ * @options: the encryption options
+ * @readfunc: callback for reading data from the volume
+ * @opaque: data to pass to @readfunc
+ * @flags: bitmask of QCryptoBlockOpenFlags values
+ * @errp: pointer to an uninitialized error object
+ *
+ * Create a new block encryption object for an existing
+ * storage volume encrypted with format identified by
+ * the parameters in @options.
+ *
+ * This will use @readfunc to initialize the encryption
+ * context based on the volume header(s), extracting the
+ * master key(s) as required.
+ *
+ * If @flags contains QCRYPTO_BLOCK_OPEN_NO_IO then
+ * the open process will be optimized to skip any parts
+ * that are only required to perform I/O. In particular
+ * this would usually avoid the need to decrypt any
+ * master keys. The only thing that can be done with
+ * the resulting QCryptoBlock object would be to query
+ * metadata such as the payload offset. There will be
+ * no cipher or ivgen objects available.
+ *
+ * If any part of initializing the encryption context
+ * fails an error will be returned. This could be due
+ * to the volume being in the wrong format, an cipher
+ * or IV generator algorithm that is not supoported,
+ * or incorrect passphrases.
+ *
+ * Returns: a block encryption format, or NULL on error
+ */
+QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
+ QCryptoBlockReadFunc readfunc,
+ void *opaque,
+ unsigned int flags,
+ Error **errp);
+
+/**
+ * qcrypto_block_create:
+ * @format: the encryption format
+ * @keyid: ID of a QCryptoSecret with key for unlocking master key
+ * @initfunc: callback for initializing volume header
+ * @writefunc: callback for writing data to the volume header
+ * @opaque: data to pass to @initfunc & @writefunc
+ * @errp: pointer to an uninitialized error object
+ *
+ * Create a new block encryption object for initializing
+ * a storage volume to be encrypted with format identified
+ * by the parameters in @options.
+ *
+ * This method will allocate space for a new volume header
+ * using @initfunc and then write header data using @writefunc,
+ * generating new master keys, etc as required. Any existing
+ * data present on the volume will be irrevokably destroyed.
+ *
+ * If any part of initializing the encryption context
+ * fails an error will be returned. This could be due
+ * to the volume being in the wrong format, an cipher
+ * or IV generator algorithm that is not supoported,
+ * or incorrect passphrases.
+ *
+ * Returns: a block encryption format, or NULL on error
+ */
+QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
+ QCryptoBlockInitFunc initfunc,
+ QCryptoBlockWriteFunc writefunc,
+ void *opaque,
+ Error **errp);
+
+/**
+ * @qcrypto_block_decrypt:
+ * @block: the block encryption object
+ * @startsector: the sector from which @buf was read
+ * @buf: the buffer to decrypt
+ * @len: the length of @buf in bytes
+ * @errp: pointer to an uninitialized error object
+ *
+ * Decrypt @len bytes of cipher text in @buf, writing
+ * plain text back into @buf
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int qcrypto_block_decrypt(QCryptoBlock *block,
+ uint64_t startsector,
+ uint8_t *buf,
+ size_t len,
+ Error **errp);
+
+/**
+ * @qcrypto_block_encrypt:
+ * @block: the block encryption object
+ * @startsector: the sector to which @buf will be written
+ * @buf: the buffer to decrypt
+ * @len: the length of @buf in bytes
+ * @errp: pointer to an uninitialized error object
+ *
+ * Encrypt @len bytes of plain text in @buf, writing
+ * cipher text back into @buf
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int qcrypto_block_encrypt(QCryptoBlock *block,
+ uint64_t startsector,
+ uint8_t *buf,
+ size_t len,
+ Error **errp);
+
+/**
+ * qcrypto_block_get_cipher:
+ * @block: the block encryption object
+ *
+ * Get the cipher to use for payload encryption
+ *
+ * Returns: the cipher object
+ */
+QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block);
+
+/**
+ * qcrypto_block_get_ivgen:
+ * @block: the block encryption object
+ *
+ * Get the initialization vector generator to use for
+ * payload encryption
+ *
+ * Returns: the IV generator object
+ */
+QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block);
+
+/**
+ * qcrypto_block_get_payload_offset:
+ * @block: the block encryption object
+ *
+ * Get the offset to the payload indicated by the
+ * encryption header. The offset is measured in
+ * 512 byte sectors
+ *
+ * Returns: the payload offset in sectors.
+ */
+uint64_t qcrypto_block_get_payload_offset(QCryptoBlock *block);
+
+/**
+ * qcrypto_block_free:
+ * @block: the block encryption object
+ *
+ * Release all resources associated with the encryption
+ * object
+ */
+void qcrypto_block_free(QCryptoBlock *block);
+
+#endif /* QCRYPTO_BLOCK_H__ */
diff --git a/qapi/crypto.json b/qapi/crypto.json
index 48946b0..07b9b46 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -94,3 +94,68 @@
{ 'enum': 'QCryptoIVGenAlgorithm',
'prefix': 'QCRYPTO_IVGEN_ALG',
'data': ['plain', 'plain64', 'essiv']}
+
+##
+# QCryptoBlockFormat:
+#
+# The supported full disk encryption formats
+#
+# @qcowaes: QCow/QCow2 built-in AES-CBC encryption. Do not use
+#
+# Since: 2.6
+##
+{ 'enum': 'QCryptoBlockFormat',
+# 'prefix': 'QCRYPTO_BLOCK_FORMAT',
+ 'data': ['qcowaes']}
+
+##
+# QCryptoBlockOptionsBase:
+#
+# The common options that apply to all full disk
+# encryption formats
+#
+# @format: the encryption format
+#
+# Since: 2.6
+##
+{ 'struct': 'QCryptoBlockOptionsBase',
+ 'data': { 'format': 'QCryptoBlockFormat' }}
+
+##
+# QCryptoBlockOptionsQCowAES:
+#
+# The options that apply to QCow AES encryption format
+#
+# @key-id: the ID of a QCryptoSecret object providing the decryption key
+#
+# Since: 2.6
+##
+{ 'struct': 'QCryptoBlockOptionsQCowAES',
+ 'data': { '*key-id': 'str' }}
+
+##
+# QCryptoBlockOpenOptions:
+#
+# The options that are available for all encryption formats
+# when opening an existing volume
+#
+# Since: 2.6
+##
+{ 'union': 'QCryptoBlockOpenOptions',
+ 'base': 'QCryptoBlockOptionsBase',
+ 'discriminator': 'format',
+ 'data': { 'qcowaes': 'QCryptoBlockOptionsQCowAES' } }
+
+
+##
+# QCryptoBlockCreateOptions:
+#
+# The options that are available for all encryption formats
+# when initializing a new volume
+#
+# Since: 2.6
+##
+{ 'union': 'QCryptoBlockCreateOptions',
+ 'base': 'QCryptoBlockOptionsBase',
+ 'discriminator': 'format',
+ 'data': { 'qcowaes': 'QCryptoBlockOptionsQCowAES' } }
--
2.5.0
next prev parent reply other threads:[~2016-01-12 18:57 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-12 18:56 [Qemu-devel] [PATCH v1 00/15] Support LUKS encryption in block devices Daniel P. Berrange
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 01/15] crypto: add cryptographic random byte source Daniel P. Berrange
2016-01-13 2:46 ` Fam Zheng
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 02/15] crypto: add support for PBKDF2 algorithm Daniel P. Berrange
2016-01-13 5:53 ` Fam Zheng
2016-01-14 12:17 ` Daniel P. Berrange
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 03/15] crypto: add support for generating initialization vectors Daniel P. Berrange
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 04/15] crypto: add support for anti-forensic split algorithm Daniel P. Berrange
2016-01-12 18:56 ` Daniel P. Berrange [this message]
2016-01-13 23:40 ` [Qemu-devel] [PATCH v1 05/15] crypto: add block encryption framework Eric Blake
2016-01-14 12:16 ` Daniel P. Berrange
2016-01-18 19:48 ` Eric Blake
2016-01-19 9:41 ` Daniel P. Berrange
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 06/15] crypto: implement the LUKS block encryption format Daniel P. Berrange
2016-01-13 23:43 ` Eric Blake
2016-01-14 10:14 ` Daniel P. Berrange
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 07/15] block: add flag to indicate that no I/O will be performed Daniel P. Berrange
2016-01-13 17:44 ` [Qemu-devel] [Qemu-block] " Kevin Wolf
2016-01-13 17:56 ` Daniel P. Berrange
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 08/15] block: add generic full disk encryption driver Daniel P. Berrange
2016-01-13 23:47 ` Eric Blake
2016-01-14 10:15 ` Daniel P. Berrange
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 09/15] qcow2: make qcow2_encrypt_sectors encrypt in place Daniel P. Berrange
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 10/15] qcow2: convert QCow2 to use QCryptoBlock for encryption Daniel P. Berrange
2016-01-13 18:42 ` [Qemu-devel] [Qemu-block] " Kevin Wolf
2016-01-14 12:14 ` Daniel P. Berrange
2016-01-14 12:58 ` Kevin Wolf
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 11/15] qcow: make encrypt_sectors encrypt in place Daniel P. Berrange
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 12/15] qcow: convert QCow to use QCryptoBlock for encryption Daniel P. Berrange
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 13/15] block: rip out all traces of password prompting Daniel P. Berrange
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 14/15] block: remove all encryption handling APIs Daniel P. Berrange
2016-01-12 18:56 ` [Qemu-devel] [PATCH v1 15/15] block: remove support for legecy AES qcow/qcow2 encryption Daniel P. Berrange
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1452624982-19332-6-git-send-email-berrange@redhat.com \
--to=berrange@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.