[RFC PATCH] efi_loader: clean up uefi secure boot image verification logic
Ilias Apalodimas
ilias.apalodimas at linaro.org
Tue Jan 25 08:25:56 CET 2022
Hi Akashi-san,
On Tue, Jan 25, 2022 at 11:31:07AM +0900, AKASHI Takahiro wrote:
> Hi Ilias,
>
> On Mon, Jan 24, 2022 at 05:36:20PM +0200, Ilias Apalodimas wrote:
> > From: Ilias Apalodimas <apalos at gmail.com>
> >
> > We currently distinguish between signed and non signed PE/COFF
> > executables while trying to authenticate signatures and/or sha256
> > hashes in db and dbx. That code duplication can be avoided.
>
> Thank you for cleaning up the code.
> The change you made here looks good.
> I want you to revise some wordings for clarification.
>
> > On sha256 hashes we don't really care if the image is signed or
> > not.
>
> The sentence above might sound a bit misleading?
I can change that to 'when checking for sha256 hashes in db' or something
along those lines
>
> > The logic can be implemented in
> > 1. Is the sha256 of the image in dbx
>
> Please explicitly mention that the image will be rejected
> in this case unlike the other cases below.
sure
>
> > 2. Is the image signed with a certificate that's found in db and
> > not in dbx
> > 3. The image carries a cert which is signed by a cert in db (and
> > not in dbx, and the image can be verified against the former)
>
> (2) and (3) are the rules applied only if the image is signed. So,
> 2. If the image is signed,
> 2-1. ...
> 2-2. ...
>
> In addition, your (3) should be described in a similar way as (2).
> For instance,
> 3. Is the image signed with a certificate that is carried in
> the image and the cert is signed by another cert in the image
> and so on, or in db (... ).
Doesn't the 'signed against the former' describes the same thing here?
>
> (although it is difficult to describe the logic precisely.)
>
> > 4. Is the sha256 of the image in db
> > So weed out the 'special' case handling unsigned images.
> >
> > While at it move the checking of a hash outside the certificate
> > verification loop which isn't really needed and check for the hash
> > only once.
>
> It might be my preference, but I would like to add
> assert(ret == false);
> before efi_signature_lookup_digest(regs, db) to indicate this is the last
> resort to authenticate the image.
I am not a fan of asserts myself. How about a comment or an EFI_PRINT?
>
> > Also allow a mix of signatures and hashes in db instead
> > of explicitly breaking out the sha verification loop if a signature
> > happens to be added first.
>
> I don't think that your change gives us an extra case of "allowing".
> Please elaborate if I misunderstand something.
This might actually be better of in a separated patch.
The patch for efi_signature.c changes the logic a bit.
Right now when we try to verify a hash and find a non supported algorithm
we stop processing db. But that assumes that the hashes are added first
and the signatures follow.
IOW if you add in db <sha256 hash, esl cert> everything works fine when you
try to authenticate an image with it's hash. If the order is reversed the
code rejects the image (while it shouldn't)
>
> > It's worth noting that (2) only works if the certificate is self
> > signed, but that canb be fixed in a following patch.
>
> Yes, please.
>
> -Takahiro Akashi
Thanks
/Ilias
>
> > Signed-off-by: Ilias Apalodimas <apalos at gmail.com>
> > ---
> > lib/efi_loader/efi_image_loader.c | 84 ++++++-------------------------
> > lib/efi_loader/efi_signature.c | 2 +-
> > 2 files changed, 15 insertions(+), 71 deletions(-)
> >
> > diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
> > index 255613eb72ba..53d54ca42f5c 100644
> > --- a/lib/efi_loader/efi_image_loader.c
> > +++ b/lib/efi_loader/efi_image_loader.c
> > @@ -516,63 +516,16 @@ err:
> > }
> >
> > #ifdef CONFIG_EFI_SECURE_BOOT
> > -/**
> > - * efi_image_unsigned_authenticate() - authenticate unsigned image with
> > - * SHA256 hash
> > - * @regs: List of regions to be verified
> > - *
> > - * If an image is not signed, it doesn't have a signature. In this case,
> > - * its message digest is calculated and it will be compared with one of
> > - * hash values stored in signature databases.
> > - *
> > - * Return: true if authenticated, false if not
> > - */
> > -static bool efi_image_unsigned_authenticate(struct efi_image_regions *regs)
> > -{
> > - struct efi_signature_store *db = NULL, *dbx = NULL;
> > - bool ret = false;
> > -
> > - dbx = efi_sigstore_parse_sigdb(L"dbx");
> > - if (!dbx) {
> > - EFI_PRINT("Getting signature database(dbx) failed\n");
> > - goto out;
> > - }
> > -
> > - db = efi_sigstore_parse_sigdb(L"db");
> > - if (!db) {
> > - EFI_PRINT("Getting signature database(db) failed\n");
> > - goto out;
> > - }
> > -
> > - /* try black-list first */
> > - if (efi_signature_lookup_digest(regs, dbx)) {
> > - EFI_PRINT("Image is not signed and its digest found in \"dbx\"\n");
> > - goto out;
> > - }
> > -
> > - /* try white-list */
> > - if (efi_signature_lookup_digest(regs, db))
> > - ret = true;
> > - else
> > - EFI_PRINT("Image is not signed and its digest not found in \"db\" or \"dbx\"\n");
> > -
> > -out:
> > - efi_sigstore_free(db);
> > - efi_sigstore_free(dbx);
> > -
> > - return ret;
> > -}
> > -
> > /**
> > * efi_image_authenticate() - verify a signature of signed image
> > * @efi: Pointer to image
> > * @efi_size: Size of @efi
> > *
> > - * A signed image should have its signature stored in a table of its PE header.
> > + * An image should have its signature stored in a table of its PE header.
> > * So if an image is signed and only if if its signature is verified using
> > - * signature databases, an image is authenticated.
> > - * If an image is not signed, its validity is checked by using
> > - * efi_image_unsigned_authenticated().
> > + * signature databases or if it's sha256 is found in db an image is
> > + * authenticated.
> > + *
> > * TODO:
> > * When AuditMode==0, if the image's signature is not found in
> > * the authorized database, or is found in the forbidden database,
> > @@ -608,14 +561,7 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
> > if (!efi_image_parse(new_efi, efi_size, ®s, &wincerts,
> > &wincerts_len)) {
> > EFI_PRINT("Parsing PE executable image failed\n");
> > - goto err;
> > - }
> > -
> > - if (!wincerts) {
> > - /* The image is not signed */
> > - ret = efi_image_unsigned_authenticate(regs);
> > -
> > - goto err;
> > + goto out;
> > }
> >
> > /*
> > @@ -624,18 +570,18 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
> > db = efi_sigstore_parse_sigdb(L"db");
> > if (!db) {
> > EFI_PRINT("Getting signature database(db) failed\n");
> > - goto err;
> > + goto out;
> > }
> >
> > dbx = efi_sigstore_parse_sigdb(L"dbx");
> > if (!dbx) {
> > EFI_PRINT("Getting signature database(dbx) failed\n");
> > - goto err;
> > + goto out;
> > }
> >
> > if (efi_signature_lookup_digest(regs, dbx)) {
> > EFI_PRINT("Image's digest was found in \"dbx\"\n");
> > - goto err;
> > + goto out;
> > }
> >
> > /*
> > @@ -729,20 +675,18 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
> > /* try white-list */
> > if (efi_signature_verify(regs, msg, db, dbx)) {
> > ret = true;
> > - break;
> > + goto out;
> > }
> >
> > EFI_PRINT("Signature was not verified by \"db\"\n");
> >
> > - if (efi_signature_lookup_digest(regs, db)) {
> > - ret = true;
> > - break;
> > - }
> > -
> > - EFI_PRINT("Image's digest was not found in \"db\" or \"dbx\"\n");
> > }
> >
> > -err:
> > + if (efi_signature_lookup_digest(regs, db))
> > + ret = true;
> > + else
> > + EFI_PRINT("Image's digest was not found in \"db\" or \"dbx\"\n");
> > +out:
> > efi_sigstore_free(db);
> > efi_sigstore_free(dbx);
> > pkcs7_free_message(msg);
> > diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
> > index 3243e2c60de0..8fa82f8cea4c 100644
> > --- a/lib/efi_loader/efi_signature.c
> > +++ b/lib/efi_loader/efi_signature.c
> > @@ -176,7 +176,7 @@ bool efi_signature_lookup_digest(struct efi_image_regions *regs,
> > if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) {
> > EFI_PRINT("Digest algorithm is not supported: %pUs\n",
> > &siglist->sig_type);
> > - break;
> > + continue;
> > }
> >
> > if (!efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
> > --
> > 2.30.2
> >
More information about the U-Boot
mailing list