All of lore.kernel.org
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: "Philippe Mathieu-Daudé" <philmd@redhat.com>
Cc: Laszlo Ersek <lersek@redhat.com>,
	Gerd Hoffmann <kraxel@redhat.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v3 2/4] hw/firmware: Add Edk2Crypto and edk2_add_host_crypto_policy()
Date: Mon, 11 Mar 2019 08:26:44 +0100	[thread overview]
Message-ID: <8736ntswgb.fsf@dusky.pond.sub.org> (raw)
In-Reply-To: <20190310004749.27029-3-philmd@redhat.com> ("Philippe Mathieu-Daudé"'s message of "Sun, 10 Mar 2019 01:47:47 +0100")

Philippe Mathieu-Daudé <philmd@redhat.com> writes:

> The Edk2Crypto object is used to hold configuration values specific
> to EDK2.
>
> The edk2_add_host_crypto_policy() function loads crypto policies
> from the host, and register them as fw_cfg named file items.
> So far only the 'https' policy is supported.
>
> A usercase example is the 'HTTPS Boof' feature of OVMF [*].
>
> Usage example:
>
>   $ qemu-system-x86_64 \
>       --object edk2_crypto,id=https,\
>               ciphers=/etc/crypto-policies/back-ends/openssl.config,\
>               cacerts=/etc/pki/ca-trust/extracted/edk2/cacerts.bin
>
> (On Fedora these files are provided by the ca-certificates and
> crypto-policies packages).
>
> [*]: https://github.com/tianocore/edk2/blob/master/OvmfPkg/README
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> ---
> v3:
> - '-object' -> '--object' in commit description (Eric)
> - reworded the 'TODO: g_free' comment
> ---
>  MAINTAINERS                             |   8 ++
>  hw/Makefile.objs                        |   1 +
>  hw/firmware/Makefile.objs               |   1 +
>  hw/firmware/uefi_edk2_crypto_policies.c | 177 ++++++++++++++++++++++++
>  include/hw/firmware/uefi_edk2.h         |  28 ++++
>  5 files changed, 215 insertions(+)
>  create mode 100644 hw/firmware/Makefile.objs
>  create mode 100644 hw/firmware/uefi_edk2_crypto_policies.c
>  create mode 100644 include/hw/firmware/uefi_edk2.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index cf09a4c127..70122b3d0d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2206,6 +2206,14 @@ F: include/hw/i2c/smbus_master.h
>  F: include/hw/i2c/smbus_slave.h
>  F: include/hw/i2c/smbus_eeprom.h
>  
> +EDK2 Firmware
> +M: Laszlo Ersek <lersek@redhat.com>
> +M: Philippe Mathieu-Daudé <philmd@redhat.com>
> +S: Maintained
> +F: docs/interop/firmware.json
> +F: hw/firmware/uefi_edk2_crypto_policies.c
> +F: include/hw/firmware/uefi_edk2.h
> +
>  Usermode Emulation
>  ------------------
>  Overall
> diff --git a/hw/Makefile.objs b/hw/Makefile.objs
> index 82aa7fab8e..2b075aa1e0 100644
> --- a/hw/Makefile.objs
> +++ b/hw/Makefile.objs
> @@ -8,6 +8,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += char/
>  devices-dirs-$(CONFIG_SOFTMMU) += cpu/
>  devices-dirs-$(CONFIG_SOFTMMU) += display/
>  devices-dirs-$(CONFIG_SOFTMMU) += dma/
> +devices-dirs-$(CONFIG_SOFTMMU) += firmware/
>  devices-dirs-$(CONFIG_SOFTMMU) += gpio/
>  devices-dirs-$(CONFIG_HYPERV) += hyperv/
>  devices-dirs-$(CONFIG_I2C) += i2c/
> diff --git a/hw/firmware/Makefile.objs b/hw/firmware/Makefile.objs
> new file mode 100644
> index 0000000000..ea1f6d44df
> --- /dev/null
> +++ b/hw/firmware/Makefile.objs
> @@ -0,0 +1 @@
> +common-obj-y += uefi_edk2_crypto_policies.o
> diff --git a/hw/firmware/uefi_edk2_crypto_policies.c b/hw/firmware/uefi_edk2_crypto_policies.c
> new file mode 100644
> index 0000000000..5f88819a50
> --- /dev/null
> +++ b/hw/firmware/uefi_edk2_crypto_policies.c
> @@ -0,0 +1,177 @@
> +/*
> + * UEFI EDK2 Support
> + *
> + * Copyright (c) 2019 Red Hat Inc.
> + *
> + * Author:
> + *  Philippe Mathieu-Daudé <philmd@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qom/object_interfaces.h"
> +#include "hw/firmware/uefi_edk2.h"
> +
> +
> +#define TYPE_EDK2_CRYPTO "edk2_crypto"
> +
> +#define EDK2_CRYPTO_CLASS(klass) \
> +     OBJECT_CLASS_CHECK(Edk2CryptoClass, (klass), \
> +                        TYPE_EDK2_CRYPTO)
> +#define EDK2_CRYPTO_GET_CLASS(obj) \
> +     OBJECT_GET_CLASS(Edk2CryptoClass, (obj), \
> +                      TYPE_EDK2_CRYPTO)
> +#define EDK2_CRYPTO(obj) \
> +     INTERFACE_CHECK(Edk2Crypto, (obj), \
> +                     TYPE_EDK2_CRYPTO)

Uh, should this be OBJECT_CLASS_CHECK()?  TYPE_EDK2_CRYPTO is a
TYPE_OBJECT, not a TYPE_INTERFACE...

> +
> +typedef struct Edk2Crypto {
> +    Object parent_obj;
> +
> +    /*
> +     * Path to the acceptable ciphersuites and the preferred order from
> +     * the host-side crypto policy.
> +     */
> +    char *ciphers_path;
> +
> +    /* Path to the trusted CA certificates configured on the host side. */
> +    char *cacerts_path;
> +} Edk2Crypto;

Bike-shedding: I prefer to call file names file names, and reserve
"path" for search paths.  But it's your shed, not mine.

> +
> +typedef struct Edk2CryptoClass {
> +    ObjectClass parent_class;
> +} Edk2CryptoClass;
> +
> +
> +static void edk2_crypto_prop_set_ciphers(Object *obj, const char *value,
> +                                         Error **errp G_GNUC_UNUSED)
> +{
> +    Edk2Crypto *s = EDK2_CRYPTO(obj);
> +
> +    g_free(s->ciphers_path);
> +    s->ciphers_path = g_strdup(value);
> +}
> +
> +static char *edk2_crypto_prop_get_ciphers(Object *obj,
> +                                          Error **errp G_GNUC_UNUSED)
> +{
> +    Edk2Crypto *s = EDK2_CRYPTO(obj);
> +
> +    return g_strdup(s->ciphers_path);
> +}
> +
> +static void edk2_crypto_prop_set_cacerts(Object *obj, const char *value,
> +                                         Error **errp G_GNUC_UNUSED)
> +{
> +    Edk2Crypto *s = EDK2_CRYPTO(obj);
> +
> +    g_free(s->cacerts_path);
> +    s->cacerts_path = g_strdup(value);
> +}
> +
> +static char *edk2_crypto_prop_get_cacerts(Object *obj,
> +                                          Error **errp G_GNUC_UNUSED)
> +{
> +    Edk2Crypto *s = EDK2_CRYPTO(obj);
> +
> +    return g_strdup(s->cacerts_path);
> +}
> +
> +static void edk2_crypto_finalize(Object *obj)
> +{
> +    Edk2Crypto *s = EDK2_CRYPTO(obj);
> +
> +    g_free(s->ciphers_path);
> +    g_free(s->cacerts_path);
> +}
> +
> +static void edk2_crypto_class_init(ObjectClass *oc, void *data)
> +{
> +    object_class_property_add_str(oc, "ciphers",
> +                                  edk2_crypto_prop_get_ciphers,
> +                                  edk2_crypto_prop_set_ciphers,
> +                                  NULL);
> +    object_class_property_add_str(oc, "cacerts",
> +                                  edk2_crypto_prop_get_cacerts,
> +                                  edk2_crypto_prop_set_cacerts,
> +                                  NULL);
> +}
> +
> +static const TypeInfo edk2_crypto_info = {
> +    .parent = TYPE_OBJECT,
> +    .name = TYPE_EDK2_CRYPTO,
> +    .instance_size = sizeof(Edk2Crypto),
> +    .instance_finalize = edk2_crypto_finalize,
> +    .class_size = sizeof(Edk2CryptoClass),
> +    .class_init = edk2_crypto_class_init,
> +    .interfaces = (InterfaceInfo[]) {
> +        { TYPE_USER_CREATABLE },
> +        { }
> +    }
> +};
> +
> +static void edk2_crypto_register_types(void)
> +{
> +    type_register_static(&edk2_crypto_info);
> +}
> +
> +type_init(edk2_crypto_register_types);
> +
> +static Edk2Crypto *edk2_crypto_by_id(const char *edk_crypto_id, Error **errp)
> +{
> +    Object *obj;
> +    Object *container;
> +
> +    container = object_get_objects_root();
> +    obj = object_resolve_path_component(container,
> +                                        edk_crypto_id);
> +    if (!obj) {
> +        error_setg(errp, "Cannot find EDK2 crypto object ID %s",
> +                   edk_crypto_id);
> +        return NULL;
> +    }
> +
> +    if (!object_dynamic_cast(obj, TYPE_EDK2_CRYPTO)) {
> +        error_setg(errp, "Object '%s' is not a EDK2 crypto subclass",
> +                   edk_crypto_id);
> +        return NULL;
> +    }
> +
> +    return EDK2_CRYPTO(obj);
> +}
> +
> +void edk2_add_host_crypto_policy(FWCfgState *fw_cfg)
> +{
> +    Edk2Crypto *s;
> +
> +    s = edk2_crypto_by_id("https", NULL);
> +    if (!s) {
> +        return;
> +    }
> +
> +    if (s->ciphers_path) {
> +        /*
> +         * Note:
> +         * Unlike with fw_cfg_add_file() where the allocated data has
> +         * to be valid for the lifetime of the FwCfg object, there is
> +         * no such contract interface with fw_cfg_add_file_from_host().

In my review of PATCH 1, I argue there should be.

> +         * It would be easier that the FwCfg object keeps reference of
> +         * its allocated memory and releases it when destroy, but it
> +         * currently doesn't. Meanwhile we simply add this TODO comment.
> +         */
> +        fw_cfg_add_file_from_host(fw_cfg, "etc/edk2/https/ciphers",
> +                                  s->ciphers_path, NULL);
> +    }
> +
> +    if (s->cacerts_path) {
> +        /*
> +         * TODO: g_free the returned pointer
> +         * (see previous comment for ciphers_path in this function).
> +         */

Is it even possible to reolve this TODO?  Is there any point in time
where we can free the returned pointer without leaving a dangling
pointer in @fw_cfg?

> +        fw_cfg_add_file_from_host(fw_cfg, "etc/edk2/https/cacerts",
> +                                  s->cacerts_path, NULL);
> +    }
> +}
> diff --git a/include/hw/firmware/uefi_edk2.h b/include/hw/firmware/uefi_edk2.h
> new file mode 100644
> index 0000000000..e0b2fb160a
> --- /dev/null
> +++ b/include/hw/firmware/uefi_edk2.h
> @@ -0,0 +1,28 @@
> +/*
> + * UEFI EDK2 Support
> + *
> + * Copyright (c) 2019 Red Hat Inc.
> + *
> + * Author:
> + *  Philippe Mathieu-Daudé <philmd@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#ifndef HW_FIRMWARE_UEFI_EDK2_H
> +#define HW_FIRMWARE_UEFI_EDK2_H
> +
> +#include "hw/nvram/fw_cfg.h"
> +
> +/**
> + * edk2_add_host_crypto_policy:
> + * @s: fw_cfg device being modified
> + *
> + * Add a new named file containing the host crypto policy.
> + *
> + * Currently only the 'https' policy is supported.
> + */
> +void edk2_add_host_crypto_policy(FWCfgState *s);

Out of curiosity, what happens if you call this more than once?

> +
> +#endif /* HW_FIRMWARE_UEFI_EDK2_H */

  reply	other threads:[~2019-03-11  7:28 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-10  0:47 [Qemu-devel] [PATCH v3 0/4] fw_cfg: Add edk2_add_host_crypto_policy() Philippe Mathieu-Daudé
2019-03-10  0:47 ` [Qemu-devel] [PATCH v3 1/4] hw/nvram/fw_cfg: Add fw_cfg_add_file_from_host() Philippe Mathieu-Daudé
2019-03-11  7:15   ` Markus Armbruster
2019-03-10  0:47 ` [Qemu-devel] [PATCH v3 2/4] hw/firmware: Add Edk2Crypto and edk2_add_host_crypto_policy() Philippe Mathieu-Daudé
2019-03-11  7:26   ` Markus Armbruster [this message]
2019-03-11 18:27     ` Philippe Mathieu-Daudé
     [not found]   ` <5e2f3651-5f00-0c93-353e-e58f079998e9@redhat.com>
     [not found]     ` <124e54f9-c7e1-0157-61f1-673154872749@redhat.com>
2019-06-20 12:07       ` Philippe Mathieu-Daudé
2019-06-20 13:51         ` Laszlo Ersek
2019-03-10  0:47 ` [Qemu-devel] [PATCH v3 3/4] hw/i386: Use edk2_add_host_crypto_policy() Philippe Mathieu-Daudé
2019-03-10  0:47 ` [Qemu-arm] [PATCH v3 4/4] hw/arm/virt: " Philippe Mathieu-Daudé
2019-03-10  0:47   ` [Qemu-devel] " Philippe Mathieu-Daudé

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=8736ntswgb.fsf@dusky.pond.sub.org \
    --to=armbru@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=lersek@redhat.com \
    --cc=mst@redhat.com \
    --cc=philmd@redhat.com \
    --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.