From 91129418a48089851ad6e5b94c06453f9a25d4cb Mon Sep 17 00:00:00 2001
From: Daniel Kiper <daniel.kiper@oracle.com>
Date: Thu, 3 Dec 2020 16:01:48 +0100
Subject: [PATCH 05/41] efi: Add secure boot detection

Introduce grub_efi_get_secureboot() function which returns whether
UEFI Secure Boot is enabled or not on UEFI systems.

Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Marco A Benatto <mbenatto@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/Makefile.am       |   1 +
 grub-core/Makefile.core.def |   1 +
 grub-core/kern/efi/sb.c     | 109 ++++++++++++++++++++++++++++++++++++
 include/grub/efi/sb.h       |  40 +++++++++++++
 4 files changed, 151 insertions(+)
 create mode 100644 grub-core/kern/efi/sb.c
 create mode 100644 include/grub/efi/sb.h

diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 856c36165..e8487fcac 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -71,6 +71,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/disk.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dl.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/sb.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 505b3205d..6b47b984a 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -174,6 +174,7 @@ kernel = {
   efi = term/efi/console.c;
   efi = kern/acpi.c;
   efi = kern/efi/acpi.c;
+  efi = kern/efi/sb.c;
   i386_coreboot = kern/i386/pc/acpi.c;
   i386_multiboot = kern/i386/pc/acpi.c;
   i386_coreboot = kern/acpi.c;
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
new file mode 100644
index 000000000..19658d962
--- /dev/null
+++ b/grub-core/kern/efi/sb.c
@@ -0,0 +1,109 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  UEFI Secure Boot related checkings.
+ */
+
+#include <grub/efi/efi.h>
+#include <grub/efi/pe32.h>
+#include <grub/efi/sb.h>
+#include <grub/err.h>
+#include <grub/i386/linux.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+
+/*
+ * Determine whether we're in secure boot mode.
+ *
+ * Please keep the logic in sync with the Linux kernel,
+ * drivers/firmware/efi/libstub/secureboot.c:efi_get_secureboot().
+ */
+grub_uint8_t
+grub_efi_get_secureboot (void)
+{
+  static grub_efi_guid_t efi_variable_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
+  static grub_efi_guid_t efi_shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID;
+  grub_efi_status_t status;
+  grub_efi_uint32_t attr = 0;
+  grub_size_t size = 0;
+  grub_uint8_t *secboot = NULL;
+  grub_uint8_t *setupmode = NULL;
+  grub_uint8_t *moksbstate = NULL;
+  grub_uint8_t secureboot = GRUB_EFI_SECUREBOOT_MODE_UNKNOWN;
+  const char *secureboot_str = "UNKNOWN";
+
+  status = grub_efi_get_variable ("SecureBoot", &efi_variable_guid,
+				  &size, (void **) &secboot);
+
+  if (status == GRUB_EFI_NOT_FOUND)
+    {
+      secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED;
+      goto out;
+    }
+
+  if (status != GRUB_EFI_SUCCESS)
+    goto out;
+
+  status = grub_efi_get_variable ("SetupMode", &efi_variable_guid,
+				  &size, (void **) &setupmode);
+
+  if (status != GRUB_EFI_SUCCESS)
+    goto out;
+
+  if ((*secboot == 0) || (*setupmode == 1))
+    {
+      secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED;
+      goto out;
+    }
+
+  /*
+   * See if a user has put the shim into insecure mode. If so, and if the
+   * variable doesn't have the runtime attribute set, we might as well
+   * honor that.
+   */
+  status = grub_efi_get_variable_with_attributes ("MokSBState", &efi_shim_lock_guid,
+						  &size, (void **) &moksbstate, &attr);
+
+  /* If it fails, we don't care why. Default to secure. */
+  if (status != GRUB_EFI_SUCCESS)
+    {
+      secureboot = GRUB_EFI_SECUREBOOT_MODE_ENABLED;
+      goto out;
+    }
+
+  if (!(attr & GRUB_EFI_VARIABLE_RUNTIME_ACCESS) && *moksbstate == 1)
+    {
+      secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED;
+      goto out;
+    }
+
+  secureboot = GRUB_EFI_SECUREBOOT_MODE_ENABLED;
+
+ out:
+  grub_free (moksbstate);
+  grub_free (setupmode);
+  grub_free (secboot);
+
+  if (secureboot == GRUB_EFI_SECUREBOOT_MODE_DISABLED)
+    secureboot_str = "Disabled";
+  else if (secureboot == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+    secureboot_str = "Enabled";
+
+  grub_dprintf ("efi", "UEFI Secure Boot state: %s\n", secureboot_str);
+
+  return secureboot;
+}
diff --git a/include/grub/efi/sb.h b/include/grub/efi/sb.h
new file mode 100644
index 000000000..a33d985e3
--- /dev/null
+++ b/include/grub/efi/sb.h
@@ -0,0 +1,40 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_EFI_SB_H
+#define GRUB_EFI_SB_H     1
+
+#include <grub/types.h>
+#include <grub/dl.h>
+
+#define GRUB_EFI_SECUREBOOT_MODE_UNSET	0
+#define GRUB_EFI_SECUREBOOT_MODE_UNKNOWN	1
+#define GRUB_EFI_SECUREBOOT_MODE_DISABLED	2
+#define GRUB_EFI_SECUREBOOT_MODE_ENABLED	3
+
+#ifdef GRUB_MACHINE_EFI
+extern grub_uint8_t
+EXPORT_FUNC (grub_efi_get_secureboot) (void);
+#else
+static inline grub_uint8_t
+grub_efi_get_secureboot (void)
+{
+  return GRUB_EFI_SECUREBOOT_MODE_UNSET;
+}
+#endif
+#endif /* GRUB_EFI_SB_H */
-- 
2.26.2

