efi_loader: image_loader: add a missing digest verification for signed PE image
authorAKASHI Takahiro <takahiro.akashi@linaro.org>
Tue, 5 Jul 2022 05:48:14 +0000 (14:48 +0900)
committerHeinrich Schuchardt <heinrich.schuchardt@canonical.com>
Tue, 5 Jul 2022 12:37:16 +0000 (14:37 +0200)
At the last step of PE image authentication, an image's hash value must be
compared with a message digest stored as the content (of SpcPeImageData type)
of pkcs7's contentInfo.

Fixes: commit 4540dabdcaca ("efi_loader: image_loader: support image authentication")
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
lib/efi_loader/Kconfig
lib/efi_loader/efi_image_loader.c

index e2a1a5a..e3f2402 100644 (file)
@@ -366,6 +366,7 @@ config EFI_SECURE_BOOT
        select X509_CERTIFICATE_PARSER
        select PKCS7_MESSAGE_PARSER
        select PKCS7_VERIFY
+       select MSCODE_PARSER
        select EFI_SIGNATURE_SUPPORT
        help
          Select this option to enable EFI secure boot support.
index fe8e4a8..eaf75a5 100644 (file)
@@ -16,6 +16,7 @@
 #include <malloc.h>
 #include <pe.h>
 #include <sort.h>
+#include <crypto/mscode.h>
 #include <crypto/pkcs7_parser.h>
 #include <linux/err.h>
 
@@ -517,6 +518,51 @@ err:
 
 #ifdef CONFIG_EFI_SECURE_BOOT
 /**
+ * efi_image_verify_digest - verify image's message digest
+ * @regs:      Array of memory regions to digest
+ * @msg:       Signature in pkcs7 structure
+ *
+ * @regs contains all the data in a PE image to digest. Calculate
+ * a hash value based on @regs and compare it with a messaged digest
+ * in the content (SpcPeImageData) of @msg's contentInfo.
+ *
+ * Return:     true if verified, false if not
+ */
+static bool efi_image_verify_digest(struct efi_image_regions *regs,
+                                   struct pkcs7_message *msg)
+{
+       struct pefile_context ctx;
+       void *hash;
+       int hash_len, ret;
+
+       const void *data;
+       size_t data_len;
+       size_t asn1hdrlen;
+
+       /* get pkcs7's contentInfo */
+       ret = pkcs7_get_content_data(msg, &data, &data_len, &asn1hdrlen);
+       if (ret < 0 || !data)
+               return false;
+
+       /* parse data and retrieve a message digest into ctx */
+       ret = mscode_parse(&ctx, data, data_len, asn1hdrlen);
+       if (ret < 0)
+               return false;
+
+       /* calculate a hash value of PE image */
+       hash = NULL;
+       if (!efi_hash_regions(regs->reg, regs->num, &hash, ctx.digest_algo,
+                             &hash_len))
+               return false;
+
+       /* match the digest */
+       if (ctx.digest_len != hash_len || memcmp(ctx.digest, hash, hash_len))
+               return false;
+
+       return true;
+}
+
+/**
  * efi_image_authenticate() - verify a signature of signed image
  * @efi:       Pointer to image
  * @efi_size:  Size of @efi
@@ -645,6 +691,9 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
                }
 
                /*
+                * verify signatures in pkcs7's signedInfos which are
+                * to authenticate the integrity of pkcs7's contentInfo.
+                *
                 * NOTE:
                 * UEFI specification defines two signature types possible
                 * in signature database:
@@ -677,12 +726,21 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
                }
 
                /* try white-list */
-               if (efi_signature_verify(regs, msg, db, dbx)) {
+               if (!efi_signature_verify(regs, msg, db, dbx)) {
+                       log_debug("Signature was not verified by \"db\"\n");
+                       continue;
+               }
+
+               /*
+                * now calculate an image's hash value and compare it with
+                * a messaged digest embedded in pkcs7's contentInfo
+                */
+               if (efi_image_verify_digest(regs, msg)) {
                        ret = true;
                        continue;
                }
 
-               log_debug("Signature was not verified by \"db\"\n");
+               log_debug("Message digest doesn't match\n");
        }