From nobody Mon Feb 9 02:52:03 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1565814937; cv=none; d=zoho.com; s=zohoarc; b=H03a9l82cxOyENRrbRi2ffOwIaxAdE7rHe2SHp1wxDu8PvputKczCeVVfDiG3x+Tkz40ulF6loZa8nsgqJEfT0aCBFThpSrx5LfcF67ORJd1RPk25BMhefA1QYYNAbnQIpWcBTQ7961EQQKeZ7RPCHW7Y9J/RMioySHWqbpaewI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1565814937; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=SnB519hPwIfnoV+8+ptkCYcwaAO0mRaCAJBtIB5VnEU=; b=ZiXKXHwnWV635ROESmyYzsSGkqeaazj/1SICIUbKoeRJ/HjGgjGquOIWFdrxL2GcSurfm/7uaPJ3wk5eh4/HPLoo/XrayFOWrZYFZlDQsrEkPS9A9QWoDqEfzfeHOheSzhAMgK1T7xA0DqrVFoitcHwdOKKMeeRJacDqY50qgo4= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1565814937826864.5155909360253; Wed, 14 Aug 2019 13:35:37 -0700 (PDT) Received: from localhost ([::1]:35826 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1hxzza-0000Ef-7C for importer@patchew.org; Wed, 14 Aug 2019 16:35:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33465) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1hxzo2-0004ox-Kd for qemu-devel@nongnu.org; Wed, 14 Aug 2019 16:23:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hxzo1-0004Tk-03 for qemu-devel@nongnu.org; Wed, 14 Aug 2019 16:23:38 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58878) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hxznx-0004Rj-Pr; Wed, 14 Aug 2019 16:23:33 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2069A30ADBA2; Wed, 14 Aug 2019 20:23:33 +0000 (UTC) Received: from maximlenovopc.usersys.redhat.com (unknown [10.35.206.39]) by smtp.corp.redhat.com (Postfix) with ESMTP id AC4EF10016EB; Wed, 14 Aug 2019 20:23:25 +0000 (UTC) From: Maxim Levitsky To: qemu-devel@nongnu.org Date: Wed, 14 Aug 2019 23:22:18 +0300 Message-Id: <20190814202219.1870-13-mlevitsk@redhat.com> In-Reply-To: <20190814202219.1870-1-mlevitsk@redhat.com> References: <20190814202219.1870-1-mlevitsk@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.47]); Wed, 14 Aug 2019 20:23:33 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 12/13] qemu-img: implement key management X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , qemu-block@nongnu.org, Markus Armbruster , Max Reitz , Stefan Hajnoczi , Maxim Levitsky Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Maxim Levitsky --- block/crypto.c | 16 ++++++ block/crypto.h | 3 + qemu-img-cmds.hx | 13 +++++ qemu-img.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+) diff --git a/block/crypto.c b/block/crypto.c index 415b6db041..2fcdf9dd39 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -203,6 +203,22 @@ block_crypto_create_opts_init(QDict *opts, Error **err= p) return ret; } =20 +QCryptoEncryptionSetupOptions * +block_crypto_setup_opts_init(QDict *opts, Error **errp) +{ + Visitor *v; + QCryptoEncryptionSetupOptions *ret; + + v =3D qobject_input_visitor_new_flat_confused(opts, errp); + if (!v) { + return NULL; + } + + visit_type_QCryptoEncryptionSetupOptions(v, NULL, &ret, errp); + + visit_free(v); + return ret; +} =20 static int block_crypto_open_generic(QCryptoBlockFormat format, QemuOptsList *opts_spec, diff --git a/block/crypto.h b/block/crypto.h index b935695e79..ece4d64aef 100644 --- a/block/crypto.h +++ b/block/crypto.h @@ -94,4 +94,7 @@ block_crypto_create_opts_init(QDict *opts, Error **errp); QCryptoBlockOpenOptions * block_crypto_open_opts_init(QDict *opts, Error **errp); =20 +QCryptoEncryptionSetupOptions * +block_crypto_setup_opts_init(QDict *opts, Error **errp); + #endif /* BLOCK_CRYPTO_H */ diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index 1c93e6d185..7816a0adfb 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -19,6 +19,18 @@ STEXI @item amend [--object @var{objectdef}] [--image-opts] [-p] [-q] [-f @var{f= mt}] [-t @var{cache}] -o @var{options} @var{filename} ETEXI =20 +DEF("add_encryption_key", img_add_encryption_key, + "add_encryption_key [--object objectdef] [--image-opts] [--force] -U -= -keydef key_definition filename") +STEXI +@item add_encryption_key [--object @var{objectdef}] [--image-opts] [--forc= e] -U --keydef @var{key_definition} @var{filename} +ETEXI + +DEF("erase_encryption_key", img_erase_encryption_key, + "erase_encryption_key [--object objectdef] [--image-opts] [--force] -U= --keydef key_definition filename") +STEXI +@item erase_encryption_key [--object @var{objectdef}] [--image-opts] [--fo= rce] -U --keydef @var{key_definition} @var{filename} +ETEXI + DEF("bench", img_bench, "bench [-c count] [-d depth] [-f fmt] [--flush-interval=3Dflush_interv= al] [-n] [--no-drain] [-o offset] [--pattern=3Dpattern] [-q] [-s buffer_siz= e] [-S step_size] [-t cache] [-w] [-U] filename") STEXI @@ -97,6 +109,7 @@ STEXI @item resize [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [--p= reallocation=3D@var{prealloc}] [-q] [--shrink] @var{filename} [+ | -]@var{s= ize} ETEXI =20 + STEXI @end table ETEXI diff --git a/qemu-img.c b/qemu-img.c index 79983772de..bc6cd60df1 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -47,6 +47,7 @@ #include "block/blockjob.h" #include "block/qapi.h" #include "crypto/init.h" +#include "block/crypto.h" #include "trace/control.h" =20 #define QEMU_IMG_VERSION "qemu-img version " QEMU_FULL_VERSION \ @@ -70,6 +71,8 @@ enum { OPTION_PREALLOCATION =3D 265, OPTION_SHRINK =3D 266, OPTION_SALVAGE =3D 267, + OPTION_FORCE =3D 268, + OPTION_KEYDEF =3D 269, }; =20 typedef enum OutputFormat { @@ -223,6 +226,14 @@ static QemuOptsList qemu_source_opts =3D { }, }; =20 +static QemuOptsList keydef_opts =3D { + .name =3D "encryption_opts", + .head =3D QTAILQ_HEAD_INITIALIZER(keydef_opts.head), + .desc =3D { + { } + }, +}; + static int GCC_FMT_ATTR(2, 3) qprintf(bool quiet, const char *fmt, ...) { int ret =3D 0; @@ -4997,6 +5008,135 @@ out: return ret; } =20 + +static QemuOptsList keydef_options_list =3D { + .name =3D "encryption", + .head =3D QTAILQ_HEAD_INITIALIZER(keydef_options_list.head), + .desc =3D { + { } + }, +}; + +static int setup_encryption(int argc, char **argv, + enum BlkSetupEncryptionAction action) +{ + static const struct option long_options[] =3D { + {"help", no_argument, 0, 'h'}, + {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, + {"object", required_argument, 0, OPTION_OBJECT}, + {"force", no_argument, 0, OPTION_FORCE}, + {"force-share", no_argument, 0, 'U'}, + {"keydef", required_argument, 0, OPTION_KEYDEF}, + {0, 0, 0, 0} + }; + + BlockBackend *blk =3D NULL; + const char *filename =3D NULL; + bool force_share =3D false; + QemuOpts *keydef_opts =3D NULL; + bool image_opts =3D false; + Error *local_err =3D NULL; + QDict *keydef_dict =3D NULL; + QCryptoEncryptionSetupOptions *qcrypto_options =3D NULL; + bool force =3D false; + + int ret =3D 1; + int c; + + while ((c =3D getopt_long(argc, argv, "hU:", long_options, NULL)) !=3D= -1) { + switch (c) { + case '?': + case 'h': + help(); + break; + case 'U': + force_share =3D true; + break; + + case OPTION_KEYDEF: + if (keydef_opts) { + error_report("Only single --keydef argument is allowed."); + goto out; + } + + keydef_opts =3D qemu_opts_parse_noisily(&keydef_options_list, + optarg, false); + if (!keydef_opts) { + goto out; + } + break; + + case OPTION_OBJECT: { + QemuOpts *object_opts =3D qemu_opts_parse_noisily(&qemu_object= _opts, + optarg, true); + if (!object_opts) { + goto out; + } + break; + } + case OPTION_IMAGE_OPTS: + image_opts =3D true; + break; + case OPTION_FORCE: + force =3D true; + break; + break; + } + } + + if (qemu_opts_foreach(&qemu_object_opts, + user_creatable_add_opts_foreach, + NULL, &error_fatal)) { + goto out; + } + + if (argc - optind > 1) { + error_report("At most one filename argument is allowed."); + goto out; + } else if (argc - optind =3D=3D 1) { + filename =3D argv[optind]; + } else { + error_report("filename is required"); + goto out; + + } + + blk =3D img_open(image_opts, filename, NULL, BDRV_O_RDWR, + false, false, force_share); + if (!blk) { + goto out; + } + + keydef_dict =3D qemu_opts_to_qdict(keydef_opts, NULL); + qcrypto_options =3D block_crypto_setup_opts_init(keydef_dict, &local_e= rr); + if (!qcrypto_options) { + error_report_err(local_err); + goto out; + } + + if (blk_setup_encryption(blk, action, qcrypto_options, force, &local_e= rr)) { + error_report_err(local_err); + goto out; + } + ret =3D 0; +out: + qemu_opts_del(keydef_opts); + qobject_unref(keydef_dict); + qapi_free_QCryptoEncryptionSetupOptions(qcrypto_options); + blk_unref(blk); + return ret; +} + +static int img_add_encryption_key(int argc, char **argv) +{ + return setup_encryption(argc, argv, BLK_UPDATE_ENCRYPTION); +} + +static int img_erase_encryption_key(int argc, char **argv) +{ + return setup_encryption(argc, argv, BLK_ERASE_ENCRYPTION); +} + static const img_cmd_t img_cmds[] =3D { #define DEF(option, callback, arg_string) \ { option, callback }, --=20 2.17.2