Re: [Qemu-devel] [PATCH v1 06/15] crypto: implement the LUKS block encryption format

2016-01-14 Thread Daniel P. Berrange
On Wed, Jan 13, 2016 at 04:43:15PM -0700, Eric Blake wrote:
> On 01/12/2016 11:56 AM, Daniel P. Berrange wrote:
> > Provide a block encryption implementation that follows the
> > LUKS/dm-crypt specification.
> > 
> > This supports all combinations of hash, cipher algorithm,
> > cipher mode and iv generator that are implemented by the
> > current crypto layer.
> > 
> > The notable missing feature is support for the 'xts'
> > cipher mode, which is commonly used for disk encryption
> > instead of 'cbc'. This is because it is not provided by
> > either nettle or libgcrypt. A suitable implementation
> > will be identified & integrated later.
> > 
> > There is support for opening existing volumes formatted
> > by dm-crypt, and for formatting new volumes. In the latter
> > case it will only use key slot 0.
> > 
> > Signed-off-by: Daniel P. Berrange 
> > ---
> 
> > +++ b/qapi/crypto.json
> > @@ -101,12 +101,13 @@
> >  # The supported full disk encryption formats
> >  #
> >  # @qcowaes: QCow/QCow2 built-in AES-CBC encryption. Do not use
> > +# @luks: LUKS encryption format. Recommended
> >  #
> >  # Since: 2.6
> >  ##
> >  { 'enum': 'QCryptoBlockFormat',
> >  #  'prefix': 'QCRYPTO_BLOCK_FORMAT',
> > -  'data': ['qcowaes']}
> > +  'data': ['qcowaes', 'luks']}
> >  
> >  ##
> >  # QCryptoBlockOptionsBase:
> > @@ -134,6 +135,39 @@
> >'data': { '*key-id': 'str' }}
> >  
> >  ##
> > +# QCryptoBlockOptionsLUKS:
> > +#
> > +# The options that apply to LUKS encryption format
> > +#
> > +# @key-id: the ID of a QCryptoSecret object providing the decryption key
> 
> Is the key-id really optional?  If so, missing the '#optional' tag.

Yes & no. It is not optional if you actually want to open the disk
and do I/O, but we want 'qemu-img info' to be able to report on data
when using the BDRV_O_NO_IO flag, so we have to declare it optional
to allow that to work. This is why we have an explicit check for
key_id being non-NULL in the code at time of use.

Regards,
Daniel
-- 
|: http://berrange.com  -o-http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org  -o- http://virt-manager.org :|
|: http://autobuild.org   -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org   -o-   http://live.gnome.org/gtk-vnc :|



Re: [Qemu-devel] [PATCH v1 06/15] crypto: implement the LUKS block encryption format

2016-01-13 Thread Eric Blake
On 01/12/2016 11:56 AM, Daniel P. Berrange wrote:
> Provide a block encryption implementation that follows the
> LUKS/dm-crypt specification.
> 
> This supports all combinations of hash, cipher algorithm,
> cipher mode and iv generator that are implemented by the
> current crypto layer.
> 
> The notable missing feature is support for the 'xts'
> cipher mode, which is commonly used for disk encryption
> instead of 'cbc'. This is because it is not provided by
> either nettle or libgcrypt. A suitable implementation
> will be identified & integrated later.
> 
> There is support for opening existing volumes formatted
> by dm-crypt, and for formatting new volumes. In the latter
> case it will only use key slot 0.
> 
> Signed-off-by: Daniel P. Berrange 
> ---

> +++ b/qapi/crypto.json
> @@ -101,12 +101,13 @@
>  # The supported full disk encryption formats
>  #
>  # @qcowaes: QCow/QCow2 built-in AES-CBC encryption. Do not use
> +# @luks: LUKS encryption format. Recommended
>  #
>  # Since: 2.6
>  ##
>  { 'enum': 'QCryptoBlockFormat',
>  #  'prefix': 'QCRYPTO_BLOCK_FORMAT',
> -  'data': ['qcowaes']}
> +  'data': ['qcowaes', 'luks']}
>  
>  ##
>  # QCryptoBlockOptionsBase:
> @@ -134,6 +135,39 @@
>'data': { '*key-id': 'str' }}
>  
>  ##
> +# QCryptoBlockOptionsLUKS:
> +#
> +# The options that apply to LUKS encryption format
> +#
> +# @key-id: the ID of a QCryptoSecret object providing the decryption key

Is the key-id really optional?  If so, missing the '#optional' tag.

> +# Since: 2.6
> +##
> +{ 'struct': 'QCryptoBlockOptionsLUKS',
> +  'data': { '*key-id': 'str' }}
> +
> +
> +##
> +# QCryptoBlockCreateOptionsLUKS:
> +#
> +# The options that apply to LUKS encryption format initialization
> +#
> +# @cipher-alg: (optional) the cipher algorithm for data encryption

Marc-Andre's pending patches to auto-generate docs from the .json files
want this to be s/(optional)/#optional/ (here and elsewhere).

-- 
Eric Blake   eblake redhat com+1-919-301-3266
Libvirt virtualization library http://libvirt.org



signature.asc
Description: OpenPGP digital signature


[Qemu-devel] [PATCH v1 06/15] crypto: implement the LUKS block encryption format

2016-01-12 Thread Daniel P. Berrange
Provide a block encryption implementation that follows the
LUKS/dm-crypt specification.

This supports all combinations of hash, cipher algorithm,
cipher mode and iv generator that are implemented by the
current crypto layer.

The notable missing feature is support for the 'xts'
cipher mode, which is commonly used for disk encryption
instead of 'cbc'. This is because it is not provided by
either nettle or libgcrypt. A suitable implementation
will be identified & integrated later.

There is support for opening existing volumes formatted
by dm-crypt, and for formatting new volumes. In the latter
case it will only use key slot 0.

Signed-off-by: Daniel P. Berrange 
---
 crypto/Makefile.objs |1 +
 crypto/block-luks.c  | 1092 ++
 crypto/block-luks.h  |   28 ++
 crypto/block.c   |2 +
 qapi/crypto.json |   42 +-
 5 files changed, 1162 insertions(+), 3 deletions(-)
 create mode 100644 crypto/block-luks.c
 create mode 100644 crypto/block-luks.h

diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
index b5b32a6..c65880f 100644
--- a/crypto/Makefile.objs
+++ b/crypto/Makefile.objs
@@ -17,6 +17,7 @@ crypto-obj-y += ivgen-plain64.o
 crypto-obj-y += afsplit.o
 crypto-obj-y += block.o
 crypto-obj-y += block-qcowaes.o
+crypto-obj-y += block-luks.o
 
 # Let the userspace emulators avoid linking gnutls/etc
 crypto-aes-obj-y = aes.o
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
new file mode 100644
index 000..dbe107c
--- /dev/null
+++ b/crypto/block-luks.c
@@ -0,0 +1,1092 @@
+/*
+ * QEMU Crypto block device encryption LUKS 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 .
+ *
+ */
+
+#include "config-host.h"
+
+#include "crypto/block-luks.h"
+
+#include "crypto/hash.h"
+#include "crypto/afsplit.h"
+#include "crypto/pbkdf.h"
+#include "crypto/secret.h"
+#include "crypto/random.h"
+
+#ifdef CONFIG_UUID
+#include 
+#endif
+
+#include "qemu/coroutine.h"
+
+/*
+ * Reference for format is
+ *
+ * docs/on-disk-format.pdf
+ *
+ * In 'cryptsetup' package source code
+ *
+ */
+
+typedef struct QCryptoBlockLUKS QCryptoBlockLUKS;
+typedef struct QCryptoBlockLUKSHeader QCryptoBlockLUKSHeader;
+typedef struct QCryptoBlockLUKSKeySlot QCryptoBlockLUKSKeySlot;
+
+#define QCRYPTO_BLOCK_LUKS_VERSION 1
+
+#define QCRYPTO_BLOCK_LUKS_MAGIC_LEN 6
+#define QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN 32
+#define QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN 32
+#define QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN 32
+#define QCRYPTO_BLOCK_LUKS_DIGEST_LEN 20
+#define QCRYPTO_BLOCK_LUKS_SALT_LEN 32
+#define QCRYPTO_BLOCK_LUKS_UUID_LEN 40
+#define QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS 8
+#define QCRYPTO_BLOCK_LUKS_STRIPES 4000
+#define QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS 1000
+#define QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS 1000
+#define QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET 4096
+
+#define QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED 0xDEAD
+#define QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED 0x00AC71F3
+
+static const char qcrypto_block_luks_magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN] = {
+'L', 'U', 'K', 'S', 0xBA, 0xBE
+};
+
+typedef struct QCryptoBlockLUKSNameMap QCryptoBlockLUKSNameMap;
+struct QCryptoBlockLUKSNameMap {
+const char *name;
+int id;
+};
+
+typedef struct QCryptoBlockLUKSCipherSizeMap QCryptoBlockLUKSCipherSizeMap;
+struct QCryptoBlockLUKSCipherSizeMap {
+uint32_t key_bytes;
+int id;
+};
+typedef struct QCryptoBlockLUKSCipherNameMap QCryptoBlockLUKSCipherNameMap;
+struct QCryptoBlockLUKSCipherNameMap {
+const char *name;
+const QCryptoBlockLUKSCipherSizeMap *sizes;
+};
+
+
+static const QCryptoBlockLUKSCipherSizeMap
+qcrypto_block_luks_cipher_size_map_aes[] = {
+{ 16, QCRYPTO_CIPHER_ALG_AES_128 },
+{ 24, QCRYPTO_CIPHER_ALG_AES_192 },
+{ 32, QCRYPTO_CIPHER_ALG_AES_256 },
+{ 0, 0 },
+};
+
+static const QCryptoBlockLUKSCipherNameMap
+qcrypto_block_luks_cipher_name_map[] = {
+{ "aes", qcrypto_block_luks_cipher_size_map_aes, },
+};
+
+
+struct QCryptoBlockLUKSKeySlot {
+/* state of keyslot, enabled/disable */
+uint32_t active;
+/* iterations for PBKDF2 */
+uint32_t iterations;
+/* salt for PBKDF2 */
+uint8_t salt[QCRYPTO_BLOCK_LUKS_SALT_LEN];
+/* start sector of key material */
+uint32_t key_offset;
+/* number of anti-forensic stripes */
+