All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sughosh Ganu <sughosh.ganu@linaro.org>
To: u-boot@lists.denx.de
Subject: [PATCH 6/8] efi: capsule: Add support for uefi capsule authentication
Date: Sun, 10 May 2020 16:56:21 +0530	[thread overview]
Message-ID: <CADg8p97inyPtK=RiLBHneDTmH0cL4J4JQ7wqqUaTTOfuhmLbmA@mail.gmail.com> (raw)
In-Reply-To: <20200508004238.GB31466@laputa>

On Fri, 8 May 2020 at 06:12, Akashi Takahiro <takahiro.akashi@linaro.org>
wrote:

> On Thu, May 07, 2020 at 05:20:35PM +0530, Sughosh Ganu wrote:
> > On Thu, 7 May 2020 at 13:49, Akashi Takahiro <takahiro.akashi@linaro.org
> >
> > wrote:
> >
> > > Sughosh,
> > >
> > > On Thu, Apr 30, 2020 at 11:06:28PM +0530, Sughosh Ganu wrote:
> > > > Add support for authenticating uefi capsules. Most of the signature
> > > > verification functionality is shared with the uefi secure boot
> > > > feature.
> > > >
> > > > The root certificate containing the public key used for the signature
> > > > verification is stored as an efi variable, similar to the variables
> > > > used for uefi secure boot. The root certificate is stored as an efi
> > > > signature list(esl) file -- this file contains the x509 certificate
> > > > which is the root certificate.
> > > >
> > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > ---
> > > >  include/efi_api.h              |  17 +++++
> > > >  include/efi_loader.h           |   8 ++-
> > > >  lib/efi_loader/Kconfig         |  16 +++++
> > > >  lib/efi_loader/efi_capsule.c   | 126
> +++++++++++++++++++++++++++++++++
> > > >  lib/efi_loader/efi_signature.c |   4 +-
> > > >  5 files changed, 167 insertions(+), 4 deletions(-)
> > > >
> > >
> >
> > <snip>
> >
> > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > index ec2976ceba..245deabbed 100644
> > > > --- a/lib/efi_loader/Kconfig
> > > > +++ b/lib/efi_loader/Kconfig
> > > > @@ -110,6 +110,22 @@ config EFI_CAPSULE_FIT_DEVICE
> > > >       help
> > > >         Define storage device, say 1:1, for storing FIT image
> > > >
> > > > +config EFI_CAPSULE_AUTHENTICATE
> > > > +     bool "Update Capsule authentication"
> > > > +     depends on EFI_HAVE_CAPSULE_SUPPORT
> > > > +     depends on EFI_CAPSULE_ON_DISK
> > > > +     depends on EFI_FIRMWARE_MANAGEMENT_PROTOCOL
> > >
> > > Do we need those two configurations?
> > >
> >
> > Right, I think we can just do with the EFI_CAPSULE_ON_DISK. Will change.
>
> Actually I don't think we need EFI_CAPSULE_ON_DISK neither.
>

We at least need EFI_HAVE_CAPSULE_SUPPORT, isn't it.


>
> >
> > >
> > > > +     select SHA256
> > > > +     select RSA
> > > > +     select RSA_VERIFY
> > > > +     select RSA_VERIFY_WITH_PKEY
> > > > +     select X509_CERTIFICATE_PARSER
> > > > +     select PKCS7_MESSAGE_PARSER
> > > > +     default n
> > > > +     help
> > > > +       Select this option if you want to enable capsule
> > > > +       authentication
> > > > +
> > > >  config EFI_DEVICE_PATH_TO_TEXT
> > > >       bool "Device path to text protocol"
> > > >       default y
> > > > diff --git a/lib/efi_loader/efi_capsule.c
> b/lib/efi_loader/efi_capsule.c
> > > > index 931d363edc..a265d36ff0 100644
> > > > --- a/lib/efi_loader/efi_capsule.c
> > > > +++ b/lib/efi_loader/efi_capsule.c
> > > > @@ -12,6 +12,10 @@
> > > >  #include <malloc.h>
> > > >  #include <mapmem.h>
> > > >  #include <sort.h>
> > > > +#include "../lib/crypto/pkcs7_parser.h"
> > > > +
> > >
> > > As you might notice, the location was changed by
> > > my recent patch.
> > >
> >
> > Will check and update.
> >
> >
> > >
> > > > +#include <crypto/pkcs7.h>
> > > > +#include <linux/err.h>
> > > >
> > > >  const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
> > > >  static const efi_guid_t efi_guid_firmware_management_capsule_id =
> > > > @@ -245,6 +249,128 @@ out:
> > > >
> > > >       return ret;
> > > >  }
> > > > +
> > > > +#if defined(CONFIG_EFI_CAPSULE_AUTHENTICATE)
> > > > +
> > > > +const efi_guid_t efi_guid_capsule_root_cert_guid =
> > > > +     EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
> > > > +
> > > > +__weak u16 *efi_get_truststore_name(void)
> > > > +{
> > > > +     return L"CRT";
> > >
> > > This variable is not defined by UEFI specification, isn't it?
> > > How can this variable be protected?
> > >
> >
> > This is not part of the uefi specification. The uefi specification does
> not
> > mandate any particular method for storing the root certificate to be used
> > for capsule authentication. The edk2 code gets the root certificate
> through
> > a pcd. I had tried using KEK variable for storing the root certificate,
> and
> > had also come up with an implementation. However, the addition/deletion
> and
> > update of the secure variables is very closely tied with the secure boot
> > feature and the secure boot state of the system, which is the reason why
> i
> > dropped that solution and used a separate variable, which can be defined
> by
> > the vendor to store the root certificate.
>
> My concern is that, without any protection, the value of this variable
> can be modified by a mal-user.
> (One simple solution would be to set this variable read-only.)
>

Yes, that is one solution. This will also be taken care of in a scenario
where the platform is booted in a trusted chain, and the env is also part
of the image which gets verified by the previous stage(e.g BL2) before
jumping to the u-boot image. If there is any change in the u-boot image,
that would result in a boot failure -- but that would need the env to be
part of the u-boot image which gets verified. I will explore making this
variable read-only.


> >
> > >
> > > > +}
> > > > +
> > > > +__weak const efi_guid_t *efi_get_truststore_vendor(void)
> > > > +{
> > > > +
> > > > +     return &efi_guid_capsule_root_cert_guid;
> > > > +}
> > > > +
> > > > +/**
> > > > + * efi_capsule_authenticate() - Authenticate a uefi capsule
> > > > + *
> > > > + * @capsule:         Capsule file with the authentication
> > > > + *                   header
> > > > + * @capsule_size:    Size of the entire capsule
> > > > + * @image:           pointer to the image payload minus the
> > > > + *                   authentication header
> > > > + * @image_size:              size of the image payload
> > > > + *
> > > > + * Authenticate the capsule signature with the public key contained
> > > > + * in the root certificate stored as an efi environment variable
> > > > + *
> > > > + * Return: EFI_SUCCESS on successfull authentication or
> > > > + *      EFI_SECURITY_VIOLATION on authentication failure
> > > > + */
> > > > +efi_status_t efi_capsule_authenticate(const void *capsule,
> > > > +                                   efi_uintn_t capsule_size,
> > > > +                                   void **image, efi_uintn_t
> > > *image_size)
> > > > +{
> > > > +     uint64_t monotonic_count;
> > > > +     struct efi_signature_store *truststore;
> > > > +     struct pkcs7_message *capsule_sig;
> > > > +     struct efi_image_regions *regs;
> > > > +     struct efi_firmware_image_authentication *auth_hdr;
> > > > +     efi_status_t status;
> > > > +
> > > > +     status = EFI_SECURITY_VIOLATION;
> > > > +     capsule_sig = NULL;
> > > > +     truststore = NULL;
> > > > +     regs = NULL;
> > > > +
> > > > +     /* Sanity checks */
> > > > +     if (capsule == NULL || capsule_size == 0)
> > > > +             goto out;
> > > > +
> > > > +     auth_hdr = (struct efi_firmware_image_authentication *)capsule;
> > > > +     if (capsule_size < sizeof(*auth_hdr))
> > > > +             goto out;
> > > > +
> > > > +     if (auth_hdr->auth_info.hdr.dwLength <=
> > > > +         offsetof(struct win_certificate_uefi_guid, cert_data))
> > > > +             goto out;
> > > > +
> > > > +     if (guidcmp(&auth_hdr->auth_info.cert_type,
> > > &efi_guid_cert_type_pkcs7))
> > > > +             goto out;
> > > > +
> > > > +     *image = (uint8_t *)capsule +
> sizeof(auth_hdr->monotonic_count) +
> > > > +             auth_hdr->auth_info.hdr.dwLength;
> > > > +     *image_size = capsule_size - auth_hdr->auth_info.hdr.dwLength -
> > > > +
>  sizeof(auth_hdr->monotonic_count);
> > > > +     memcpy(&monotonic_count, &auth_hdr->monotonic_count,
> > > > +            sizeof(monotonic_count));
> > > > +
> > > > +     /* data to be digested */
> > > > +     regs = calloc(sizeof(*regs) + sizeof(struct image_region) * 2,
> 1);
> > > > +     if (!regs)
> > > > +             goto out;
> > > > +
> > > > +     regs->max = 2;
> > > > +     efi_image_region_add(regs, (uint8_t *)*image,
> > > > +                          (uint8_t *)*image + *image_size, 1);
> > > > +
> > > > +     efi_image_region_add(regs, (uint8_t *)&monotonic_count,
> > > > +                          (uint8_t *)&monotonic_count +
> > > sizeof(monotonic_count),
> > > > +                          1);
> > >
> > > Is the order of regions to be calculated correct?
> > > It seems that 'monotonic_count' precedes 'image' itself
> > > in a capsule header.
> > >
> >
> > Does that have any impact on the hash value computed.
>
> Not 100% sure, but if it doesn't, it cannot guarantee uniqueness
> of digest values.
>

Will check this.

-sughosh


>
> Thanks,
> -Takahiro Akashi
>
> > I did not see any
> > difference in the hash value computed due to the order in which the
> regions
> > are added. But that could be because of the way the hash value gets
> > computed at the time of building the capsule. I will check this out.
> >
> >
> > >
> > > > +
> > > > +     capsule_sig =
> efi_parse_pkcs7_header(auth_hdr->auth_info.cert_data,
> > > > +
> > > auth_hdr->auth_info.hdr.dwLength
> > > > +                                          -
> > > sizeof(auth_hdr->auth_info));
> > > > +     if (IS_ERR(capsule_sig)) {
> > >
> > > As Patrick reported, ex-efi_variable_parse_signature()
> > > returns NULL on error cases, this check should be "!capsule_sig."
> > >
> >
> > Will change.
> >
> > -sughosh
>

  reply	other threads:[~2020-05-10 11:26 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-30 17:36 [PATCH 0/8] qemu: arm64: Add support for uefi firmware management protocol routines Sughosh Ganu
2020-04-30 17:36 ` [PATCH 1/8] semihosting: Change semihosting file operation functions into global symbols Sughosh Ganu
2020-05-11  3:05   ` Akashi Takahiro
2020-05-18 16:34     ` Heinrich Schuchardt
2020-04-30 17:36 ` [PATCH 2/8] semihosting: Add support for writing to a file Sughosh Ganu
2020-05-18 17:04   ` Heinrich Schuchardt
2020-04-30 17:36 ` [PATCH 3/8] qemu: arm64: Add support for efi firmware management protocol routines Sughosh Ganu
2020-04-30 18:39   ` Heinrich Schuchardt
2020-04-30 19:13     ` Sughosh Ganu
2020-05-01  9:33       ` Heinrich Schuchardt
2020-05-05 11:15         ` Grant Likely
2020-05-05 17:04           ` Heinrich Schuchardt
2020-05-05 17:23             ` Grant Likely
2020-05-05 17:57               ` Heinrich Schuchardt
2020-05-06 15:04                 ` Grant Likely
2020-05-09 10:04                   ` Heinrich Schuchardt
2020-05-10 11:59                     ` Sughosh Ganu
2020-05-18 17:14                     ` Grant Likely
2020-05-07  2:33         ` Akashi Takahiro
2020-05-07 20:47           ` Heinrich Schuchardt
2020-05-07 23:36             ` Akashi Takahiro
2020-04-30 17:36 ` [PATCH 4/8] efi_loader: Allow parsing of miscellaneous signature database variables Sughosh Ganu
2020-04-30 17:36 ` [PATCH 5/8] efi_loader: Make the pkcs7 header parsing function an extern Sughosh Ganu
2020-05-07  7:34   ` Akashi Takahiro
2020-05-07 11:18     ` Sughosh Ganu
2020-05-08  0:51       ` Akashi Takahiro
2020-05-10 11:20         ` Sughosh Ganu
2020-04-30 17:36 ` [PATCH 6/8] efi: capsule: Add support for uefi capsule authentication Sughosh Ganu
2020-05-07  8:19   ` Akashi Takahiro
2020-05-07 11:50     ` Sughosh Ganu
2020-05-08  0:42       ` Akashi Takahiro
2020-05-10 11:26         ` Sughosh Ganu [this message]
2020-05-11  2:45           ` Akashi Takahiro
2020-04-30 17:36 ` [PATCH 7/8] qemu: arm64: " Sughosh Ganu
2020-04-30 17:36 ` [PATCH 8/8] qemu: arm64: Add documentation for capsule update Sughosh Ganu
2020-04-30 18:37   ` Heinrich Schuchardt
2020-04-30 19:08     ` Sughosh Ganu
2020-04-30 19:27       ` Tom Rini
2020-05-01  5:47         ` Sughosh Ganu
2020-05-07  2:10           ` Akashi Takahiro
2020-05-07 20:52             ` Heinrich Schuchardt

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='CADg8p97inyPtK=RiLBHneDTmH0cL4J4JQ7wqqUaTTOfuhmLbmA@mail.gmail.com' \
    --to=sughosh.ganu@linaro.org \
    --cc=u-boot@lists.denx.de \
    /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.