[RFC PATCH] efi_loader: clean up uefi secure boot image verification logic
Heinrich Schuchardt
xypron.glpk at gmx.de
Mon Jan 24 18:17:55 CET 2022
On 1/24/22 16:36, 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.
> On sha256 hashes we don't really care if the image is signed or
> not. The logic can be implemented in
> 1. Is the sha256 of the image in dbx
> 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)
> 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. 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.
>
> It's worth noting that (2) only works if the certificate is self
> signed, but that canb be fixed in a following patch.
>
> 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.
The signature must be stored in the "Certificate Table". See PE-COFF
specification. The PE header only contains the Optional Header Data
Directory that points to the table.
Best regards
Heinrich
> * 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)) {
More information about the U-Boot
mailing list