]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.4
authorSasha Levin <sashal@kernel.org>
Mon, 28 Jun 2021 13:48:43 +0000 (09:48 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 28 Jun 2021 13:48:43 +0000 (09:48 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.4/certs-add-efi_cert_x509_guid-support-for-dbx-entries.patch [new file with mode: 0644]
queue-5.4/certs-add-wrapper-function-to-check-blacklisted-bina.patch [new file with mode: 0644]
queue-5.4/certs-move-load_system_certificate_list-to-a-common-.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/x86-efi-move-common-keyring-handler-functions-to-new.patch [new file with mode: 0644]

diff --git a/queue-5.4/certs-add-efi_cert_x509_guid-support-for-dbx-entries.patch b/queue-5.4/certs-add-efi_cert_x509_guid-support-for-dbx-entries.patch
new file mode 100644 (file)
index 0000000..bb79ccd
--- /dev/null
@@ -0,0 +1,225 @@
+From 5887ffd6dd44f47a80bbbc535480f1fe2eb8c857 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Jan 2021 13:10:51 -0500
+Subject: certs: Add EFI_CERT_X509_GUID support for dbx entries
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Eric Snowberg <eric.snowberg@oracle.com>
+
+[ Upstream commit 56c5812623f95313f6a46fbf0beee7fa17c68bbf ]
+
+This fixes CVE-2020-26541.
+
+The Secure Boot Forbidden Signature Database, dbx, contains a list of now
+revoked signatures and keys previously approved to boot with UEFI Secure
+Boot enabled.  The dbx is capable of containing any number of
+EFI_CERT_X509_SHA256_GUID, EFI_CERT_SHA256_GUID, and EFI_CERT_X509_GUID
+entries.
+
+Currently when EFI_CERT_X509_GUID are contained in the dbx, the entries are
+skipped.
+
+Add support for EFI_CERT_X509_GUID dbx entries. When a EFI_CERT_X509_GUID
+is found, it is added as an asymmetrical key to the .blacklist keyring.
+Anytime the .platform keyring is used, the keys in the .blacklist keyring
+are referenced, if a matching key is found, the key will be rejected.
+
+[DH: Made the following changes:
+ - Added to have a config option to enable the facility.  This allows a
+   Kconfig solution to make sure that pkcs7_validate_trust() is
+   enabled.[1][2]
+ - Moved the functions out from the middle of the blacklist functions.
+ - Added kerneldoc comments.]
+
+Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
+cc: Randy Dunlap <rdunlap@infradead.org>
+cc: Mickaël Salaün <mic@digikod.net>
+cc: Arnd Bergmann <arnd@kernel.org>
+cc: keyrings@vger.kernel.org
+Link: https://lore.kernel.org/r/20200901165143.10295-1-eric.snowberg@oracle.com/ # rfc
+Link: https://lore.kernel.org/r/20200909172736.73003-1-eric.snowberg@oracle.com/ # v2
+Link: https://lore.kernel.org/r/20200911182230.62266-1-eric.snowberg@oracle.com/ # v3
+Link: https://lore.kernel.org/r/20200916004927.64276-1-eric.snowberg@oracle.com/ # v4
+Link: https://lore.kernel.org/r/20210122181054.32635-2-eric.snowberg@oracle.com/ # v5
+Link: https://lore.kernel.org/r/161428672051.677100.11064981943343605138.stgit@warthog.procyon.org.uk/
+Link: https://lore.kernel.org/r/161433310942.902181.4901864302675874242.stgit@warthog.procyon.org.uk/ # v2
+Link: https://lore.kernel.org/r/161529605075.163428.14625520893961300757.stgit@warthog.procyon.org.uk/ # v3
+Link: https://lore.kernel.org/r/bc2c24e3-ed68-2521-0bf4-a1f6be4a895d@infradead.org/ [1]
+Link: https://lore.kernel.org/r/20210225125638.1841436-1-arnd@kernel.org/ [2]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ certs/Kconfig                                 |  9 ++++
+ certs/blacklist.c                             | 43 +++++++++++++++++++
+ certs/blacklist.h                             |  2 +
+ certs/system_keyring.c                        |  6 +++
+ include/keys/system_keyring.h                 | 15 +++++++
+ .../platform_certs/keyring_handler.c          | 11 +++++
+ 6 files changed, 86 insertions(+)
+
+diff --git a/certs/Kconfig b/certs/Kconfig
+index c94e93d8bccf..76e469b56a77 100644
+--- a/certs/Kconfig
++++ b/certs/Kconfig
+@@ -83,4 +83,13 @@ config SYSTEM_BLACKLIST_HASH_LIST
+         wrapper to incorporate the list into the kernel.  Each <hash> should
+         be a string of hex digits.
++config SYSTEM_REVOCATION_LIST
++      bool "Provide system-wide ring of revocation certificates"
++      depends on SYSTEM_BLACKLIST_KEYRING
++      depends on PKCS7_MESSAGE_PARSER=y
++      help
++        If set, this allows revocation certificates to be stored in the
++        blacklist keyring and implements a hook whereby a PKCS#7 message can
++        be checked to see if it matches such a certificate.
++
+ endmenu
+diff --git a/certs/blacklist.c b/certs/blacklist.c
+index f1c434b04b5e..59b2f106b294 100644
+--- a/certs/blacklist.c
++++ b/certs/blacklist.c
+@@ -144,6 +144,49 @@ int is_binary_blacklisted(const u8 *hash, size_t hash_len)
+ }
+ EXPORT_SYMBOL_GPL(is_binary_blacklisted);
++#ifdef CONFIG_SYSTEM_REVOCATION_LIST
++/**
++ * add_key_to_revocation_list - Add a revocation certificate to the blacklist
++ * @data: The data blob containing the certificate
++ * @size: The size of data blob
++ */
++int add_key_to_revocation_list(const char *data, size_t size)
++{
++      key_ref_t key;
++
++      key = key_create_or_update(make_key_ref(blacklist_keyring, true),
++                                 "asymmetric",
++                                 NULL,
++                                 data,
++                                 size,
++                                 ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW),
++                                 KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_BUILT_IN);
++
++      if (IS_ERR(key)) {
++              pr_err("Problem with revocation key (%ld)\n", PTR_ERR(key));
++              return PTR_ERR(key);
++      }
++
++      return 0;
++}
++
++/**
++ * is_key_on_revocation_list - Determine if the key for a PKCS#7 message is revoked
++ * @pkcs7: The PKCS#7 message to check
++ */
++int is_key_on_revocation_list(struct pkcs7_message *pkcs7)
++{
++      int ret;
++
++      ret = pkcs7_validate_trust(pkcs7, blacklist_keyring);
++
++      if (ret == 0)
++              return -EKEYREJECTED;
++
++      return -ENOKEY;
++}
++#endif
++
+ /*
+  * Initialise the blacklist
+  */
+diff --git a/certs/blacklist.h b/certs/blacklist.h
+index 1efd6fa0dc60..51b320cf8574 100644
+--- a/certs/blacklist.h
++++ b/certs/blacklist.h
+@@ -1,3 +1,5 @@
+ #include <linux/kernel.h>
++#include <linux/errno.h>
++#include <crypto/pkcs7.h>
+ extern const char __initconst *const blacklist_hashes[];
+diff --git a/certs/system_keyring.c b/certs/system_keyring.c
+index 798291177186..cc165b359ea3 100644
+--- a/certs/system_keyring.c
++++ b/certs/system_keyring.c
+@@ -241,6 +241,12 @@ int verify_pkcs7_message_sig(const void *data, size_t len,
+                       pr_devel("PKCS#7 platform keyring is not available\n");
+                       goto error;
+               }
++
++              ret = is_key_on_revocation_list(pkcs7);
++              if (ret != -ENOKEY) {
++                      pr_devel("PKCS#7 platform key is on revocation list\n");
++                      goto error;
++              }
+       }
+       ret = pkcs7_validate_trust(pkcs7, trusted_keys);
+       if (ret < 0) {
+diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
+index fb8b07daa9d1..875e002a4180 100644
+--- a/include/keys/system_keyring.h
++++ b/include/keys/system_keyring.h
+@@ -31,6 +31,7 @@ extern int restrict_link_by_builtin_and_secondary_trusted(
+ #define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted
+ #endif
++extern struct pkcs7_message *pkcs7;
+ #ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
+ extern int mark_hash_blacklisted(const char *hash);
+ extern int is_hash_blacklisted(const u8 *hash, size_t hash_len,
+@@ -49,6 +50,20 @@ static inline int is_binary_blacklisted(const u8 *hash, size_t hash_len)
+ }
+ #endif
++#ifdef CONFIG_SYSTEM_REVOCATION_LIST
++extern int add_key_to_revocation_list(const char *data, size_t size);
++extern int is_key_on_revocation_list(struct pkcs7_message *pkcs7);
++#else
++static inline int add_key_to_revocation_list(const char *data, size_t size)
++{
++      return 0;
++}
++static inline int is_key_on_revocation_list(struct pkcs7_message *pkcs7)
++{
++      return -ENOKEY;
++}
++#endif
++
+ #ifdef CONFIG_IMA_BLACKLIST_KEYRING
+ extern struct key *ima_blacklist_keyring;
+diff --git a/security/integrity/platform_certs/keyring_handler.c b/security/integrity/platform_certs/keyring_handler.c
+index c5ba695c10e3..5604bd57c990 100644
+--- a/security/integrity/platform_certs/keyring_handler.c
++++ b/security/integrity/platform_certs/keyring_handler.c
+@@ -55,6 +55,15 @@ static __init void uefi_blacklist_binary(const char *source,
+       uefi_blacklist_hash(source, data, len, "bin:", 4);
+ }
++/*
++ * Add an X509 cert to the revocation list.
++ */
++static __init void uefi_revocation_list_x509(const char *source,
++                                           const void *data, size_t len)
++{
++      add_key_to_revocation_list(data, len);
++}
++
+ /*
+  * Return the appropriate handler for particular signature list types found in
+  * the UEFI db and MokListRT tables.
+@@ -76,5 +85,7 @@ __init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type)
+               return uefi_blacklist_x509_tbs;
+       if (efi_guidcmp(*sig_type, efi_cert_sha256_guid) == 0)
+               return uefi_blacklist_binary;
++      if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
++              return uefi_revocation_list_x509;
+       return 0;
+ }
+-- 
+2.30.2
+
diff --git a/queue-5.4/certs-add-wrapper-function-to-check-blacklisted-bina.patch b/queue-5.4/certs-add-wrapper-function-to-check-blacklisted-bina.patch
new file mode 100644 (file)
index 0000000..8595924
--- /dev/null
@@ -0,0 +1,72 @@
+From bf26abb55c4eec48e2fd8645ff374bacbfc02987 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Oct 2019 23:31:31 -0400
+Subject: certs: Add wrapper function to check blacklisted binary hash
+
+From: Nayna Jain <nayna@linux.ibm.com>
+
+[ Upstream commit 2434f7d2d488c3301ae81f1031e1c66c6f076fb7 ]
+
+The -EKEYREJECTED error returned by existing is_hash_blacklisted() is
+misleading when called for checking against blacklisted hash of a
+binary.
+
+This patch adds a wrapper function is_binary_blacklisted() to return
+-EPERM error if binary is blacklisted.
+
+Signed-off-by: Nayna Jain <nayna@linux.ibm.com>
+Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/1572492694-6520-7-git-send-email-zohar@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ certs/blacklist.c             | 9 +++++++++
+ include/keys/system_keyring.h | 6 ++++++
+ 2 files changed, 15 insertions(+)
+
+diff --git a/certs/blacklist.c b/certs/blacklist.c
+index 025a41de28fd..f1c434b04b5e 100644
+--- a/certs/blacklist.c
++++ b/certs/blacklist.c
+@@ -135,6 +135,15 @@ int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type)
+ }
+ EXPORT_SYMBOL_GPL(is_hash_blacklisted);
++int is_binary_blacklisted(const u8 *hash, size_t hash_len)
++{
++      if (is_hash_blacklisted(hash, hash_len, "bin") == -EKEYREJECTED)
++              return -EPERM;
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(is_binary_blacklisted);
++
+ /*
+  * Initialise the blacklist
+  */
+diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
+index c1a96fdf598b..fb8b07daa9d1 100644
+--- a/include/keys/system_keyring.h
++++ b/include/keys/system_keyring.h
+@@ -35,12 +35,18 @@ extern int restrict_link_by_builtin_and_secondary_trusted(
+ extern int mark_hash_blacklisted(const char *hash);
+ extern int is_hash_blacklisted(const u8 *hash, size_t hash_len,
+                              const char *type);
++extern int is_binary_blacklisted(const u8 *hash, size_t hash_len);
+ #else
+ static inline int is_hash_blacklisted(const u8 *hash, size_t hash_len,
+                                     const char *type)
+ {
+       return 0;
+ }
++
++static inline int is_binary_blacklisted(const u8 *hash, size_t hash_len)
++{
++      return 0;
++}
+ #endif
+ #ifdef CONFIG_IMA_BLACKLIST_KEYRING
+-- 
+2.30.2
+
diff --git a/queue-5.4/certs-move-load_system_certificate_list-to-a-common-.patch b/queue-5.4/certs-move-load_system_certificate_list-to-a-common-.patch
new file mode 100644 (file)
index 0000000..a626aea
--- /dev/null
@@ -0,0 +1,198 @@
+From 834500a81e821b37e20b6232effd47be16fe43a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Jan 2021 13:10:52 -0500
+Subject: certs: Move load_system_certificate_list to a common function
+
+From: Eric Snowberg <eric.snowberg@oracle.com>
+
+[ Upstream commit 2565ca7f5ec1a98d51eea8860c4ab923f1ca2c85 ]
+
+Move functionality within load_system_certificate_list to a common
+function, so it can be reused in the future.
+
+DH Changes:
+ - Added inclusion of common.h to common.c (Eric [1]).
+
+Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
+Acked-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: David Howells <dhowells@redhat.com>
+cc: keyrings@vger.kernel.org
+Link: https://lore.kernel.org/r/EDA280F9-F72D-4181-93C7-CDBE95976FF7@oracle.com/ [1]
+Link: https://lore.kernel.org/r/20200930201508.35113-2-eric.snowberg@oracle.com/
+Link: https://lore.kernel.org/r/20210122181054.32635-3-eric.snowberg@oracle.com/ # v5
+Link: https://lore.kernel.org/r/161428672825.677100.7545516389752262918.stgit@warthog.procyon.org.uk/
+Link: https://lore.kernel.org/r/161433311696.902181.3599366124784670368.stgit@warthog.procyon.org.uk/ # v2
+Link: https://lore.kernel.org/r/161529605850.163428.7786675680201528556.stgit@warthog.procyon.org.uk/ # v3
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ certs/Makefile         |  2 +-
+ certs/common.c         | 57 ++++++++++++++++++++++++++++++++++++++++++
+ certs/common.h         |  9 +++++++
+ certs/system_keyring.c | 49 +++---------------------------------
+ 4 files changed, 70 insertions(+), 47 deletions(-)
+ create mode 100644 certs/common.c
+ create mode 100644 certs/common.h
+
+diff --git a/certs/Makefile b/certs/Makefile
+index f4c25b67aad9..f4b90bad8690 100644
+--- a/certs/Makefile
++++ b/certs/Makefile
+@@ -3,7 +3,7 @@
+ # Makefile for the linux kernel signature checking certificates.
+ #
+-obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
++obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o common.o
+ obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o
+ ifneq ($(CONFIG_SYSTEM_BLACKLIST_HASH_LIST),"")
+ obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_hashes.o
+diff --git a/certs/common.c b/certs/common.c
+new file mode 100644
+index 000000000000..16a220887a53
+--- /dev/null
++++ b/certs/common.c
+@@ -0,0 +1,57 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++#include <linux/kernel.h>
++#include <linux/key.h>
++#include "common.h"
++
++int load_certificate_list(const u8 cert_list[],
++                        const unsigned long list_size,
++                        const struct key *keyring)
++{
++      key_ref_t key;
++      const u8 *p, *end;
++      size_t plen;
++
++      p = cert_list;
++      end = p + list_size;
++      while (p < end) {
++              /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
++               * than 256 bytes in size.
++               */
++              if (end - p < 4)
++                      goto dodgy_cert;
++              if (p[0] != 0x30 &&
++                  p[1] != 0x82)
++                      goto dodgy_cert;
++              plen = (p[2] << 8) | p[3];
++              plen += 4;
++              if (plen > end - p)
++                      goto dodgy_cert;
++
++              key = key_create_or_update(make_key_ref(keyring, 1),
++                                         "asymmetric",
++                                         NULL,
++                                         p,
++                                         plen,
++                                         ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
++                                         KEY_USR_VIEW | KEY_USR_READ),
++                                         KEY_ALLOC_NOT_IN_QUOTA |
++                                         KEY_ALLOC_BUILT_IN |
++                                         KEY_ALLOC_BYPASS_RESTRICTION);
++              if (IS_ERR(key)) {
++                      pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
++                             PTR_ERR(key));
++              } else {
++                      pr_notice("Loaded X.509 cert '%s'\n",
++                                key_ref_to_ptr(key)->description);
++                      key_ref_put(key);
++              }
++              p += plen;
++      }
++
++      return 0;
++
++dodgy_cert:
++      pr_err("Problem parsing in-kernel X.509 certificate list\n");
++      return 0;
++}
+diff --git a/certs/common.h b/certs/common.h
+new file mode 100644
+index 000000000000..abdb5795936b
+--- /dev/null
++++ b/certs/common.h
+@@ -0,0 +1,9 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++
++#ifndef _CERT_COMMON_H
++#define _CERT_COMMON_H
++
++int load_certificate_list(const u8 cert_list[], const unsigned long list_size,
++                        const struct key *keyring);
++
++#endif
+diff --git a/certs/system_keyring.c b/certs/system_keyring.c
+index cc165b359ea3..a44a8915c94c 100644
+--- a/certs/system_keyring.c
++++ b/certs/system_keyring.c
+@@ -15,6 +15,7 @@
+ #include <keys/asymmetric-type.h>
+ #include <keys/system_keyring.h>
+ #include <crypto/pkcs7.h>
++#include "common.h"
+ static struct key *builtin_trusted_keys;
+ #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
+@@ -136,54 +137,10 @@ device_initcall(system_trusted_keyring_init);
+  */
+ static __init int load_system_certificate_list(void)
+ {
+-      key_ref_t key;
+-      const u8 *p, *end;
+-      size_t plen;
+-
+       pr_notice("Loading compiled-in X.509 certificates\n");
+-      p = system_certificate_list;
+-      end = p + system_certificate_list_size;
+-      while (p < end) {
+-              /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
+-               * than 256 bytes in size.
+-               */
+-              if (end - p < 4)
+-                      goto dodgy_cert;
+-              if (p[0] != 0x30 &&
+-                  p[1] != 0x82)
+-                      goto dodgy_cert;
+-              plen = (p[2] << 8) | p[3];
+-              plen += 4;
+-              if (plen > end - p)
+-                      goto dodgy_cert;
+-
+-              key = key_create_or_update(make_key_ref(builtin_trusted_keys, 1),
+-                                         "asymmetric",
+-                                         NULL,
+-                                         p,
+-                                         plen,
+-                                         ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
+-                                         KEY_USR_VIEW | KEY_USR_READ),
+-                                         KEY_ALLOC_NOT_IN_QUOTA |
+-                                         KEY_ALLOC_BUILT_IN |
+-                                         KEY_ALLOC_BYPASS_RESTRICTION);
+-              if (IS_ERR(key)) {
+-                      pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
+-                             PTR_ERR(key));
+-              } else {
+-                      pr_notice("Loaded X.509 cert '%s'\n",
+-                                key_ref_to_ptr(key)->description);
+-                      key_ref_put(key);
+-              }
+-              p += plen;
+-      }
+-
+-      return 0;
+-
+-dodgy_cert:
+-      pr_err("Problem parsing in-kernel X.509 certificate list\n");
+-      return 0;
++      return load_certificate_list(system_certificate_list, system_certificate_list_size,
++                                   builtin_trusted_keys);
+ }
+ late_initcall(load_system_certificate_list);
+-- 
+2.30.2
+
index 31fe4bd552514d30b55f7700a88f16ff94a8a8d1..6d183cd83fc3e77df01aac6305c85de12959a8a7 100644 (file)
@@ -64,3 +64,7 @@ mm-page_vma_mapped_walk-get-vma_address_end-earlier.patch
 mm-thp-fix-page_vma_mapped_walk-if-thp-mapped-by-ptes.patch
 mm-thp-another-pvmw_sync-fix-in-page_vma_mapped_walk.patch
 mm-futex-fix-shared-futex-pgoff-on-shmem-huge-page.patch
+certs-add-wrapper-function-to-check-blacklisted-bina.patch
+x86-efi-move-common-keyring-handler-functions-to-new.patch
+certs-add-efi_cert_x509_guid-support-for-dbx-entries.patch
+certs-move-load_system_certificate_list-to-a-common-.patch
diff --git a/queue-5.4/x86-efi-move-common-keyring-handler-functions-to-new.patch b/queue-5.4/x86-efi-move-common-keyring-handler-functions-to-new.patch
new file mode 100644 (file)
index 0000000..a9f8ed7
--- /dev/null
@@ -0,0 +1,256 @@
+From 5da81d6989172b38c257f1fe45a7b69677b717eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 10 Nov 2019 21:10:35 -0600
+Subject: x86/efi: move common keyring handler functions to new file
+
+From: Nayna Jain <nayna@linux.ibm.com>
+
+[ Upstream commit ad723674d6758478829ee766e3f1a2a24d56236f ]
+
+The handlers to add the keys to the .platform keyring and blacklisted
+hashes to the .blacklist keyring is common for both the uefi and powerpc
+mechanisms of loading the keys/hashes from the firmware.
+
+This patch moves the common code from load_uefi.c to keyring_handler.c
+
+Signed-off-by: Nayna Jain <nayna@linux.ibm.com>
+Acked-by: Mimi Zohar <zohar@linux.ibm.com>
+Signed-off-by: Eric Richter <erichte@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/1573441836-3632-4-git-send-email-nayna@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ security/integrity/Makefile                   |  3 +-
+ .../platform_certs/keyring_handler.c          | 80 +++++++++++++++++++
+ .../platform_certs/keyring_handler.h          | 32 ++++++++
+ security/integrity/platform_certs/load_uefi.c | 67 +---------------
+ 4 files changed, 115 insertions(+), 67 deletions(-)
+ create mode 100644 security/integrity/platform_certs/keyring_handler.c
+ create mode 100644 security/integrity/platform_certs/keyring_handler.h
+
+diff --git a/security/integrity/Makefile b/security/integrity/Makefile
+index 35e6ca773734..351c9662994b 100644
+--- a/security/integrity/Makefile
++++ b/security/integrity/Makefile
+@@ -11,7 +11,8 @@ integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
+ integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
+ integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += platform_certs/platform_keyring.o
+ integrity-$(CONFIG_LOAD_UEFI_KEYS) += platform_certs/efi_parser.o \
+-                                      platform_certs/load_uefi.o
++                                    platform_certs/load_uefi.o \
++                                    platform_certs/keyring_handler.o
+ integrity-$(CONFIG_LOAD_IPL_KEYS) += platform_certs/load_ipl_s390.o
+ obj-$(CONFIG_IMA)                     += ima/
+diff --git a/security/integrity/platform_certs/keyring_handler.c b/security/integrity/platform_certs/keyring_handler.c
+new file mode 100644
+index 000000000000..c5ba695c10e3
+--- /dev/null
++++ b/security/integrity/platform_certs/keyring_handler.c
+@@ -0,0 +1,80 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/cred.h>
++#include <linux/err.h>
++#include <linux/efi.h>
++#include <linux/slab.h>
++#include <keys/asymmetric-type.h>
++#include <keys/system_keyring.h>
++#include "../integrity.h"
++
++static efi_guid_t efi_cert_x509_guid __initdata = EFI_CERT_X509_GUID;
++static efi_guid_t efi_cert_x509_sha256_guid __initdata =
++      EFI_CERT_X509_SHA256_GUID;
++static efi_guid_t efi_cert_sha256_guid __initdata = EFI_CERT_SHA256_GUID;
++
++/*
++ * Blacklist a hash.
++ */
++static __init void uefi_blacklist_hash(const char *source, const void *data,
++                                     size_t len, const char *type,
++                                     size_t type_len)
++{
++      char *hash, *p;
++
++      hash = kmalloc(type_len + len * 2 + 1, GFP_KERNEL);
++      if (!hash)
++              return;
++      p = memcpy(hash, type, type_len);
++      p += type_len;
++      bin2hex(p, data, len);
++      p += len * 2;
++      *p = 0;
++
++      mark_hash_blacklisted(hash);
++      kfree(hash);
++}
++
++/*
++ * Blacklist an X509 TBS hash.
++ */
++static __init void uefi_blacklist_x509_tbs(const char *source,
++                                         const void *data, size_t len)
++{
++      uefi_blacklist_hash(source, data, len, "tbs:", 4);
++}
++
++/*
++ * Blacklist the hash of an executable.
++ */
++static __init void uefi_blacklist_binary(const char *source,
++                                       const void *data, size_t len)
++{
++      uefi_blacklist_hash(source, data, len, "bin:", 4);
++}
++
++/*
++ * Return the appropriate handler for particular signature list types found in
++ * the UEFI db and MokListRT tables.
++ */
++__init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type)
++{
++      if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
++              return add_to_platform_keyring;
++      return 0;
++}
++
++/*
++ * Return the appropriate handler for particular signature list types found in
++ * the UEFI dbx and MokListXRT tables.
++ */
++__init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type)
++{
++      if (efi_guidcmp(*sig_type, efi_cert_x509_sha256_guid) == 0)
++              return uefi_blacklist_x509_tbs;
++      if (efi_guidcmp(*sig_type, efi_cert_sha256_guid) == 0)
++              return uefi_blacklist_binary;
++      return 0;
++}
+diff --git a/security/integrity/platform_certs/keyring_handler.h b/security/integrity/platform_certs/keyring_handler.h
+new file mode 100644
+index 000000000000..2462bfa08fe3
+--- /dev/null
++++ b/security/integrity/platform_certs/keyring_handler.h
+@@ -0,0 +1,32 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++#ifndef PLATFORM_CERTS_INTERNAL_H
++#define PLATFORM_CERTS_INTERNAL_H
++
++#include <linux/efi.h>
++
++void blacklist_hash(const char *source, const void *data,
++                  size_t len, const char *type,
++                  size_t type_len);
++
++/*
++ * Blacklist an X509 TBS hash.
++ */
++void blacklist_x509_tbs(const char *source, const void *data, size_t len);
++
++/*
++ * Blacklist the hash of an executable.
++ */
++void blacklist_binary(const char *source, const void *data, size_t len);
++
++/*
++ * Return the handler for particular signature list types found in the db.
++ */
++efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type);
++
++/*
++ * Return the handler for particular signature list types found in the dbx.
++ */
++efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type);
++
++#endif
+diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c
+index 020fc7a11ef0..aa874d84e413 100644
+--- a/security/integrity/platform_certs/load_uefi.c
++++ b/security/integrity/platform_certs/load_uefi.c
+@@ -9,6 +9,7 @@
+ #include <keys/asymmetric-type.h>
+ #include <keys/system_keyring.h>
+ #include "../integrity.h"
++#include "keyring_handler.h"
+ static efi_guid_t efi_cert_x509_guid __initdata = EFI_CERT_X509_GUID;
+ static efi_guid_t efi_cert_x509_sha256_guid __initdata =
+@@ -69,72 +70,6 @@ static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
+       return db;
+ }
+-/*
+- * Blacklist a hash.
+- */
+-static __init void uefi_blacklist_hash(const char *source, const void *data,
+-                                     size_t len, const char *type,
+-                                     size_t type_len)
+-{
+-      char *hash, *p;
+-
+-      hash = kmalloc(type_len + len * 2 + 1, GFP_KERNEL);
+-      if (!hash)
+-              return;
+-      p = memcpy(hash, type, type_len);
+-      p += type_len;
+-      bin2hex(p, data, len);
+-      p += len * 2;
+-      *p = 0;
+-
+-      mark_hash_blacklisted(hash);
+-      kfree(hash);
+-}
+-
+-/*
+- * Blacklist an X509 TBS hash.
+- */
+-static __init void uefi_blacklist_x509_tbs(const char *source,
+-                                         const void *data, size_t len)
+-{
+-      uefi_blacklist_hash(source, data, len, "tbs:", 4);
+-}
+-
+-/*
+- * Blacklist the hash of an executable.
+- */
+-static __init void uefi_blacklist_binary(const char *source,
+-                                       const void *data, size_t len)
+-{
+-      uefi_blacklist_hash(source, data, len, "bin:", 4);
+-}
+-
+-/*
+- * Return the appropriate handler for particular signature list types found in
+- * the UEFI db and MokListRT tables.
+- */
+-static __init efi_element_handler_t get_handler_for_db(const efi_guid_t *
+-                                                     sig_type)
+-{
+-      if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
+-              return add_to_platform_keyring;
+-      return 0;
+-}
+-
+-/*
+- * Return the appropriate handler for particular signature list types found in
+- * the UEFI dbx and MokListXRT tables.
+- */
+-static __init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *
+-                                                      sig_type)
+-{
+-      if (efi_guidcmp(*sig_type, efi_cert_x509_sha256_guid) == 0)
+-              return uefi_blacklist_x509_tbs;
+-      if (efi_guidcmp(*sig_type, efi_cert_sha256_guid) == 0)
+-              return uefi_blacklist_binary;
+-      return 0;
+-}
+-
+ /*
+  * Load the certs contained in the UEFI databases into the platform trusted
+  * keyring and the UEFI blacklisted X.509 cert SHA256 hashes into the blacklist
+-- 
+2.30.2
+