qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Maxim Levitsky <mlevitsk@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Kevin Wolf" <kwolf@redhat.com>, "Fam Zheng" <fam@euphon.net>,
	"Daniel P. Berrangé" <berrange@redhat.com>,
	qemu-block@nongnu.org, "Markus Armbruster" <armbru@redhat.com>,
	"Max Reitz" <mreitz@redhat.com>,
	"Stefan Hajnoczi" <stefanha@redhat.com>,
	"Maxim Levitsky" <mlevitsk@redhat.com>
Subject: [Qemu-devel] [PATCH 07/13] block: add manage-encryption command (qmp and blockdev)
Date: Wed, 14 Aug 2019 23:22:13 +0300	[thread overview]
Message-ID: <20190814202219.1870-8-mlevitsk@redhat.com> (raw)
In-Reply-To: <20190814202219.1870-1-mlevitsk@redhat.com>

This adds:

* x-blockdev-update-encryption and x-blockdev-erase-encryption qmp commands
  Both commands take the QCryptoKeyManageOptions
  the x-blockdev-update-encryption is meant for non destructive addition
  of key slots / whatever the encryption driver supports in the future

  x-blockdev-erase-encryption is meant for destructive encryption key erase,
  in some cases even without way to recover the data.


* bdrv_setup_encryption callback in the block driver
  This callback does both the above functions with 'action' parameter

* QCryptoKeyManageOptions with set of options that drivers can use for encryption managment
  Currently it has all the options that LUKS needs, and later it can be extended
  (via union) to support more encryption drivers if needed

* blk_setup_encryption / bdrv_setup_encryption - the usual block layer wrappers.
  Note that bdrv_setup_encryption takes BlockDriverState and not BdrvChild,
  for the ease of use from the qmp code. It is not expected that this function
  will be used by anything but qmp and qemu-img code


Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
 block/block-backend.c          |  9 ++++++++
 block/io.c                     | 24 ++++++++++++++++++++
 blockdev.c                     | 40 ++++++++++++++++++++++++++++++++++
 include/block/block.h          | 12 ++++++++++
 include/block/block_int.h      | 11 ++++++++++
 include/sysemu/block-backend.h |  7 ++++++
 qapi/block-core.json           | 36 ++++++++++++++++++++++++++++++
 qapi/crypto.json               | 26 ++++++++++++++++++++++
 8 files changed, 165 insertions(+)

diff --git a/block/block-backend.c b/block/block-backend.c
index 0056b526b8..1b75f28d0c 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -2284,3 +2284,12 @@ const BdrvChild *blk_root(BlockBackend *blk)
 {
     return blk->root;
 }
+
+int blk_setup_encryption(BlockBackend *blk,
+                         enum BlkSetupEncryptionAction action,
+                         QCryptoEncryptionSetupOptions *options,
+                         bool force,
+                         Error **errp)
+{
+    return bdrv_setup_encryption(blk->root->bs, action, options, force, errp);
+}
diff --git a/block/io.c b/block/io.c
index 06305c6ea6..50090afe68 100644
--- a/block/io.c
+++ b/block/io.c
@@ -3256,3 +3256,27 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
 
     return tco.ret;
 }
+
+
+int bdrv_setup_encryption(BlockDriverState *bs,
+                          enum BlkSetupEncryptionAction action,
+                          QCryptoEncryptionSetupOptions *options,
+                          bool force,
+                          Error **errp)
+{
+    Error *local_err = NULL;
+    int ret;
+
+    if (!(bs->open_flags & BDRV_O_RDWR)) {
+        error_setg(errp, "Can't do key management on read only block device");
+        return -ENOTSUP;
+    }
+
+    ret = bs->drv->bdrv_setup_encryption(bs, action, options, force,
+                                         &local_err);
+    if (ret) {
+        error_propagate(errp, local_err);
+        return ret;
+    }
+    return 0;
+}
diff --git a/blockdev.c b/blockdev.c
index 4d141e9a1f..27be251656 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -4563,6 +4563,46 @@ void qmp_block_latency_histogram_set(
     }
 }
 
+void qmp_x_blockdev_update_encryption(const char *node_name,
+                                      bool has_force, bool force,
+                                      QCryptoEncryptionSetupOptions *options,
+                                      Error **errp)
+{
+    BlockDriverState *bs = bdrv_find_node(node_name);
+    Error *local_error = NULL;
+
+    if (!bs) {
+        error_setg(errp, "Cannot find node %s", node_name);
+        return;
+    }
+
+    if (bdrv_setup_encryption(bs, BLK_UPDATE_ENCRYPTION, options,
+                              has_force ? force : false, &local_error)) {
+        error_propagate(errp, local_error);
+    }
+}
+
+
+void qmp_x_blockdev_erase_encryption(const char *node_name,
+                                     bool has_force, bool force,
+                                     QCryptoEncryptionSetupOptions *options,
+                                     Error **errp)
+{
+    BlockDriverState *bs = bdrv_find_node(node_name);
+    Error *local_error = NULL;
+
+    if (!bs) {
+        error_setg(errp, "Cannot find node %s", node_name);
+        return;
+    }
+
+    if (bdrv_setup_encryption(bs, BLK_ERASE_ENCRYPTION, options,
+                              has_force ? force : false, &local_error)) {
+            error_propagate(errp, local_error);
+        }
+}
+
+
 QemuOptsList qemu_common_drive_opts = {
     .name = "drive",
     .head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head),
diff --git a/include/block/block.h b/include/block/block.h
index 50a07c1c33..b55ef4c416 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -276,6 +276,12 @@ enum {
     DEFAULT_PERM_UNCHANGED      = BLK_PERM_ALL & ~DEFAULT_PERM_PASSTHROUGH,
 };
 
+enum BlkSetupEncryptionAction {
+    BLK_UPDATE_ENCRYPTION,
+    BLK_ERASE_ENCRYPTION,
+
+};
+
 char *bdrv_perm_names(uint64_t perm);
 
 /* disk I/O throttling */
@@ -348,6 +354,12 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
 int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
                   Error **errp);
 
+int bdrv_setup_encryption(BlockDriverState *bs,
+                          enum BlkSetupEncryptionAction action,
+                          QCryptoEncryptionSetupOptions *options,
+                          bool force,
+                          Error **errp);
+
 int64_t bdrv_nb_sectors(BlockDriverState *bs);
 int64_t bdrv_getlength(BlockDriverState *bs);
 int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 3aa1e832a8..64c71fe269 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -556,6 +556,16 @@ struct BlockDriver {
     void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host);
     QLIST_ENTRY(BlockDriver) list;
 
+
+    /* Manage encryption keys on the block device */
+    int (*bdrv_setup_encryption)(BlockDriverState *bs,
+                                  enum BlkSetupEncryptionAction action,
+                                  QCryptoEncryptionSetupOptions *options,
+                                  bool force,
+                                  Error **errp);
+
+
+
     /* Pointer to a NULL-terminated array of names of strong options
      * that can be specified for bdrv_open(). A strong option is one
      * that changes the data of a BDS.
@@ -1271,4 +1281,5 @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, uint64_t src_offset,
 
 int refresh_total_sectors(BlockDriverState *bs, int64_t hint);
 
+
 #endif /* BLOCK_INT_H */
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 733c4957eb..18e98499fd 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -262,4 +262,11 @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
 
 const BdrvChild *blk_root(BlockBackend *blk);
 
+
+int blk_setup_encryption(BlockBackend *blk,
+                         enum BlkSetupEncryptionAction action,
+                         QCryptoEncryptionSetupOptions *options,
+                         bool force,
+                         Error **errp);
+
 #endif
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 0d43d4f37c..53ed411eed 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -5327,3 +5327,39 @@
   'data' : { 'node-name': 'str',
              'iothread': 'StrOrNull',
              '*force': 'bool' } }
+
+
+##
+# @x-blockdev-update-encryption:
+#
+# Update the encryption keys for an encrypted block device
+#
+# @node-name: 	  Name of the blockdev to operate on
+# @force:         Disable safety checks (use with care)
+# @options:       Driver specific options
+#
+
+# Since: 4.2
+##
+{ 'command': 'x-blockdev-update-encryption',
+  'data': { 'node-name' : 'str',
+            '*force' : 'bool',
+            'options': 'QCryptoEncryptionSetupOptions' } }
+
+##
+# @x-blockdev-erase-encryption:
+#
+# Erase the encryption keys for an encrypted block device
+#
+# @node-name: 	  Name of the blockdev to operate on
+# @force:         Disable safety checks (use with care)
+# @options:       Driver specific options
+#
+# Returns: @QCryptoKeyManageResult
+#
+# Since: 4.2
+##
+{ 'command': 'x-blockdev-erase-encryption',
+  'data': { 'node-name' : 'str',
+            '*force' : 'bool',
+            'options': 'QCryptoEncryptionSetupOptions' } }
diff --git a/qapi/crypto.json b/qapi/crypto.json
index b2a4cff683..69e8b086db 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -309,3 +309,29 @@
   'base': 'QCryptoBlockInfoBase',
   'discriminator': 'format',
   'data': { 'luks': 'QCryptoBlockInfoLUKS' } }
+
+
+##
+# @QCryptoEncryptionSetupOptions:
+#
+# Driver specific options for encryption key management.
+#
+# @key-secret: the ID of a QCryptoSecret object providing the password
+#              to add or to erase (optional for erase)
+#
+# @old-key-secret: the ID of a QCryptoSecret object providing the password
+#                  that can currently unlock the image
+#
+# @slot: Key slot to update/erase
+#        (optional, for update will select a free slot,
+#        for erase will erase all slots that match the password)
+#
+# @iter-time: number of milliseconds to spend in
+#             PBKDF passphrase processing. Currently defaults to 2000
+# Since: 4.2
+##
+{ 'struct': 'QCryptoEncryptionSetupOptions',
+  'data': { '*key-secret': 'str',
+            '*old-key-secret': 'str',
+            '*slot': 'int',
+            '*iter-time': 'int' } }
-- 
2.17.2



  parent reply	other threads:[~2019-08-14 20:25 UTC|newest]

Thread overview: 87+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-14 20:22 [Qemu-devel] [PATCH 00/13] RFC: luks/encrypted qcow2 key management Maxim Levitsky
2019-08-14 20:22 ` [Qemu-devel] [PATCH 01/13] block-crypto: misc refactoring Maxim Levitsky
2019-08-20 16:38   ` Max Reitz
2019-08-22  0:05     ` Maxim Levitsky
2019-08-22 14:34       ` Max Reitz
2019-08-22 15:04         ` Maxim Levitsky
2019-08-21 15:39   ` Daniel P. Berrangé
2019-08-22  0:08     ` Maxim Levitsky
2019-08-14 20:22 ` [Qemu-devel] [PATCH 02/13] qcrypto-luks: " Maxim Levitsky
2019-08-15 21:40   ` [Qemu-devel] [Qemu-block] " John Snow
2019-08-19 14:21     ` Maxim Levitsky
2019-08-22 10:29     ` Daniel P. Berrangé
2019-08-22 11:04       ` Maxim Levitsky
2019-08-22 11:10         ` Daniel P. Berrangé
2019-08-22 11:13           ` Maxim Levitsky
2019-08-20 17:36   ` [Qemu-devel] " Max Reitz
2019-08-21 23:59     ` Maxim Levitsky
2019-08-22 14:32       ` Max Reitz
2019-08-25 10:46         ` Maxim Levitsky
2019-08-14 20:22 ` [Qemu-devel] [PATCH 03/13] qcrypto-luks: refactoring: extract load/store/check/parse header functions Maxim Levitsky
2019-08-20 18:01   ` Max Reitz
2019-08-21 22:43     ` Maxim Levitsky
2019-08-22 10:32       ` Daniel P. Berrangé
2019-08-22 10:57         ` Maxim Levitsky
2019-08-22 10:34       ` Daniel P. Berrangé
2019-08-25 14:11         ` Maxim Levitsky
2019-08-22 10:38   ` Daniel P. Berrangé
2019-08-25 14:09     ` Maxim Levitsky
2019-08-14 20:22 ` [Qemu-devel] [PATCH 04/13] qcrypto-luks: refactoring: simplify the math used for keyslot locations Maxim Levitsky
2019-08-22 10:47   ` Daniel P. Berrangé
2019-08-25 14:30     ` Maxim Levitsky
2019-08-14 20:22 ` [Qemu-devel] [PATCH 05/13] qcrypto-luks: clear the masterkey and password before freeing them always Maxim Levitsky
2019-08-20 18:12   ` Max Reitz
2019-08-21 22:40     ` Maxim Levitsky
2019-08-22 10:49     ` Daniel P. Berrangé
2019-08-22 10:56       ` Maxim Levitsky
2019-08-25 15:31         ` Maxim Levitsky
2019-08-25 17:15           ` Maxim Levitsky
2019-08-27  8:55           ` Daniel P. Berrangé
2019-08-21 23:01   ` [Qemu-devel] [Qemu-block] " Nir Soffer
2019-08-21 23:11     ` Maxim Levitsky
2019-08-14 20:22 ` [Qemu-devel] [PATCH 06/13] qcrypto-luks: implement more rigorous header checking Maxim Levitsky
2019-08-22 11:04   ` Daniel P. Berrangé
2019-08-25 15:40     ` Maxim Levitsky
2019-08-25 16:08       ` Maxim Levitsky
2019-08-26 13:31         ` Eric Blake
2019-08-26 13:39           ` Maxim Levitsky
2019-08-27  8:56         ` Daniel P. Berrangé
2019-08-14 20:22 ` Maxim Levitsky [this message]
2019-08-20 18:27   ` [Qemu-devel] [PATCH 07/13] block: add manage-encryption command (qmp and blockdev) Max Reitz
2019-08-21 22:32     ` Maxim Levitsky
2019-08-22 11:14     ` Daniel P. Berrangé
2019-08-21 11:47   ` Markus Armbruster
2019-08-21 22:24     ` Maxim Levitsky
2019-08-22 14:07       ` Markus Armbruster
2019-08-25 16:42         ` Maxim Levitsky
2019-08-14 20:22 ` [Qemu-devel] [PATCH 08/13] qcrypto: add the plumbing for encryption management Maxim Levitsky
2019-08-22 11:16   ` Daniel P. Berrangé
2019-08-22 11:47     ` Maxim Levitsky
2019-08-22 11:49       ` Daniel P. Berrangé
2019-08-14 20:22 ` [Qemu-devel] [PATCH 09/13] qcrypto-luks: implement the encryption key management Maxim Levitsky
2019-08-22 11:27   ` Daniel P. Berrangé
2019-08-25 17:01     ` Maxim Levitsky
2019-08-14 20:22 ` [Qemu-devel] [PATCH 10/13] block/crypto: " Maxim Levitsky
2019-08-22 11:29   ` Daniel P. Berrangé
2019-08-22 11:36     ` Maxim Levitsky
2019-08-14 20:22 ` [Qemu-devel] [PATCH 11/13] block/qcow2: implement the encryption key managment Maxim Levitsky
2019-08-14 20:22 ` [Qemu-devel] [PATCH 12/13] qemu-img: implement key management Maxim Levitsky
2019-08-20 18:29   ` Max Reitz
2019-08-21 22:33     ` Maxim Levitsky
2019-08-22 11:32     ` Daniel P. Berrangé
2019-08-22 14:42       ` Max Reitz
2019-08-25 17:04         ` Maxim Levitsky
2019-08-14 20:22 ` [Qemu-devel] [PATCH 13/13] iotests : add tests for encryption " Maxim Levitsky
2019-08-14 21:08 ` [Qemu-devel] [PATCH 00/13] RFC: luks/encrypted qcow2 " Eric Blake
2019-08-15  8:49   ` Maxim Levitsky
2019-08-15  9:10   ` Kevin Wolf
2019-08-15 14:18     ` Markus Armbruster
2019-08-15 14:44       ` Maxim Levitsky
2019-08-15 15:00         ` Eric Blake
2019-08-19 12:35           ` Maxim Levitsky
2019-08-21 11:31             ` Markus Armbruster
2019-08-21 13:22               ` Maxim Levitsky
2019-08-20 17:59 ` Max Reitz
2019-08-21 22:00   ` Maxim Levitsky
2019-08-22 11:35 ` Daniel P. Berrangé
2019-08-25 17:10   ` Maxim Levitsky

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=20190814202219.1870-8-mlevitsk@redhat.com \
    --to=mlevitsk@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=fam@euphon.net \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).