linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher
@ 2020-05-04 23:21 Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 01/18] i386/msr: Merge rdmsr.h and wrmsr.h into msr.h Daniel Kiper
                   ` (18 more replies)
  0 siblings, 19 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

Hi,

This is an RFC patchset for the GRUB introducing the Intel TXT secure launcher.
This is a part of larger work known as the TrenchBoot. Patchset can be split
into two distinct parts:
  - 01-12: preparatory patches,
  - 13-18: the Intel TXT secure launcher itself.

The initial implementation of the Intel TXT secure launcher works. However,
there are still some missing bits and pieces, e.g.:
  - SINIT ACM auto loader,
  - lack of RMRR support,
  - lack of support for MLEs larger than 1 GiB,
  - lack of TPM 1.2 support.
  - various fixes and cleanups.

Commands introduced by this patchset: tpm_type, slaunch, slaunch_module (not
required on server platforms) and slaunch_state (useful for checking platform
configuration and state; based on tboot's txt-stat).

Daniel


^ permalink raw reply	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 01/18] i386/msr: Merge rdmsr.h and wrmsr.h into msr.h
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 02/18] i386/msr: Rename grub_msr_read() and grub_msr_write() Daniel Kiper
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

It does not make sense to have separate headers for separate static
functions. Additionally, we have to add some constants with MSR addresses
in subsequent patches. So, make one common place to store them.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/i386/rdmsr.c      |  2 +-
 grub-core/commands/i386/wrmsr.c      |  2 +-
 include/grub/i386/{wrmsr.h => msr.h} | 16 +++++++++++++---
 include/grub/i386/rdmsr.h            | 37 ------------------------------------
 4 files changed, 15 insertions(+), 42 deletions(-)
 rename include/grub/i386/{wrmsr.h => msr.h} (78%)
 delete mode 100644 include/grub/i386/rdmsr.h

diff --git a/grub-core/commands/i386/rdmsr.c b/grub-core/commands/i386/rdmsr.c
index 46c4346da..fa4622f9e 100644
--- a/grub-core/commands/i386/rdmsr.c
+++ b/grub-core/commands/i386/rdmsr.c
@@ -26,7 +26,7 @@
 #include <grub/extcmd.h>
 #include <grub/i18n.h>
 #include <grub/i386/cpuid.h>
-#include <grub/i386/rdmsr.h>
+#include <grub/i386/msr.h>
 
 GRUB_MOD_LICENSE("GPLv3+");
 
diff --git a/grub-core/commands/i386/wrmsr.c b/grub-core/commands/i386/wrmsr.c
index fa76f5aed..9b7abba7c 100644
--- a/grub-core/commands/i386/wrmsr.c
+++ b/grub-core/commands/i386/wrmsr.c
@@ -26,7 +26,7 @@
 #include <grub/extcmd.h>
 #include <grub/i18n.h>
 #include <grub/i386/cpuid.h>
-#include <grub/i386/wrmsr.h>
+#include <grub/i386/msr.h>
 
 GRUB_MOD_LICENSE("GPLv3+");
 
diff --git a/include/grub/i386/wrmsr.h b/include/grub/i386/msr.h
similarity index 78%
rename from include/grub/i386/wrmsr.h
rename to include/grub/i386/msr.h
index dea60aed1..7b52b5d61 100644
--- a/include/grub/i386/wrmsr.h
+++ b/include/grub/i386/msr.h
@@ -16,14 +16,24 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef GRUB_WRMSR_H
-#define GRUB_WRMSR_H 1
+#ifndef GRUB_I386_MSR_H
+#define GRUB_I386_MSR_H 1
 
 /*
  * TODO: Add a general protection exception handler.
  *       Accessing a reserved or unimplemented MSR address results in a GP#.
  */
 
+static inline grub_uint64_t
+grub_msr_read (grub_uint32_t msr_id)
+{
+  grub_uint32_t low, high;
+
+  asm volatile ("rdmsr" : "=a" (low), "=d" (high) : "c" (msr_id));
+
+  return ((grub_uint64_t) high << 32) | low;
+}
+
 static inline void
 grub_msr_write(grub_uint32_t msr_id, grub_uint64_t msr_value)
 {
@@ -32,4 +42,4 @@ grub_msr_write(grub_uint32_t msr_id, grub_uint64_t msr_value)
   asm volatile ("wrmsr" : : "c" (msr_id), "a" (low), "d" (high));
 }
 
-#endif /* GRUB_WRMSR_H */
+#endif /* GRUB_I386_MSR_H */
diff --git a/include/grub/i386/rdmsr.h b/include/grub/i386/rdmsr.h
deleted file mode 100644
index c0a0c717a..000000000
--- a/include/grub/i386/rdmsr.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2019  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_RDMSR_H
-#define GRUB_RDMSR_H 1
-
-/*
- * TODO: Add a general protection exception handler.
- *       Accessing a reserved or unimplemented MSR address results in a GP#.
- */
-
-static inline grub_uint64_t
-grub_msr_read (grub_uint32_t msr_id)
-{
-  grub_uint32_t low, high;
-
-  asm volatile ("rdmsr" : "=a" (low), "=d" (high) : "c" (msr_id));
-
-  return ((grub_uint64_t)high << 32) | low;
-}
-
-#endif /* GRUB_RDMSR_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 02/18] i386/msr: Rename grub_msr_read() and grub_msr_write()
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 01/18] i386/msr: Merge rdmsr.h and wrmsr.h into msr.h Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 03/18] i386/msr: Extract and improve MSR support detection code Daniel Kiper
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

.. to grub_rdmsr() and grub_wrmsr() respectively. New names are more
obvious than older ones.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/i386/rdmsr.c | 2 +-
 grub-core/commands/i386/wrmsr.c | 2 +-
 include/grub/i386/msr.h         | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/commands/i386/rdmsr.c b/grub-core/commands/i386/rdmsr.c
index fa4622f9e..89ece7657 100644
--- a/grub-core/commands/i386/rdmsr.c
+++ b/grub-core/commands/i386/rdmsr.c
@@ -76,7 +76,7 @@ grub_cmd_msr_read (grub_extcmd_context_t ctxt, int argc, char **argv)
   if (*ptr != '\0')
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
 
-  value = grub_msr_read (addr);
+  value = grub_rdmsr (addr);
 
   if (ctxt->state[0].set)
     {
diff --git a/grub-core/commands/i386/wrmsr.c b/grub-core/commands/i386/wrmsr.c
index 9b7abba7c..e3e9f2ee3 100644
--- a/grub-core/commands/i386/wrmsr.c
+++ b/grub-core/commands/i386/wrmsr.c
@@ -76,7 +76,7 @@ grub_cmd_msr_write (grub_command_t cmd __attribute__ ((unused)), int argc, char
   if (*ptr != '\0')
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
 
-  grub_msr_write (addr, value);
+  grub_wrmsr (addr, value);
 
   return GRUB_ERR_NONE;
 }
diff --git a/include/grub/i386/msr.h b/include/grub/i386/msr.h
index 7b52b5d61..4fba1b8e0 100644
--- a/include/grub/i386/msr.h
+++ b/include/grub/i386/msr.h
@@ -25,7 +25,7 @@
  */
 
 static inline grub_uint64_t
-grub_msr_read (grub_uint32_t msr_id)
+grub_rdmsr (grub_uint32_t msr_id)
 {
   grub_uint32_t low, high;
 
@@ -35,7 +35,7 @@ grub_msr_read (grub_uint32_t msr_id)
 }
 
 static inline void
-grub_msr_write(grub_uint32_t msr_id, grub_uint64_t msr_value)
+grub_wrmsr (grub_uint32_t msr_id, grub_uint64_t msr_value)
 {
   grub_uint32_t low = msr_value, high = msr_value >> 32;
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 03/18] i386/msr: Extract and improve MSR support detection code
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 01/18] i386/msr: Merge rdmsr.h and wrmsr.h into msr.h Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 02/18] i386/msr: Rename grub_msr_read() and grub_msr_write() Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 04/18] i386/memory: Rename PAGE_SHIFT to GRUB_PAGE_SHIFT Daniel Kiper
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

Currently rdmsr and wrmsr commands have own MSR support detection code.
This code is the same. So, it is duplicated. Additionally, this code
cannot be reused by others. Hence, extract this code to a function and
make it public. By the way, improve a code a bit.

Additionally, use GRUB_ERR_BAD_DEVICE instead of GRUB_ERR_BUG to signal
an error because errors encountered by this new routine are not bugs.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/i386/rdmsr.c | 21 +++++----------------
 grub-core/commands/i386/wrmsr.c | 21 +++++----------------
 include/grub/i386/msr.h         | 29 +++++++++++++++++++++++++++++
 3 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/grub-core/commands/i386/rdmsr.c b/grub-core/commands/i386/rdmsr.c
index 89ece7657..2e42f6197 100644
--- a/grub-core/commands/i386/rdmsr.c
+++ b/grub-core/commands/i386/rdmsr.c
@@ -42,27 +42,16 @@ static const struct grub_arg_option options[] =
 static grub_err_t
 grub_cmd_msr_read (grub_extcmd_context_t ctxt, int argc, char **argv)
 {
-  grub_uint32_t manufacturer[3], max_cpuid, a, b, c, features, addr;
+  grub_err_t err;
+  grub_uint32_t addr;
   grub_uint64_t value;
   const char *ptr;
   char buf[sizeof("1122334455667788")];
 
-  /*
-   * The CPUID instruction should be used to determine whether MSRs
-   * are supported. (CPUID.01H:EDX[5] = 1)
-   */
-  if (! grub_cpu_is_cpuid_supported ())
-    return grub_error (GRUB_ERR_BUG, N_("unsupported instruction"));
+  err = grub_cpu_is_msr_supported ();
 
-  grub_cpuid (0, max_cpuid, manufacturer[0], manufacturer[2], manufacturer[1]);
-
-  if (max_cpuid < 1)
-    return grub_error (GRUB_ERR_BUG, N_("unsupported instruction"));
-
-  grub_cpuid (1, a, b, c, features);
-
-  if (!(features & (1 << 5)))
-    return grub_error (GRUB_ERR_BUG, N_("unsupported instruction"));
+  if (err != GRUB_ERR_NONE)
+    return grub_error (err, N_("RDMSR is unsupported"));
 
   if (argc != 1)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
diff --git a/grub-core/commands/i386/wrmsr.c b/grub-core/commands/i386/wrmsr.c
index e3e9f2ee3..d14bb3176 100644
--- a/grub-core/commands/i386/wrmsr.c
+++ b/grub-core/commands/i386/wrmsr.c
@@ -35,26 +35,15 @@ static grub_command_t cmd_write;
 static grub_err_t
 grub_cmd_msr_write (grub_command_t cmd __attribute__ ((unused)), int argc, char **argv)
 {
-  grub_uint32_t manufacturer[3], max_cpuid, a, b, c, features, addr;
+  grub_err_t err;
+  grub_uint32_t addr;
   grub_uint64_t value;
   const char *ptr;
 
-  /*
-   * The CPUID instruction should be used to determine whether MSRs
-   * are supported. (CPUID.01H:EDX[5] = 1)
-   */
-  if (!grub_cpu_is_cpuid_supported ())
-    return grub_error (GRUB_ERR_BUG, N_("unsupported instruction"));
+  err = grub_cpu_is_msr_supported ();
 
-  grub_cpuid (0, max_cpuid, manufacturer[0], manufacturer[2], manufacturer[1]);
-
-  if (max_cpuid < 1)
-    return grub_error (GRUB_ERR_BUG, N_("unsupported instruction"));
-
-  grub_cpuid (1, a, b, c, features);
-
-  if (!(features & (1 << 5)))
-    return grub_error (GRUB_ERR_BUG, N_("unsupported instruction"));
+  if (err != GRUB_ERR_NONE)
+    return grub_error (err, N_("WRMSR is unsupported"));
 
   if (argc != 2)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
diff --git a/include/grub/i386/msr.h b/include/grub/i386/msr.h
index 4fba1b8e0..1e838c022 100644
--- a/include/grub/i386/msr.h
+++ b/include/grub/i386/msr.h
@@ -19,6 +19,35 @@
 #ifndef GRUB_I386_MSR_H
 #define GRUB_I386_MSR_H 1
 
+#include <grub/err.h>
+#include <grub/i386/cpuid.h>
+#include <grub/types.h>
+
+static inline grub_err_t
+grub_cpu_is_msr_supported (void)
+{
+  grub_uint32_t eax, ebx, ecx, edx;
+
+  /*
+   * The CPUID instruction should be used to determine whether MSRs
+   * are supported, CPUID.01H:EDX[5] = 1.
+   */
+  if (!grub_cpu_is_cpuid_supported ())
+    return GRUB_ERR_BAD_DEVICE;
+
+  grub_cpuid (0, eax, ebx, ecx, edx);
+
+  if (eax < 1)
+    return GRUB_ERR_BAD_DEVICE;
+
+  grub_cpuid (1, eax, ebx, ecx, edx);
+
+  if (!(edx & (1 << 5)))
+    return GRUB_ERR_BAD_DEVICE;
+
+  return GRUB_ERR_NONE;
+}
+
 /*
  * TODO: Add a general protection exception handler.
  *       Accessing a reserved or unimplemented MSR address results in a GP#.
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 04/18] i386/memory: Rename PAGE_SHIFT to GRUB_PAGE_SHIFT
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (2 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 03/18] i386/msr: Extract and improve MSR support detection code Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 05/18] i386/memory: Rename PAGE_SIZE to GRUB_PAGE_SIZE and make it global Daniel Kiper
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

..to avoid potential conflicts and confusion.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/lib/i386/xen/relocator.S   |  6 +++---
 grub-core/lib/x86_64/xen/relocator.S |  4 ++--
 grub-core/loader/i386/xen.c          | 28 ++++++++++++++--------------
 include/grub/i386/memory.h           |  2 +-
 4 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/grub-core/lib/i386/xen/relocator.S b/grub-core/lib/i386/xen/relocator.S
index 96e51b59a..dab4d8ace 100644
--- a/grub-core/lib/i386/xen/relocator.S
+++ b/grub-core/lib/i386/xen/relocator.S
@@ -75,10 +75,10 @@ VARIABLE(grub_relocator_xen_mfn_list)
 	.long	0
 	movl    0(%eax, %ebp, 4), %ecx	/* mfn */
 	movl	%ebp, %ebx
-	shll	$PAGE_SHIFT, %ebx	/* virtual address (1:1 mapping) */
+	shll	$GRUB_PAGE_SHIFT, %ebx	/* virtual address (1:1 mapping) */
 	movl    %ecx, %edx
-	shll    $PAGE_SHIFT,  %ecx	/* prepare pte low part */
-	shrl    $(32 - PAGE_SHIFT),  %edx	/* pte high part */
+	shll    $GRUB_PAGE_SHIFT,  %ecx	/* prepare pte low part */
+	shrl    $(32 - GRUB_PAGE_SHIFT),  %edx	/* pte high part */
 	orl     $(GRUB_PAGE_PRESENT | GRUB_PAGE_USER), %ecx	/* pte low */
 	movl    $UVMF_INVLPG, %esi
 	movl    $__HYPERVISOR_update_va_mapping, %eax
diff --git a/grub-core/lib/x86_64/xen/relocator.S b/grub-core/lib/x86_64/xen/relocator.S
index f5364ed0f..852cd40aa 100644
--- a/grub-core/lib/x86_64/xen/relocator.S
+++ b/grub-core/lib/x86_64/xen/relocator.S
@@ -60,9 +60,9 @@ LOCAL(cont):
 	jz	3f
 2:
 	movq	%r12, %rdi
-	shlq	$PAGE_SHIFT, %rdi	/* virtual address (1:1 mapping) */
+	shlq	$GRUB_PAGE_SHIFT, %rdi	/* virtual address (1:1 mapping) */
 	movq    (%rbx, %r12, 8), %rsi	/* mfn */
-	shlq    $PAGE_SHIFT,  %rsi
+	shlq    $GRUB_PAGE_SHIFT,  %rsi
 	orq     $(GRUB_PAGE_PRESENT | GRUB_PAGE_USER), %rsi	/* Build pte */
 	movq    $UVMF_INVLPG, %rdx
 	movq    %rcx, %r9	/* %rcx clobbered by hypercall */
diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
index 8f662c8ac..fe92874e0 100644
--- a/grub-core/loader/i386/xen.c
+++ b/grub-core/loader/i386/xen.c
@@ -91,7 +91,7 @@ static struct xen_loader_state xen_state;
 
 static grub_dl_t my_mod;
 
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_SIZE (1UL << GRUB_PAGE_SHIFT)
 #define MAX_MODULES (PAGE_SIZE / sizeof (struct xen_multiboot_mod_list))
 #define STACK_SIZE 1048576
 #define ADDITIONAL_SIZE (1 << 19)
@@ -102,7 +102,7 @@ static grub_dl_t my_mod;
 static grub_uint64_t
 page2offset (grub_uint64_t page)
 {
-  return page << PAGE_SHIFT;
+  return page << GRUB_PAGE_SHIFT;
 }
 
 static grub_err_t
@@ -141,7 +141,7 @@ get_pgtable_size (grub_uint64_t from, grub_uint64_t to, grub_uint64_t pfn)
 	  continue;
 	}
 
-      bits = PAGE_SHIFT + (i + 1) * LOG_POINTERS_PER_PAGE;
+      bits = GRUB_PAGE_SHIFT + (i + 1) * LOG_POINTERS_PER_PAGE;
       mask = (1ULL << bits) - 1;
       map->lvls[i].virt_start = map->area.virt_start & ~mask;
       map->lvls[i].virt_end = map->area.virt_end | mask;
@@ -246,11 +246,11 @@ generate_page_table (grub_xen_mfn_t *mfn_list)
 	      if (lvl->virt_start >= end || lvl->virt_end <= start)
 		continue;
 	      p_s = (grub_max (start, lvl->virt_start) - start) >>
-		    (PAGE_SHIFT + l * LOG_POINTERS_PER_PAGE);
+		    (GRUB_PAGE_SHIFT + l * LOG_POINTERS_PER_PAGE);
 	      p_e = (grub_min (end, lvl->virt_end) - start) >>
-		    (PAGE_SHIFT + l * LOG_POINTERS_PER_PAGE);
+		    (GRUB_PAGE_SHIFT + l * LOG_POINTERS_PER_PAGE);
 	      pfn = ((grub_max (start, lvl->virt_start) - lvl->virt_start) >>
-		     (PAGE_SHIFT + l * LOG_POINTERS_PER_PAGE)) + lvl->pfn_start;
+		     (GRUB_PAGE_SHIFT + l * LOG_POINTERS_PER_PAGE)) + lvl->pfn_start;
 	      grub_dprintf ("xen", "write page table entries level %d pg %p "
 			    "mapping %d/%d index %lx-%lx pfn %llx\n",
 			    l, pg, m1, m2, p_s, p_e, (unsigned long long) pfn);
@@ -328,16 +328,16 @@ grub_xen_p2m_alloc (void)
     {
       err = get_pgtable_size (xen_state.xen_inf.p2m_base,
 			      xen_state.xen_inf.p2m_base + p2msize,
-			      (xen_state.max_addr + p2msize) >> PAGE_SHIFT);
+			      (xen_state.max_addr + p2msize) >> GRUB_PAGE_SHIFT);
       if (err)
 	return err;
 
-      map->area.pfn_start = xen_state.max_addr >> PAGE_SHIFT;
+      map->area.pfn_start = xen_state.max_addr >> GRUB_PAGE_SHIFT;
       p2malloc = p2msize + page2offset (map->area.n_pt_pages);
       xen_state.n_mappings++;
       xen_state.next_start.mfn_list = xen_state.xen_inf.p2m_base;
       xen_state.next_start.first_p2m_pfn = map->area.pfn_start;
-      xen_state.next_start.nr_p2m_frames = p2malloc >> PAGE_SHIFT;
+      xen_state.next_start.nr_p2m_frames = p2malloc >> GRUB_PAGE_SHIFT;
     }
   else
     {
@@ -380,7 +380,7 @@ grub_xen_special_alloc (void)
   xen_state.virt_start_info = get_virtual_current_address (ch);
   xen_state.max_addr =
     ALIGN_UP (xen_state.max_addr + sizeof (xen_state.next_start), PAGE_SIZE);
-  xen_state.console_pfn = xen_state.max_addr >> PAGE_SHIFT;
+  xen_state.console_pfn = xen_state.max_addr >> GRUB_PAGE_SHIFT;
   xen_state.max_addr += 2 * PAGE_SIZE;
 
   xen_state.next_start.nr_pages = grub_xen_start_page_addr->nr_pages;
@@ -412,7 +412,7 @@ grub_xen_pt_alloc (void)
 
   xen_state.next_start.pt_base =
     xen_state.max_addr + xen_state.xen_inf.virt_base;
-  nr_info_pages = xen_state.max_addr >> PAGE_SHIFT;
+  nr_info_pages = xen_state.max_addr >> GRUB_PAGE_SHIFT;
   nr_need_pages = nr_info_pages;
 
   while (1)
@@ -460,7 +460,7 @@ grub_xen_pt_alloc (void)
     xen_state.max_addr + STACK_SIZE + xen_state.xen_inf.virt_base;
   xen_state.next_start.nr_pt_frames = nr_need_pages;
   xen_state.max_addr = try_virt_end - xen_state.xen_inf.virt_base;
-  xen_state.pgtbl_end = xen_state.max_addr >> PAGE_SHIFT;
+  xen_state.pgtbl_end = xen_state.max_addr >> GRUB_PAGE_SHIFT;
   xen_state.map_reloc->where = (grub_uint64_t *) ((char *) map->where +
 					page2offset (map->area.n_pt_pages));
 
@@ -514,7 +514,7 @@ grub_xen_boot (void)
   if (err)
     return err;
 
-  nr_pages = xen_state.max_addr >> PAGE_SHIFT;
+  nr_pages = xen_state.max_addr >> GRUB_PAGE_SHIFT;
 
   grub_dprintf ("xen", "bootstrap domain %llx+%llx\n",
 		(unsigned long long) xen_state.xen_inf.virt_base,
@@ -811,7 +811,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
   if (xen_state.xen_inf.unmapped_initrd)
     {
       xen_state.next_start.flags |= SIF_MOD_START_PFN;
-      xen_state.next_start.mod_start = xen_state.max_addr >> PAGE_SHIFT;
+      xen_state.next_start.mod_start = xen_state.max_addr >> GRUB_PAGE_SHIFT;
     }
   else
     xen_state.next_start.mod_start =
diff --git a/include/grub/i386/memory.h b/include/grub/i386/memory.h
index 5cb607fb4..7be57d6d7 100644
--- a/include/grub/i386/memory.h
+++ b/include/grub/i386/memory.h
@@ -20,7 +20,7 @@
 #ifndef GRUB_MEMORY_CPU_HEADER
 #define GRUB_MEMORY_CPU_HEADER	1
 
-#define PAGE_SHIFT		12
+#define GRUB_PAGE_SHIFT		12
 
 /* The flag for protected mode.  */
 #define GRUB_MEMORY_CPU_CR0_PE_ON		0x1
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 05/18] i386/memory: Rename PAGE_SIZE to GRUB_PAGE_SIZE and make it global
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (3 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 04/18] i386/memory: Rename PAGE_SHIFT to GRUB_PAGE_SHIFT Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 06/18] mmap: Add grub_mmap_get_lowest() and grub_mmap_get_highest() Daniel Kiper
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

Subsequent patches will use that constant.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/loader/i386/xen.c | 35 +++++++++++++++++------------------
 include/grub/i386/memory.h  |  1 +
 2 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
index fe92874e0..dfdddfeed 100644
--- a/grub-core/loader/i386/xen.c
+++ b/grub-core/loader/i386/xen.c
@@ -91,8 +91,7 @@ static struct xen_loader_state xen_state;
 
 static grub_dl_t my_mod;
 
-#define PAGE_SIZE (1UL << GRUB_PAGE_SHIFT)
-#define MAX_MODULES (PAGE_SIZE / sizeof (struct xen_multiboot_mod_list))
+#define MAX_MODULES (GRUB_PAGE_SIZE / sizeof (struct xen_multiboot_mod_list))
 #define STACK_SIZE 1048576
 #define ADDITIONAL_SIZE (1 << 19)
 #define ALIGN_SIZE (1 << 22)
@@ -228,7 +227,7 @@ generate_page_table (grub_xen_mfn_t *mfn_list)
 
   for (m1 = 0; m1 < xen_state.n_mappings; m1++)
     grub_memset (xen_state.mappings[m1].where, 0,
-		 xen_state.mappings[m1].area.n_pt_pages * PAGE_SIZE);
+		 xen_state.mappings[m1].area.n_pt_pages * GRUB_PAGE_SIZE);
 
   for (l = NUMBER_OF_LEVELS - 1; l >= 0; l--)
     {
@@ -323,7 +322,7 @@ grub_xen_p2m_alloc (void)
 
   map = xen_state.mappings + xen_state.n_mappings;
   p2msize = ALIGN_UP (sizeof (grub_xen_mfn_t) *
-		      grub_xen_start_page_addr->nr_pages, PAGE_SIZE);
+		      grub_xen_start_page_addr->nr_pages, GRUB_PAGE_SIZE);
   if (xen_state.xen_inf.has_p2m_base)
     {
       err = get_pgtable_size (xen_state.xen_inf.p2m_base,
@@ -379,9 +378,9 @@ grub_xen_special_alloc (void)
   xen_state.state.start_info = xen_state.max_addr + xen_state.xen_inf.virt_base;
   xen_state.virt_start_info = get_virtual_current_address (ch);
   xen_state.max_addr =
-    ALIGN_UP (xen_state.max_addr + sizeof (xen_state.next_start), PAGE_SIZE);
+    ALIGN_UP (xen_state.max_addr + sizeof (xen_state.next_start), GRUB_PAGE_SIZE);
   xen_state.console_pfn = xen_state.max_addr >> GRUB_PAGE_SHIFT;
-  xen_state.max_addr += 2 * PAGE_SIZE;
+  xen_state.max_addr += 2 * GRUB_PAGE_SIZE;
 
   xen_state.next_start.nr_pages = grub_xen_start_page_addr->nr_pages;
   grub_memcpy (xen_state.next_start.magic, grub_xen_start_page_addr->magic,
@@ -430,9 +429,9 @@ grub_xen_pt_alloc (void)
       /* Map the relocator page either at virtual 0 or after end of area. */
       nr_need_pages = nr_info_pages + map->area.n_pt_pages;
       if (xen_state.xen_inf.virt_base)
-	err = get_pgtable_size (0, PAGE_SIZE, nr_need_pages);
+	err = get_pgtable_size (0, GRUB_PAGE_SIZE, nr_need_pages);
       else
-	err = get_pgtable_size (try_virt_end, try_virt_end + PAGE_SIZE,
+	err = get_pgtable_size (try_virt_end, try_virt_end + GRUB_PAGE_SIZE,
 				nr_need_pages);
       if (err)
 	return err;
@@ -537,7 +536,7 @@ grub_xen_boot (void)
 
   return grub_relocator_xen_boot (xen_state.relocator, xen_state.state, nr_pages,
 				  xen_state.xen_inf.virt_base <
-				  PAGE_SIZE ? page2offset (nr_pages) : 0,
+				  GRUB_PAGE_SIZE ? page2offset (nr_pages) : 0,
 				  xen_state.pgtbl_end - 1,
 				  page2offset (xen_state.pgtbl_end - 1) +
 				  xen_state.xen_inf.virt_base);
@@ -675,7 +674,7 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
       goto fail;
     }
 
-  if (xen_state.xen_inf.virt_base & (PAGE_SIZE - 1))
+  if (xen_state.xen_inf.virt_base & (GRUB_PAGE_SIZE - 1))
     {
       grub_error (GRUB_ERR_BAD_OS, "unaligned virt_base");
       goto fail;
@@ -698,10 +697,10 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
       kern_start = grub_min (kern_start, xen_state.xen_inf.hypercall_page -
 					 xen_state.xen_inf.virt_base);
       kern_end = grub_max (kern_end, xen_state.xen_inf.hypercall_page -
-				     xen_state.xen_inf.virt_base + PAGE_SIZE);
+				     xen_state.xen_inf.virt_base + GRUB_PAGE_SIZE);
     }
 
-  xen_state.max_addr = ALIGN_UP (kern_end, PAGE_SIZE);
+  xen_state.max_addr = ALIGN_UP (kern_end, GRUB_PAGE_SIZE);
 
   err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, kern_start,
 					 kern_end - kern_start);
@@ -722,7 +721,7 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
   if (xen_state.xen_inf.has_hypercall_page)
     {
       unsigned i;
-      for (i = 0; i < PAGE_SIZE / HYPERCALL_INTERFACE_SIZE; i++)
+      for (i = 0; i < GRUB_PAGE_SIZE / HYPERCALL_INTERFACE_SIZE; i++)
 	set_hypercall_interface ((grub_uint8_t *) kern_chunk_src +
 				 i * HYPERCALL_INTERFACE_SIZE +
 				 xen_state.xen_inf.hypercall_page -
@@ -821,7 +820,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 		(unsigned) (xen_state.max_addr + xen_state.xen_inf.virt_base),
 		(unsigned) size);
 
-  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, PAGE_SIZE);
+  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, GRUB_PAGE_SIZE);
 
 fail:
   grub_initrd_close (&initrd_ctx);
@@ -875,7 +874,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
     {
       xen_state.xen_inf.unmapped_initrd = 0;
       xen_state.n_modules = 0;
-      xen_state.max_addr = ALIGN_UP (xen_state.max_addr, PAGE_SIZE);
+      xen_state.max_addr = ALIGN_UP (xen_state.max_addr, GRUB_PAGE_SIZE);
       xen_state.modules_target_start = xen_state.max_addr;
       xen_state.next_start.mod_start =
 	xen_state.max_addr + xen_state.xen_inf.virt_base;
@@ -895,7 +894,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
 	MAX_MODULES * sizeof (xen_state.module_info_page[0]);
     }
 
-  xen_state.max_addr = ALIGN_UP (xen_state.max_addr, PAGE_SIZE);
+  xen_state.max_addr = ALIGN_UP (xen_state.max_addr, GRUB_PAGE_SIZE);
 
   file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_INITRD |
 			 (nounzip ? GRUB_FILE_TYPE_NO_DECOMPRESS : GRUB_FILE_TYPE_NONE));
@@ -918,7 +917,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
 
   xen_state.module_info_page[xen_state.n_modules].cmdline =
     xen_state.max_addr - xen_state.modules_target_start;
-  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + cmdline_len, PAGE_SIZE);
+  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + cmdline_len, GRUB_PAGE_SIZE);
 
   if (size)
     {
@@ -945,7 +944,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
   xen_state.n_modules++;
   grub_dprintf ("xen", "module, addr=0x%x, size=0x%x\n",
 		(unsigned) xen_state.max_addr, (unsigned) size);
-  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, PAGE_SIZE);
+  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, GRUB_PAGE_SIZE);
 
 
 fail:
diff --git a/include/grub/i386/memory.h b/include/grub/i386/memory.h
index 7be57d6d7..c64529630 100644
--- a/include/grub/i386/memory.h
+++ b/include/grub/i386/memory.h
@@ -21,6 +21,7 @@
 #define GRUB_MEMORY_CPU_HEADER	1
 
 #define GRUB_PAGE_SHIFT		12
+#define GRUB_PAGE_SIZE		(1UL << GRUB_PAGE_SHIFT)
 
 /* The flag for protected mode.  */
 #define GRUB_MEMORY_CPU_CR0_PE_ON		0x1
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 06/18] mmap: Add grub_mmap_get_lowest() and grub_mmap_get_highest()
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (4 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 05/18] i386/memory: Rename PAGE_SIZE to GRUB_PAGE_SIZE and make it global Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 07/18] i386/tpm: Rename tpm module to tpm_verifier Daniel Kiper
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

The functions calculate lowest and highest available RAM
addresses respectively.

Both functions are needed to calculate PMR boundaries for
Intel TXT secure launcher introduced by subsequent patches.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/mmap/mmap.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/grub/memory.h |  3 +++
 2 files changed, 67 insertions(+)

diff --git a/grub-core/mmap/mmap.c b/grub-core/mmap/mmap.c
index b569cb23b..cf4b69f56 100644
--- a/grub-core/mmap/mmap.c
+++ b/grub-core/mmap/mmap.c
@@ -340,6 +340,70 @@ grub_mmap_unregister (int handle)
 
 #endif /* ! GRUB_MMAP_REGISTER_BY_FIRMWARE */
 
+typedef struct
+{
+  grub_uint64_t addr;
+  grub_uint64_t limit;
+} addr_limit_t;
+
+/* Helper for grub_mmap_get_lowest().  */
+static int
+lowest_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
+	     void *data)
+{
+  addr_limit_t *al = data;
+
+  if (type != GRUB_MEMORY_AVAILABLE)
+    return 0;
+
+  if (addr >= al->limit)
+    al->addr = grub_min (al->addr, addr);
+
+  if ((addr < al->limit) && ((addr + size) > al->limit))
+    al->addr = al->limit;
+
+  return 0;
+}
+
+grub_uint64_t
+grub_mmap_get_lowest (grub_uint64_t limit)
+{
+  addr_limit_t al = {~0, limit};
+
+  grub_mmap_iterate (lowest_hook, &al);
+
+  return al.addr;
+}
+
+/* Helper for grub_mmap_get_highest().  */
+static int
+highest_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
+	      void *data)
+{
+  addr_limit_t *al = data;
+
+  if (type != GRUB_MEMORY_AVAILABLE)
+    return 0;
+
+  if ((addr + size) < al->limit)
+    al->addr = grub_max (al->addr, addr + size);
+
+  if ((addr < al->limit) && ((addr + size) >= al->limit))
+    al->addr = al->limit;
+
+  return 0;
+}
+
+grub_uint64_t
+grub_mmap_get_highest (grub_uint64_t limit)
+{
+  addr_limit_t al = {0, limit};
+
+  grub_mmap_iterate (highest_hook, &al);
+
+  return al.addr;
+}
+
 #define CHUNK_SIZE	0x400
 
 struct badram_entry {
diff --git a/include/grub/memory.h b/include/grub/memory.h
index 6da114a1b..8f22f7525 100644
--- a/include/grub/memory.h
+++ b/include/grub/memory.h
@@ -69,6 +69,9 @@ void *grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size,
 
 void grub_mmap_free_and_unregister (int handle);
 
+extern grub_uint64_t grub_mmap_get_lowest (grub_uint64_t limit);
+extern grub_uint64_t grub_mmap_get_highest (grub_uint64_t limit);
+
 #ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE
 
 struct grub_mmap_region
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 07/18] i386/tpm: Rename tpm module to tpm_verifier
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (5 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 06/18] mmap: Add grub_mmap_get_lowest() and grub_mmap_get_highest() Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 08/18] i386/tpm: Add TPM TIS and CRB driver Daniel Kiper
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

..to avoid naming collision with TPM TIS and CRB driver introduced
by subsequent patch.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 docs/grub.texi                               | 15 ++++++++-------
 grub-core/Makefile.core.def                  |  4 ++--
 grub-core/commands/{tpm.c => tpm_verifier.c} |  6 +++---
 3 files changed, 13 insertions(+), 12 deletions(-)
 rename grub-core/commands/{tpm.c => tpm_verifier.c} (96%)

diff --git a/docs/grub.texi b/docs/grub.texi
index d6408d242..395431bce 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5940,10 +5940,10 @@ it cannot be unloaded if it was loaded into the memory.
 @node Measured Boot
 @section Measuring boot components
 
-If the tpm module is loaded and the platform has a Trusted Platform Module
-installed, GRUB will log each command executed and each file loaded into the
-TPM event log and extend the PCR values in the TPM correspondingly. All events
-will be logged into the PCR described below with a type of EV_IPL and an
+If the tpm_verifier module is loaded and the platform has a Trusted Platform
+Module installed, GRUB will log each command executed and each file loaded into
+the TPM event log and extend the PCR values in the TPM correspondingly. All
+events will be logged into the PCR described below with a type of EV_IPL and an
 event description as described below.
 
 @multitable @columnfractions 0.3 0.1 0.6
@@ -5968,9 +5968,10 @@ corresponding to the filename.
 
 GRUB will not measure its own @file{core.img} - it is expected that firmware
 will carry this out. GRUB will also not perform any measurements until the
-tpm module is loaded. As such it is recommended that the tpm module be built
-into @file{core.img} in order to avoid a potential gap in measurement between
-@file{core.img} being loaded and the tpm module being loaded.
+tpm_verifier module is loaded. As such it is recommended that the tpm_verifier
+module be built into @file{core.img} in order to avoid a potential gap in
+measurement between @file{core.img} being loaded and the tpm_verifier module
+being loaded.
 
 Measured boot is currently only supported on EFI platforms.
 
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 48b82e763..b74a34f0c 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2497,8 +2497,8 @@ module = {
 };
 
 module = {
-  name = tpm;
-  common = commands/tpm.c;
+  name = tpm_verifier;
+  common = commands/tpm_verifier.c;
   efi = commands/efi/tpm.c;
   enable = x86_64_efi;
 };
diff --git a/grub-core/commands/tpm.c b/grub-core/commands/tpm_verifier.c
similarity index 96%
rename from grub-core/commands/tpm.c
rename to grub-core/commands/tpm_verifier.c
index 1441c494d..6fff17720 100644
--- a/grub-core/commands/tpm.c
+++ b/grub-core/commands/tpm_verifier.c
@@ -85,18 +85,18 @@ grub_tpm_verify_string (char *str, enum grub_verify_string_type type)
 }
 
 struct grub_file_verifier grub_tpm_verifier = {
-  .name = "tpm",
+  .name = "tpm_verifier",
   .init = grub_tpm_verify_init,
   .write = grub_tpm_verify_write,
   .verify_string = grub_tpm_verify_string,
 };
 
-GRUB_MOD_INIT (tpm)
+GRUB_MOD_INIT (tpm_verifier)
 {
   grub_verifier_register (&grub_tpm_verifier);
 }
 
-GRUB_MOD_FINI (tpm)
+GRUB_MOD_FINI (tpm_verifier)
 {
   grub_verifier_unregister (&grub_tpm_verifier);
 }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 08/18] i386/tpm: Add TPM TIS and CRB driver
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (6 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 07/18] i386/tpm: Rename tpm module to tpm_verifier Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 09/18] efi: Make shim_lock GUID and protocol type public Daniel Kiper
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

It will be used by Intel TXT secure launcher introduced
by subsequent patches.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/i386/tpm.c | 182 ++++++++++++++++++++++++++++++++++++++++++
 include/grub/i386/tpm.h       |  36 +++++++++
 2 files changed, 218 insertions(+)
 create mode 100644 grub-core/commands/i386/tpm.c
 create mode 100644 include/grub/i386/tpm.h

diff --git a/grub-core/commands/i386/tpm.c b/grub-core/commands/i386/tpm.c
new file mode 100644
index 000000000..ff29c2e85
--- /dev/null
+++ b/grub-core/commands/i386/tpm.c
@@ -0,0 +1,182 @@
+/*
+ *  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/>.
+ *
+ *  TPM TIS and CRB driver.
+ *
+ *  Note: It is suggested to not use this driver together with UEFI TPM driver.
+ */
+
+#include <grub/command.h>
+#include <grub/dl.h>
+#include <grub/err.h>
+#include <grub/i386/memory.h>
+#include <grub/i386/mmio.h>
+#include <grub/i386/tpm.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define TPM_MMIO_BASE		0xfed40000
+
+/* TIS registers. */
+#define TPM_ACCESS		0x0000
+#define TPM_INTF_CAPABILITY	0x0014
+#define TPM_INTERFACE_ID	0x0030
+
+/* CRB registers. */
+#define TPM_LOC_CTRL		0x0008
+
+#define TPM_12_TIS_INTF_12	0x0
+#define TPM_12_TIS_INTF_13	0x2
+#define TPM_20_TIS_INTF_13	0x3
+
+#define TPM_CRB_INTF_ACTIVE	0x1
+
+#define TIS_RELINQUISH_LCL	0x20
+#define CRB_RELINQUISH_LCL	0x0002
+
+/* TODO: Do we need GRUB_PACKED for unions below??? */
+
+union tpm_interface_id
+{
+  grub_uint32_t raw;
+  struct
+  {
+    grub_uint32_t interface_type:4;
+    grub_uint32_t interface_version:4;
+    grub_uint32_t cap_locality:1;
+    grub_uint32_t reserved_0:4;
+    grub_uint32_t cap_tis:1;
+    grub_uint32_t cap_crb:1;
+    grub_uint32_t cap_ifres:2;
+    grub_uint32_t interface_selector:2;
+    grub_uint32_t intf_sel_lock:1;
+    grub_uint32_t reserved_1:4;
+    grub_uint32_t reserved_2:8;
+  };
+} GRUB_PACKED;
+typedef union tpm_interface_id tpm_interface_id_t;
+
+union tpm_intf_capability
+{
+  grub_uint32_t raw;
+  struct
+  {
+    grub_uint32_t data_avail_int_support:1;
+    grub_uint32_t sts_valid_int_support:1;
+    grub_uint32_t locality_change_int_support:1;
+    grub_uint32_t interrupt_level_high:1;
+    grub_uint32_t interrupt_level_low:1;
+    grub_uint32_t interrupt_edge_rising:1;
+    grub_uint32_t interrupt_edge_falling:1;
+    grub_uint32_t command_ready_int_support:1;
+    grub_uint32_t burst_count_static:1;
+    grub_uint32_t data_transfer_size_support:2;
+    grub_uint32_t reserved_0:17;
+    grub_uint32_t interface_version:3;
+    grub_uint32_t reserved_1:1;
+  };
+} GRUB_PACKED;
+typedef union tpm_intf_capability tpm_intf_capability_t;
+
+typedef enum
+  {
+    TPM_INTF_NONE = 0,
+    TPM_INTF_TIS,
+    TPM_INTF_CRB
+  }
+tpm_intf_t;
+
+static grub_tpm_ver_t tpm_ver = GRUB_TPM_NONE;
+static tpm_intf_t tpm_intf = TPM_INTF_NONE;
+
+grub_tpm_ver_t
+grub_get_tpm_ver (void)
+{
+  return tpm_ver;
+}
+
+/* Localities 0-4 are supported only. */
+void
+grub_tpm_relinquish_lcl (grub_uint8_t lcl)
+{
+  grub_addr_t addr = TPM_MMIO_BASE + lcl * GRUB_PAGE_SIZE;
+
+  if (tpm_intf == TPM_INTF_TIS)
+    grub_writeb (TIS_RELINQUISH_LCL, (void *) (addr + TPM_ACCESS));
+  else if (tpm_intf == TPM_INTF_CRB)
+    grub_writel (CRB_RELINQUISH_LCL, (void *) (addr + TPM_LOC_CTRL));
+}
+
+static grub_err_t
+grub_cmd_tpm_type (grub_command_t cmd __attribute__ ((unused)),
+		   int argc __attribute__ ((unused)),
+		   char *argv[] __attribute__ ((unused)))
+{
+  const char *tpm_ver_s = "NONE";
+  const char *tpm_intf_s = "NONE";
+
+  if (tpm_ver == GRUB_TPM_12)
+    tpm_ver_s = "1.2";
+  else if (tpm_ver == GRUB_TPM_20)
+    tpm_ver_s = "2.0";
+
+  if (tpm_intf == TPM_INTF_TIS)
+    tpm_intf_s = "TIS";
+  else if (tpm_intf == TPM_INTF_CRB)
+    tpm_intf_s = "CRB";
+
+  grub_printf ("TPM VER: %s\nTPM INTF: %s\n", tpm_ver_s, tpm_intf_s);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd_tpm_type;
+
+GRUB_MOD_INIT (tpm)
+{
+  tpm_interface_id_t intf_id;
+  tpm_intf_capability_t intf_cap;
+
+  cmd_tpm_type = grub_register_command ("tpm_type", grub_cmd_tpm_type,
+					NULL, N_("Show TPM version and interface type."));
+
+  intf_cap.raw = grub_readl ((void *)(grub_addr_t) (TPM_MMIO_BASE + TPM_INTF_CAPABILITY));
+
+  if (intf_cap.interface_version == TPM_12_TIS_INTF_12 ||
+      intf_cap.interface_version == TPM_12_TIS_INTF_13)
+    {
+      tpm_ver = GRUB_TPM_12;
+      tpm_intf = TPM_INTF_TIS;
+      return;
+    }
+
+  if (intf_cap.interface_version != TPM_20_TIS_INTF_13)
+    return;
+
+  tpm_ver = GRUB_TPM_20;
+
+  intf_id.raw = grub_readl ((void *)(grub_addr_t) (TPM_MMIO_BASE + TPM_INTERFACE_ID));
+
+  tpm_intf = (intf_id.interface_type == TPM_CRB_INTF_ACTIVE) ? TPM_INTF_CRB : TPM_INTF_TIS;
+}
+
+GRUB_MOD_FINI (tpm)
+{
+  grub_unregister_command (cmd_tpm_type);
+}
diff --git a/include/grub/i386/tpm.h b/include/grub/i386/tpm.h
new file mode 100644
index 000000000..ae8d4a27d
--- /dev/null
+++ b/include/grub/i386/tpm.h
@@ -0,0 +1,36 @@
+/*
+ *  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_I386_TPM_H
+#define GRUB_I386_TPM_H 1
+
+#include <grub/types.h>
+
+typedef enum
+  {
+    GRUB_TPM_NONE = 0,
+    GRUB_TPM_12,
+    GRUB_TPM_20
+  }
+grub_tpm_ver_t;
+
+extern grub_tpm_ver_t grub_get_tpm_ver (void);
+extern void grub_tpm_relinquish_lcl (grub_uint8_t lcl);
+
+#endif /* GRUB_I386_TPM_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 09/18] efi: Make shim_lock GUID and protocol type public
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (7 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 08/18] i386/tpm: Add TPM TIS and CRB driver Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 10/18] efi: Return grub_efi_status_t from grub_efi_get_variable() Daniel Kiper
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

The GUID will be used to properly detect and report UEFI Secure Boot
status to the x86 Linux kernel. The functionality will be added by
subsequent patches. The shim_lock protocol type is made public for
completeness.

Additionally, fix formatting of four preceding GUIDs.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/efi/shim_lock.c | 12 ------------
 include/grub/efi/api.h             | 19 +++++++++++++++----
 2 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/grub-core/commands/efi/shim_lock.c b/grub-core/commands/efi/shim_lock.c
index 764098cfc..d8f52d721 100644
--- a/grub-core/commands/efi/shim_lock.c
+++ b/grub-core/commands/efi/shim_lock.c
@@ -27,18 +27,6 @@
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
-#define GRUB_EFI_SHIM_LOCK_GUID \
-  { 0x605dab50, 0xe046, 0x4300, \
-    { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \
-  }
-
-struct grub_efi_shim_lock_protocol
-{
-  grub_efi_status_t
-  (*verify) (void *buffer, grub_uint32_t size);
-};
-typedef struct grub_efi_shim_lock_protocol grub_efi_shim_lock_protocol_t;
-
 static grub_efi_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID;
 static grub_efi_shim_lock_protocol_t *sl;
 
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 937058d68..e634afd61 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -321,22 +321,27 @@
 
 #define GRUB_EFI_SAL_TABLE_GUID \
   { 0xeb9d2d32, 0x2d88, 0x11d3, \
-      { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+    { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
   }
 
 #define GRUB_EFI_HCDP_TABLE_GUID \
   { 0xf951938d, 0x620b, 0x42ef, \
-      { 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 } \
+    { 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 } \
   }
 
 #define GRUB_EFI_DEVICE_TREE_GUID \
   { 0xb1b621d5, 0xf19c, 0x41a5, \
-      { 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 } \
+    { 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 } \
   }
 
 #define GRUB_EFI_VENDOR_APPLE_GUID \
   { 0x2B0585EB, 0xD8B8, 0x49A9,	\
-      { 0x8B, 0x8C, 0xE2, 0x1B, 0x01, 0xAE, 0xF2, 0xB7 } \
+    { 0x8B, 0x8C, 0xE2, 0x1B, 0x01, 0xAE, 0xF2, 0xB7 } \
+  }
+
+#define GRUB_EFI_SHIM_LOCK_GUID \
+  { 0x605dab50, 0xe046, 0x4300, \
+    { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \
   }
 
 struct grub_efi_sal_system_table
@@ -1690,6 +1695,12 @@ struct grub_efi_block_io
 };
 typedef struct grub_efi_block_io grub_efi_block_io_t;
 
+struct grub_efi_shim_lock_protocol
+{
+  grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
+};
+typedef struct grub_efi_shim_lock_protocol grub_efi_shim_lock_protocol_t;
+
 #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
   || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \
   || defined(__riscv)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 10/18] efi: Return grub_efi_status_t from grub_efi_get_variable()
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (8 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 09/18] efi: Make shim_lock GUID and protocol type public Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 11/18] efi: Add a function to read EFI variables with attributes Daniel Kiper
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

This is needed to properly detect and report UEFI Secure Boot status
to the x86 Linux kernel. The functionality will be added by subsequent
patches.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/efi/efifwsetup.c |  8 ++++----
 grub-core/kern/efi/efi.c            | 16 +++++++++-------
 grub-core/video/efi_gop.c           |  2 +-
 include/grub/efi/efi.h              |  7 ++++---
 4 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/grub-core/commands/efi/efifwsetup.c b/grub-core/commands/efi/efifwsetup.c
index 7a137a72a..eaca03283 100644
--- a/grub-core/commands/efi/efifwsetup.c
+++ b/grub-core/commands/efi/efifwsetup.c
@@ -38,8 +38,8 @@ grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)),
   grub_size_t oi_size;
   grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
 
-  old_os_indications = grub_efi_get_variable ("OsIndications", &global,
-					      &oi_size);
+  grub_efi_get_variable ("OsIndications", &global, &oi_size,
+			 (void **) &old_os_indications);
 
   if (old_os_indications != NULL && oi_size == sizeof (os_indications))
     os_indications |= *old_os_indications;
@@ -63,8 +63,8 @@ efifwsetup_is_supported (void)
   grub_size_t oi_size = 0;
   grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
 
-  os_indications_supported = grub_efi_get_variable ("OsIndicationsSupported",
-						    &global, &oi_size);
+  grub_efi_get_variable ("OsIndicationsSupported", &global, &oi_size,
+			 (void **) &os_indications_supported);
 
   if (!os_indications_supported)
     return 0;
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 3a708ed72..81bc49f84 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -222,9 +222,9 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
   return grub_error (GRUB_ERR_IO, "could not set EFI variable `%s'", var);
 }
 
-void *
+grub_efi_status_t
 grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
-		       grub_size_t *datasize_out)
+		       grub_size_t *datasize_out, void **data_out)
 {
   grub_efi_status_t status;
   grub_efi_uintn_t datasize = 0;
@@ -233,13 +233,14 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
   void *data;
   grub_size_t len, len16;
 
+  *data_out = NULL;
   *datasize_out = 0;
 
   len = grub_strlen (var);
   len16 = len * GRUB_MAX_UTF16_PER_UTF8;
   var16 = grub_malloc ((len16 + 1) * sizeof (var16[0]));
   if (!var16)
-    return NULL;
+    return GRUB_EFI_OUT_OF_RESOURCES;
   len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL);
   var16[len16] = 0;
 
@@ -250,14 +251,14 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
   if (status != GRUB_EFI_BUFFER_TOO_SMALL || !datasize)
     {
       grub_free (var16);
-      return NULL;
+      return status;
     }
 
   data = grub_malloc (datasize);
   if (!data)
     {
       grub_free (var16);
-      return NULL;
+      return GRUB_EFI_OUT_OF_RESOURCES;
     }
 
   status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, data);
@@ -265,12 +266,13 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
 
   if (status == GRUB_EFI_SUCCESS)
     {
+      *data_out = data;
       *datasize_out = datasize;
-      return data;
+      return status;
     }
 
   grub_free (data);
-  return NULL;
+  return status;
 }
 
 #pragma GCC diagnostic ignored "-Wcast-align"
diff --git a/grub-core/video/efi_gop.c b/grub-core/video/efi_gop.c
index be446f8d2..7fe0cdabf 100644
--- a/grub-core/video/efi_gop.c
+++ b/grub-core/video/efi_gop.c
@@ -316,7 +316,7 @@ grub_video_gop_get_edid (struct grub_video_edid_info *edid_info)
       char edidname[] = "agp-internal-edid";
       grub_size_t datasize;
       grub_uint8_t *data;
-      data = grub_efi_get_variable (edidname, &efi_var_guid, &datasize);
+      grub_efi_get_variable (edidname, &efi_var_guid, &datasize, (void **) &data);
       if (data && datasize > 16)
 	{
 	  copy_size = datasize - 16;
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index e90e00dc4..8b2a0f1f5 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -74,9 +74,10 @@ grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memo
 							   grub_efi_uintn_t descriptor_size,
 							   grub_efi_uint32_t descriptor_version,
 							   grub_efi_memory_descriptor_t *virtual_map);
-void *EXPORT_FUNC (grub_efi_get_variable) (const char *variable,
-					   const grub_efi_guid_t *guid,
-					   grub_size_t *datasize_out);
+grub_efi_status_t EXPORT_FUNC (grub_efi_get_variable) (const char *variable,
+						       const grub_efi_guid_t *guid,
+						       grub_size_t *datasize_out,
+						       void **data_out);
 grub_err_t
 EXPORT_FUNC (grub_efi_set_variable) (const char *var,
 				     const grub_efi_guid_t *guid,
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 11/18] efi: Add a function to read EFI variables with attributes
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (9 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 10/18] efi: Return grub_efi_status_t from grub_efi_get_variable() Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 12/18] i386/efi: Report UEFI Secure Boot status to the Linux kernel Daniel Kiper
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

It will be used to properly detect and report UEFI Secure Boot status to
the x86 Linux kernel. The functionality will be added by subsequent patches.

Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/efi/efi.c | 16 +++++++++++++---
 include/grub/efi/efi.h   |  5 +++++
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 81bc49f84..7eeac6019 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -223,8 +223,11 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
 }
 
 grub_efi_status_t
-grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
-		       grub_size_t *datasize_out, void **data_out)
+grub_efi_get_variable_with_attributes (const char *var,
+				       const grub_efi_guid_t *guid,
+				       grub_size_t *datasize_out,
+				       void **data_out,
+				       grub_efi_uint32_t *attributes)
 {
   grub_efi_status_t status;
   grub_efi_uintn_t datasize = 0;
@@ -261,7 +264,7 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
       return GRUB_EFI_OUT_OF_RESOURCES;
     }
 
-  status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, data);
+  status = efi_call_5 (r->get_variable, var16, guid, attributes, &datasize, data);
   grub_free (var16);
 
   if (status == GRUB_EFI_SUCCESS)
@@ -275,6 +278,13 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
   return status;
 }
 
+grub_efi_status_t
+grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
+		       grub_size_t *datasize_out, void **data_out)
+{
+  return grub_efi_get_variable_with_attributes (var, guid, datasize_out, data_out, NULL);
+}
+
 #pragma GCC diagnostic ignored "-Wcast-align"
 
 /* Search the mods section from the PE32/PE32+ image. This code uses
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 8b2a0f1f5..83d958f99 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -74,6 +74,11 @@ grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memo
 							   grub_efi_uintn_t descriptor_size,
 							   grub_efi_uint32_t descriptor_version,
 							   grub_efi_memory_descriptor_t *virtual_map);
+grub_efi_status_t EXPORT_FUNC (grub_efi_get_variable_with_attributes) (const char *variable,
+								       const grub_efi_guid_t *guid,
+								       grub_size_t *datasize_out,
+								       void **data_out,
+								       grub_efi_uint32_t *attributes);
 grub_efi_status_t EXPORT_FUNC (grub_efi_get_variable) (const char *variable,
 						       const grub_efi_guid_t *guid,
 						       grub_size_t *datasize_out,
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 12/18] i386/efi: Report UEFI Secure Boot status to the Linux kernel
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (10 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 11/18] efi: Add a function to read EFI variables with attributes Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-05 17:29   ` Matthew Garrett
  2020-05-04 23:21 ` [GRUB PATCH RFC 13/18] i386/slaunch: Add basic platform support for secure launch Daniel Kiper
                   ` (6 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

Otherwise the kernel does not know its state and cannot enable various
security features depending on UEFI Secure Boot.

Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/loader/i386/linux.c | 86 ++++++++++++++++++++++++++++++++++++++++++-
 include/grub/i386/linux.h     | 14 ++++++-
 2 files changed, 97 insertions(+), 3 deletions(-)

diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index ac1fae72e..952eb1191 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -397,6 +397,87 @@ grub_linux_boot_mmap_fill (grub_uint64_t addr, grub_uint64_t size,
   return 0;
 }
 
+#ifdef GRUB_MACHINE_EFI
+/*
+ * 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().
+ */
+static grub_uint8_t
+grub_efi_get_secureboot (void)
+{
+  grub_efi_guid_t efi_variable_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
+  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_LINUX_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_LINUX_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_LINUX_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_LINUX_EFI_SECUREBOOT_MODE_ENABLED;
+      goto out;
+    }
+
+  if (!(attr & GRUB_EFI_VARIABLE_RUNTIME_ACCESS) && *moksbstate == 1)
+    secureboot = GRUB_LINUX_EFI_SECUREBOOT_MODE_DISABLED;
+
+  secureboot = GRUB_LINUX_EFI_SECUREBOOT_MODE_ENABLED;
+
+ out:
+  grub_free (moksbstate);
+  grub_free (setupmode);
+  grub_free (secboot);
+
+  if (secureboot == GRUB_LINUX_EFI_SECUREBOOT_MODE_DISABLED)
+    secureboot_str = "Disabled";
+  else if (secureboot == GRUB_LINUX_EFI_SECUREBOOT_MODE_ENABLED)
+    secureboot_str = "Enabled";
+
+  grub_dprintf ("linux", "UEFI Secure Boot state: %s\n", secureboot_str);
+
+  return secureboot;
+}
+#endif
+
 static grub_err_t
 grub_linux_boot (void)
 {
@@ -579,6 +660,9 @@ grub_linux_boot (void)
     grub_efi_uintn_t efi_desc_size;
     grub_size_t efi_mmap_target;
     grub_efi_uint32_t efi_desc_version;
+
+    ctx.params->secure_boot = grub_efi_get_secureboot ();
+
     err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL,
 					 &efi_desc_size, &efi_desc_version);
     if (err)
@@ -790,7 +874,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 
   linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR;
   linux_params.kernel_alignment = (1 << align);
-  linux_params.ps_mouse = linux_params.padding10 = 0;
+  linux_params.ps_mouse = linux_params.padding11 = 0;
   linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
 
   /* These two are used (instead of cmd_line_ptr) by older versions of Linux,
diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
index ce30e7fb0..6aea73ddb 100644
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -49,6 +49,12 @@
 /* Maximum number of MBR signatures to store. */
 #define EDD_MBR_SIG_MAX			16
 
+/* Possible values for Linux secure_boot kernel parameter. */
+#define GRUB_LINUX_EFI_SECUREBOOT_MODE_UNSET	0
+#define GRUB_LINUX_EFI_SECUREBOOT_MODE_UNKNOWN	1
+#define GRUB_LINUX_EFI_SECUREBOOT_MODE_DISABLED	2
+#define GRUB_LINUX_EFI_SECUREBOOT_MODE_ENABLED	3
+
 #ifdef __x86_64__
 
 #define GRUB_LINUX_EFI_SIGNATURE	\
@@ -275,7 +281,11 @@ struct linux_kernel_params
 
   grub_uint8_t mmap_size;		/* 1e8 */
 
-  grub_uint8_t padding9[0x1f1 - 0x1e9];
+  grub_uint8_t padding9[0x1ec - 0x1e9];
+
+  grub_uint8_t secure_boot;             /* 1ec */
+
+  grub_uint8_t padding10[0x1f1 - 0x1ed];
 
   /* Linux setup header copy - BEGIN. */
   grub_uint8_t setup_sects;		/* The size of the setup in sectors */
@@ -286,7 +296,7 @@ struct linux_kernel_params
   grub_uint16_t vid_mode;		/* Video mode control */
   grub_uint16_t root_dev;		/* Default root device number */
 
-  grub_uint8_t padding10;		/* 1fe */
+  grub_uint8_t padding11;		/* 1fe */
   grub_uint8_t ps_mouse;		/* 1ff */
 
   grub_uint16_t jump;			/* Jump instruction */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 13/18] i386/slaunch: Add basic platform support for secure launch
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (11 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 12/18] i386/efi: Report UEFI Secure Boot status to the Linux kernel Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 14/18] i386/txt: Add Intel TXT definitions header file Daniel Kiper
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

From: Ross Philipson <ross.philipson@oracle.com>

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 include/grub/i386/cpuid.h |  13 ++++
 include/grub/i386/crfr.h  | 186 ++++++++++++++++++++++++++++++++++++++++++++++
 include/grub/i386/mmio.h  |  90 ++++++++++++++++++++++
 include/grub/i386/msr.h   |  61 +++++++++++++++
 4 files changed, 350 insertions(+)
 create mode 100644 include/grub/i386/crfr.h
 create mode 100644 include/grub/i386/mmio.h

diff --git a/include/grub/i386/cpuid.h b/include/grub/i386/cpuid.h
index f7ae4b0a4..8176e5d11 100644
--- a/include/grub/i386/cpuid.h
+++ b/include/grub/i386/cpuid.h
@@ -19,6 +19,19 @@
 #ifndef GRUB_CPU_CPUID_HEADER
 #define GRUB_CPU_CPUID_HEADER 1
 
+/* General  */
+#define GRUB_X86_CPUID_VENDOR	0x00000000
+#define GRUB_X86_CPUID_FEATURES	0x00000001
+
+/* Intel  */
+#define GRUB_VMX_CPUID_FEATURE	(1<<5)
+#define GRUB_SMX_CPUID_FEATURE	(1<<6)
+
+/* AMD  */
+#define GRUB_AMD_CPUID_FEATURES	0x80000001
+#define GRUB_SVM_CPUID_FEATURE	(1<<2)
+#define GRUB_AMD_CPUID_FUNC	0x8000000a
+
 extern unsigned char grub_cpuid_has_longmode;
 extern unsigned char grub_cpuid_has_pae;
 
diff --git a/include/grub/i386/crfr.h b/include/grub/i386/crfr.h
new file mode 100644
index 000000000..284d6967b
--- /dev/null
+++ b/include/grub/i386/crfr.h
@@ -0,0 +1,186 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  Oracle and/or its affiliates.
+ *
+ *  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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CRFR_H
+#define GRUB_CRFR_H 1
+
+#include <grub/types.h>
+
+/* Routines for R/W of control and flags registers */
+
+#define GRUB_CR0_X86_PE		0x00000001 /* Enable Protected Mode */
+#define GRUB_CR0_X86_MP		0x00000002 /* "Math" (FPU) Present */
+#define GRUB_CR0_X86_EM		0x00000004 /* EMulate FPU */
+#define GRUB_CR0_X86_TS		0x00000008 /* Task Switched */
+#define GRUB_CR0_X86_PG		0x80000000 /* Enable PaGing */
+
+#define GRUB_CR0_X86_NE		0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */
+#define GRUB_CR0_X86_WP		0x00010000 /* Write Protect */
+#define GRUB_CR0_X86_AM		0x00040000 /* Alignment Mask */
+#define GRUB_CR0_X86_NW		0x20000000 /* Not Write-through */
+#define GRUB_CR0_X86_CD		0x40000000 /* Cache Disable */
+
+#define GRUB_CR4_X86_VME	0x00000001 /* Virtual 8086 mode extensions */
+#define GRUB_CR4_X86_PVI	0x00000002 /* Protected-mode virtual interrupts */
+#define GRUB_CR4_X86_TSD	0x00000004 /* Time stamp disable */
+#define GRUB_CR4_X86_DE		0x00000008 /* Debugging extensions */
+#define GRUB_CR4_X86_PSE	0x00000010 /* Page size extensions */
+#define GRUB_CR4_X86_PAE	0x00000020 /* Physical address extension */
+#define GRUB_CR4_X86_MCE	0x00000040 /* Enable Machine check enable */
+#define GRUB_CR4_X86_PGE	0x00000080 /* Enable Page global */
+#define GRUB_CR4_X86_PCE	0x00000100 /* Enable Performance monitoring counter */
+#define GRUB_CR4_X86_FXSR	0x00000200 /* Fast FPU save/restore */
+#define GRUB_CR4_X86_XMM	0x00000400 /* Enable SIMD/MMX2 to use except 16 */
+#define GRUB_CR4_X86_VMXE	0x00002000 /* Enable VMX */
+#define GRUB_CR4_X86_SMXE	0x00004000 /* Enable SMX */
+#define GRUB_CR4_X86_PCIDE	0x00020000 /* Enable PCID */
+
+static inline unsigned long
+grub_read_cr4 (void)
+{
+  unsigned long val;
+
+  asm volatile ("mov %%cr4, %0" : "=r" (val) : : "memory");
+
+  return val;
+}
+
+static inline void
+grub_write_cr4 (unsigned long val)
+{
+  asm volatile ("mov %0, %%cr4" : : "r" (val) : "memory");
+}
+
+#define GRUB_CR0	0
+#define GRUB_CR1	1
+#define GRUB_CR2	2
+#define GRUB_CR3	3
+#define GRUB_CR4	4
+
+#ifdef __x86_64__
+#define read_cr(r, d) asm volatile ("movq %%cr" r ", %0" : "=r" (d))
+#else
+#define read_cr(r, d) asm volatile ("movl %%cr" r ", %0" : "=r" (d))
+#endif
+
+static inline unsigned long
+grub_read_control_register(grub_uint8_t reg)
+{
+  unsigned long data;
+
+  switch (reg)
+  {
+  case GRUB_CR0:
+    read_cr("0", data);
+    break;
+  case GRUB_CR1:
+    read_cr("1", data);
+    break;
+  case GRUB_CR2:
+    read_cr("2", data);
+    break;
+  case GRUB_CR3:
+    read_cr("3", data);
+    break;
+  case GRUB_CR4:
+    read_cr("4", data);
+    break;
+  default:
+    /* TODO: Loudly complain if this is called. Even some kind of BUG() */
+    data = ~0UL;
+    break;
+  }
+
+  return data;
+}
+
+#ifdef __x86_64__
+#define write_cr(r, d) asm volatile ("movq %0, %%cr" r : : "r" (d))
+#else
+#define write_cr(r, d) asm volatile ("movl %0, %%cr" r : : "r" (d))
+#endif
+
+static inline void
+grub_write_control_register(grub_uint8_t reg, unsigned long data)
+{
+  switch (reg)
+  {
+  case GRUB_CR0:
+    write_cr("0", data);
+    break;
+  case GRUB_CR1:
+    write_cr("1", data);
+    break;
+  case GRUB_CR2:
+    write_cr("2", data);
+    break;
+  case GRUB_CR3:
+    write_cr("3", data);
+    break;
+  case GRUB_CR4:
+    write_cr("4", data);
+    break;
+  default:
+    /* TODO: Loudly complain if this is called. Even some kind of BUG() */
+    ;
+  }
+}
+
+#define GRUB_EFLAGS_X86_CF	0x00000001 /* Carry Flag */
+#define GRUB_EFLAGS_X86_PF	0x00000004 /* Parity Flag */
+#define GRUB_EFLAGS_X86_AF	0x00000010 /* Auxillary carry Flag */
+#define GRUB_EFLAGS_X86_ZF	0x00000040 /* Zero Flag */
+#define GRUB_EFLAGS_X86_SF	0x00000080 /* Sign Flag */
+#define GRUB_EFLAGS_X86_TF	0x00000100 /* Trap Flag */
+#define GRUB_EFLAGS_X86_IF	0x00000200 /* Interrupt Flag */
+#define GRUB_EFLAGS_X86_DF	0x00000400 /* Direction Flag */
+#define GRUB_EFLAGS_X86_OF	0x00000800 /* Overflow Flag */
+#define GRUB_EFLAGS_X86_IOPL	0x00003000 /* IOPL mask */
+#define GRUB_EFLAGS_X86_NT	0x00004000 /* Nested Task */
+#define GRUB_EFLAGS_X86_RF	0x00010000 /* Resume Flag */
+#define GRUB_EFLAGS_X86_VM	0x00020000 /* Virtual Mode */
+#define GRUB_EFLAGS_X86_AC	0x00040000 /* Alignment Check */
+#define GRUB_EFLAGS_X86_VIF	0x00080000 /* Virtual Interrupt Flag */
+#define GRUB_EFLAGS_X86_VIP	0x00100000 /* Virtual Interrupt Pending */
+#define GRUB_EFLAGS_X86_ID	0x00200000 /* CPUID detection flag */
+
+static inline unsigned long
+grub_read_flags_register(void)
+{
+  unsigned long flags;
+
+#ifdef __x86_64__
+  asm volatile ("pushfq; popq %0" : "=r" (flags));
+#else
+  asm volatile ("pushfl; popl %0" : "=r" (flags));
+#endif
+
+  return flags;
+}
+
+static inline void
+grub_write_flags_register(unsigned long flags)
+{
+#ifdef __x86_64__
+  asm volatile ("pushq %0; popfq" : : "r" (flags));
+#else
+  asm volatile ("pushl %0; popfl" : : "r" (flags));
+#endif
+}
+
+#endif
diff --git a/include/grub/i386/mmio.h b/include/grub/i386/mmio.h
new file mode 100644
index 000000000..6f5bf18ce
--- /dev/null
+++ b/include/grub/i386/mmio.h
@@ -0,0 +1,90 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  Oracle and/or its affiliates.
+ *
+ *  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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_I386_MMIO_H
+#define GRUB_I386_MMIO_H 1
+
+#include <grub/types.h>
+
+/* TODO: Are these barirers really needed??? */
+#define grub_mb()	asm volatile ("mfence" : : : "memory")
+#define grub_rmb()	asm volatile ("lfence" : : : "memory")
+#define grub_wmb()	asm volatile ("sfence" : : : "memory")
+#define grub_barrier()	asm volatile ("" : : : "memory")
+
+static inline grub_uint8_t
+grub_readb (const volatile void *addr)
+{
+  grub_uint8_t val;
+
+  grub_barrier ();
+  val = (*(volatile grub_uint8_t *) (addr));
+  grub_rmb ();
+
+  return val;
+}
+
+static inline grub_uint32_t
+grub_readl (const volatile void *addr)
+{
+  grub_uint32_t val;
+
+  grub_barrier ();
+  val = (*(volatile grub_uint32_t *) (addr));
+  grub_rmb ();
+
+  return val;
+}
+
+static inline grub_uint64_t
+grub_readq (const volatile void *addr)
+{
+  grub_uint64_t val;
+
+  grub_barrier ();
+  val = (*(volatile grub_uint64_t *) (addr));
+  grub_rmb ();
+
+  return val;
+}
+
+static inline void
+grub_writeb (grub_uint8_t val, volatile void *addr)
+{
+  grub_wmb ();
+  (*(volatile grub_uint8_t *) (addr)) = val;
+  grub_barrier ();
+}
+
+static inline void
+grub_writel (grub_uint32_t val, volatile void *addr)
+{
+  grub_wmb ();
+  (*(volatile grub_uint32_t *) (addr)) = val;
+  grub_barrier ();
+}
+
+static inline void
+grub_writeq (grub_uint64_t val, volatile void *addr)
+{
+  grub_wmb ();
+  (*(volatile grub_uint64_t *) (addr)) = val;
+  grub_barrier ();
+}
+
+#endif /* GRUB_I386_MMIO_H */
diff --git a/include/grub/i386/msr.h b/include/grub/i386/msr.h
index 1e838c022..f2552ecbc 100644
--- a/include/grub/i386/msr.h
+++ b/include/grub/i386/msr.h
@@ -2,6 +2,9 @@
  *  GRUB  --  GRand Unified Bootloader
  *  Copyright (C) 2019  Free Software Foundation, Inc.
  *
+ *  Some definitions in this header are extracted from the Trusted Computing
+ *  Group's "TPM Main Specification", Parts 1-3.
+ *
  *  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
@@ -19,6 +22,62 @@
 #ifndef GRUB_I386_MSR_H
 #define GRUB_I386_MSR_H 1
 
+/* General */
+#define GRUB_MSR_X86_PLATFORM_ID	0x00000017
+
+#define GRUB_MSR_X86_APICBASE		0x0000001b
+#define GRUB_MSR_X86_APICBASE_BSP	(1<<8)
+#define GRUB_MSR_X86_APICBASE_ENABLE	(1<<11)
+#define GRUB_MSR_X86_APICBASE_BASE	(0xfffff<<12)
+
+#define GRUB_MSR_X86_FEATURE_CONTROL	0x0000003a
+#define GRUB_MSR_X86_ENABLE_VMX_IN_SMX	(1<<1)
+#define GRUB_MSR_X86_SENTER_FUNCTIONS	(0x7f<<8)
+#define GRUB_MSR_X86_SENTER_ENABLE	(1<<15)
+
+#define GRUB_MSR_X86_MTRRCAP		0x000000fe
+#define GRUB_MSR_X86_VCNT_MASK		0xff
+
+#define GRUB_MSR_X86_MCG_CAP		0x00000179
+#define GRUB_MSR_MCG_BANKCNT_MASK	0xff      /* Number of banks  */
+#define GRUB_MSR_X86_MCG_STATUS		0x0000017a
+#define GRUB_MSR_MCG_STATUS_MCIP	(1ULL<<2) /* MC in progress  */
+
+#define GRUB_MSR_X86_MISC_ENABLE	0x000001a0
+#define GRUB_MSR_X86_ENABLE_MONITOR_FSM	(1<<18)
+
+#define GRUB_MSR_X86_MTRR_PHYSBASE0	0x00000200
+#define GRUB_MSR_X86_MTRR_PHYSMASK0	0x00000201
+#define GRUB_MSR_X86_BASE_DEF_TYPE_MASK	0xff
+#define GRUB_MSR_X86_MASK_VALID		(1<<11)
+
+#define GRUB_MSR_X86_MTRR_DEF_TYPE	0x000002ff
+#define GRUB_MSR_X86_DEF_TYPE_MASK	0xff
+#define GRUB_MSR_X86_MTRR_ENABLE_FIXED	(1<<10)
+#define GRUB_MSR_X86_MTRR_ENABLE	(1<<11)
+
+#define GRUB_MSR_X86_MC0_STATUS		0x00000401
+
+#define GRUB_MSR_X86_EFER		0xc0000080 /* Extended features  */
+#define GRUB_MSR_EFER_LME		(1<<8)     /* Enable Long Mode/IA-32e  */
+#define GRUB_MSR_EFER_LMA		(1<<10)    /* Long Mode/IA-32e Actuve  */
+#define GRUB_MSR_EFER_SVME		(1<<12)    /* Enable virtualization  */
+
+/* AMD Specific */
+#define GRUB_MSR_AMD64_PATCH_LEVEL	0x0000008b
+#define GRUB_MSR_AMD64_PATCH_CLEAR	0xc0010021 /* AMD-specific microcode patch clear  */
+#define GRUB_MSR_AMD64_VM_CR		0xc0010114
+#define GRUB_MSR_SVM_VM_CR_SVM_DISABLE	4
+
+/* MTRR Specific */
+#define GRUB_MTRR_MEMORY_TYPE_UC	0
+#define GRUB_MTRR_MEMORY_TYPE_WC	1
+#define GRUB_MTRR_MEMORY_TYPE_WT	4
+#define GRUB_MTRR_MEMORY_TYPE_WP	5
+#define GRUB_MTRR_MEMORY_TYPE_WB	6
+
+#ifndef ASM_FILE
+
 #include <grub/err.h>
 #include <grub/i386/cpuid.h>
 #include <grub/types.h>
@@ -71,4 +130,6 @@ grub_wrmsr (grub_uint32_t msr_id, grub_uint64_t msr_value)
   asm volatile ("wrmsr" : : "c" (msr_id), "a" (low), "d" (high));
 }
 
+#endif /* ASM_FILE */
+
 #endif /* GRUB_I386_MSR_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 14/18] i386/txt: Add Intel TXT definitions header file
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (12 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 13/18] i386/slaunch: Add basic platform support for secure launch Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 15/18] i386/txt: Add Intel TXT core implementation Daniel Kiper
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

From: Ross Philipson <ross.philipson@oracle.com>

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 include/grub/i386/txt.h | 690 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 690 insertions(+)
 create mode 100644 include/grub/i386/txt.h

diff --git a/include/grub/i386/txt.h b/include/grub/i386/txt.h
new file mode 100644
index 000000000..8280e461e
--- /dev/null
+++ b/include/grub/i386/txt.h
@@ -0,0 +1,690 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  Oracle and/or its affiliates.
+ *
+ *  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/>.
+ *
+ *  Intel TXT definitions header file.
+ */
+
+#ifndef GRUB_TXT_H
+#define GRUB_TXT_H 1
+
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/i386/memory.h>
+#include <grub/i386/mmio.h>
+#include <grub/i386/slaunch.h>
+
+/* Intel TXT Software Developers Guide */
+
+/* Chapter 2, Table 2 MLE/SINIT Capabilities Field Bit Definitions */
+
+#define GRUB_TXT_PCR_EXT_MAX_AGILITY_POLICY	0
+#define GRUB_TXT_PCR_EXT_MAX_PERF_POLICY	1
+
+#define GRUB_TXT_PLATFORM_TYPE_LEGACY		0
+#define GRUB_TXT_PLATFORM_TYPE_CLIENT		1
+#define GRUB_TXT_PLATFORM_TYPE_SERVER		2
+#define GRUB_TXT_PLATFORM_TYPE_RESERVED		3
+
+#define GRUB_TXT_CAPS_GETSEC_WAKE_SUPPORT	(1<<0)
+#define GRUB_TXT_CAPS_MONITOR_SUPPORT		(1<<1)
+#define GRUB_TXT_CAPS_ECX_PT_SUPPORT		(1<<2)
+#define GRUB_TXT_CAPS_STM_SUPPORT		(1<<3)
+#define GRUB_TXT_CAPS_TPM_12_NO_LEGACY_PCR_USAGE	(1<<4)
+#define GRUB_TXT_CAPS_TPM_12_AUTH_PCR_USAGE	(1<<5)
+#define GRUB_TXT_CAPS_PLATFORM_TYPE		(3<<6)
+#define GRUB_TXT_CAPS_MAXPHYSADDR_SUPPORT	(1<<8)
+#define GRUB_TXT_CAPS_TPM_20_EVTLOG_SUPPORT	(1<<9)
+#define GRUB_TXT_CAPS_CBNT_SUPPORT		(1<<10)
+/* Rest is reserved */
+
+/* Appendix A TXT Execution Technology Authenticated Code Modules */
+/* A.1 Authenticated Code Module Format */
+
+#define GRUB_TXT_ACM_MODULE_TYPE		2
+
+#define GRUB_TXT_ACM_MODULE_SUB_TYPE_TXT_ACM	0
+#define GRUB_TXT_ACM_MODULE_SUB_TYPE_S_ACM	1
+
+#define GRUB_TXT_ACM_HEADER_LEN_0_0		161
+#define GRUB_TXT_ACM_HEADER_LEN_3_0		224
+
+#define GRUB_TXT_ACM_HEADER_VERSION_0_0		0x0000
+#define GRUB_TXT_ACM_HEADER_VERSION_3_0		0x0300
+
+#define GRUB_TXT_ACM_FLAG_PREPRODUCTION		(1<<14)
+#define GRUB_TXT_ACM_FLAG_DEBUG_SIGNED		(1<<15)
+
+#define GRUB_TXT_ACM_MODULE_VENDOR_INTEL	0x00008086
+
+#define GRUB_TXT_MLE_MAX_SIZE			0x40000000
+
+#define GRUB_MLE_AP_WAKE_BLOCK_SIZE		GRUB_PAGE_SIZE
+
+struct grub_txt_acm_header
+{
+  grub_uint16_t module_type;
+  grub_uint16_t module_sub_type;
+  grub_uint32_t header_len;
+  grub_uint32_t header_version;
+  grub_uint16_t chipset_id;
+  grub_uint16_t flags;
+  grub_uint32_t module_vendor;
+  grub_uint32_t date; /* e.g 20131231H == December 31, 2013 */
+  grub_uint32_t size; /* multiples of 4 bytes */
+  grub_uint16_t txt_svn;
+  grub_uint16_t se_svn;
+  grub_uint32_t code_control;
+  grub_uint32_t error_entry_point;
+  grub_uint32_t gdt_limit;
+  grub_uint32_t gdt_base;
+  grub_uint32_t seg_sel;
+  grub_uint32_t entry_point;
+  grub_uint8_t reserved2[64];
+  grub_uint32_t key_size;
+  grub_uint32_t scratch_size;
+  /* RSA Pub Key and Signature */
+} GRUB_PACKED;
+
+#define GRUB_TXT_ACM_UUID "\xaa\x3a\xc0\x7f\xa7\x46\xdb\x18\x2e\xac\x69\x8f\x8d\x41\x7f\x5a"
+
+#define GRUB_TXT_ACM_CHIPSET_TYPE_BIOS		0
+#define GRUB_TXT_ACM_CHIPSET_TYPE_SINIT		1
+#define GRUB_TXT_ACM_CHIPSET_TYPE_BIOS_RACM	8
+#define GRUB_TXT_ACM_CHIPSET_TYPE_SINIT_RACM	9
+
+struct grub_txt_acm_info_table
+{
+  grub_uint8_t uuid[16];
+  grub_uint8_t chipset_acm_type;
+  grub_uint8_t version;
+  grub_uint16_t length;
+  grub_uint32_t chipset_id_list;
+  grub_uint32_t os_sinit_data_ver;
+  grub_uint32_t min_mle_header_ver;
+  grub_uint32_t capabilities;
+  grub_uint32_t acm_version_revision;
+  grub_uint32_t processor_id_list;
+  /* Version >= 5 */
+  grub_uint32_t tpm_info_list;
+} GRUB_PACKED;
+
+struct grub_txt_acm_chipset_id_list
+{
+  grub_uint32_t count;
+        /* Array of chipset ID structs */
+} GRUB_PACKED;
+
+#define GRUB_TXT_ACM_REVISION_ID_MASK	(1<<0)
+
+struct grub_txt_acm_chipset_id
+{
+  grub_uint32_t flags;
+  grub_uint16_t vendor_id;
+  grub_uint16_t device_id;
+  grub_uint16_t revision_id;
+  grub_uint16_t reserved;
+  grub_uint32_t extended_id;
+} GRUB_PACKED;
+
+struct grub_txt_acm_processor_id_list
+{
+  grub_uint32_t count;
+        /* Array of processor ID structs */
+} GRUB_PACKED;
+
+struct grub_txt_acm_processor_id
+{
+  grub_uint32_t fms;
+  grub_uint32_t fms_mask;
+  grub_uint64_t platform_id;
+  grub_uint64_t platform_mask;
+} GRUB_PACKED;
+
+#define GRUB_TXT_TPM_CAPS_EXTPOL_NONE		0 /* TPM 1.2 */
+#define GRUB_TXT_TPM_CAPS_EXTPOL_MA		1
+#define GRUB_TXT_TPM_CAPS_EXTPOL_MP		2
+#define GRUB_TXT_TPM_CAPS_EXTPOL_BOTH		3
+
+#define GRUB_TXT_TPM_CAPS_FAMILY_DISCRETE_12	1
+#define GRUB_TXT_TPM_CAPS_FAMILY_DISCRETE_20	2
+#define GRUB_TXT_TPM_CAPS_FAMILY_FIRMWARE_20	8
+
+#define GRUB_TXT_TPM_CAPS_INITIAL_NV_INDICES	0
+#define GRUB_TXT_TPM_CAPS_TCP_NV_INDICES	1
+
+struct grub_txt_acm_tpm_info
+{
+  grub_uint32_t capabilities;
+  grub_uint16_t count;
+  /* List of supported hash algorithm per TPM2 spec */
+} GRUB_PACKED;
+
+/* Appendix B SMX Interaction with Platform */
+/* B.1 Intel Trusted Execution Technology Configuration Registers */
+
+#ifdef __x86_64__
+#define GRUB_TXT_CFG_REGS_PUB	0xfed30000ULL
+#else
+#define GRUB_TXT_CFG_REGS_PUB	0xfed30000
+#endif
+
+#define GRUB_TXT_STS			0x0000
+#define GRUB_TXT_ESTS			0x0008
+#define GRUB_TXT_ERRORCODE		0x0030
+#define GRUB_TXT_CMD_RESET		0x0038
+#define GRUB_TXT_CMD_CLOSE_PRIVATE	0x0048
+#define GRUB_TXT_VER_FSBIF		0x0100
+#define GRUB_TXT_DIDVID			0x0110
+#define GRUB_TXT_VER_QPIIF		0x0200
+#define GRUB_TXT_CMD_UNLOCK_MEM_CONFIG	0x0218
+#define GRUB_TXT_SINIT_BASE		0x0270
+#define GRUB_TXT_SINIT_SIZE		0x0278
+#define GRUB_TXT_MLE_JOIN		0x0290
+#define GRUB_TXT_HEAP_BASE		0x0300
+#define GRUB_TXT_HEAP_SIZE		0x0308
+#define GRUB_TXT_MSEG_BASE		0x0310
+#define GRUB_TXT_MSEG_SIZE		0x0318
+#define GRUB_TXT_DPR			0x0330
+#define GRUB_TXT_CMD_OPEN_LOCALITY1	0x0380
+#define GRUB_TXT_CMD_CLOSE_LOCALITY1	0x0388
+#define GRUB_TXT_CMD_OPEN_LOCALITY2	0x0390
+#define GRUB_TXT_CMD_CLOSE_LOCALITY2	0x0398
+#define GRUB_TXT_PUBLIC_KEY		0x0400
+#define GRUB_TXT_CMD_SECRETS		0x08e0
+#define GRUB_TXT_CMD_NO_SECRETS		0x08e8
+#define GRUB_TXT_E2STS			0x08f0
+
+#define GRUB_TXT_STS_SENTER_DONE	(1 << 0)
+#define GRUB_TXT_STS_SEXIT_DONE		(1 << 1)
+#define GRUB_TXT_STS_MEM_CONFIG_LOCK	(1 << 6)
+#define GRUB_TXT_STS_PRIVATE_OPEN	(1 << 7)
+#define GRUB_TXT_STS_LOCALITY1_OPEN	(1 << 15)
+#define GRUB_TXT_STS_LOCALITY2_OPEN	(1 << 16)
+
+#define GRUB_TXT_ESTS_TXT_RESET		(1 << 0)
+
+#define GRUB_TXT_VER_FSBIF_DEBUG_FUSE	(1 << 31)
+
+#define GRUB_TXT_VER_QPIIF_DEBUG_FUSE	(1 << 31)
+
+#define GRUB_TXT_E2STS_SECRETS		(1 << 1)
+
+union grub_txt_didvid
+{
+  grub_uint64_t value;
+  struct
+  {
+    grub_uint16_t vid;
+    grub_uint16_t did;
+    grub_uint16_t rid;
+    grub_uint16_t id_ext;
+  };
+} GRUB_PACKED;
+
+#define GRUB_TXT_VERSION_DEBUG_FUSED	(1<<31)
+
+/* Appendix C Intel TXT Heap Memory */
+
+/* Ext Data Structs */
+
+struct grub_txt_heap_uuid
+{
+  grub_uint32_t data1;
+  grub_uint16_t data2;
+  grub_uint16_t data3;
+  grub_uint16_t data4;
+  grub_uint8_t data5[6];
+} GRUB_PACKED;
+
+struct grub_txt_heap_ext_data_element
+{
+  grub_uint32_t type;
+  grub_uint32_t size;
+  grub_uint8_t data[];
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_END			0
+
+struct grub_txt_heap_end_element
+{
+  grub_uint32_t type;
+  grub_uint32_t size;
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_BIOS_SPEC_VER	1
+
+struct grub_txt_heap_bios_spec_ver_element
+{
+  grub_uint16_t spec_ver_major;
+  grub_uint16_t spec_ver_minor;
+  grub_uint16_t spec_ver_revision;
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_ACM			2
+
+struct grub_txt_heap_acm_element
+{
+  grub_uint32_t num_acms;
+  /* Array of num_acms grub_uint64_t addresses */
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_STM			3
+
+struct grub_txt_heap_stm_element
+{
+  /* STM specific BIOS properties */
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_CUSTOM		4
+
+struct grub_txt_heap_custom_element
+{
+  struct grub_txt_heap_uuid uuid;
+  /* Vendor Data */
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR	5
+
+struct grub_txt_heap_tpm_event_log_element
+{
+  grub_uint32_t type;
+  grub_uint32_t size;
+  grub_uint64_t event_log_phys_addr;
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_MADT			6
+
+struct grub_txt_heap_madt_element
+{
+  /* Copy of ACPI MADT table */
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1	8
+
+struct grub_txt_heap_event_log_pointer2_1_element
+{
+  grub_uint32_t type;
+  grub_uint32_t size;
+  grub_uint64_t phys_addr;
+  grub_uint32_t allocated_event_container_size;
+  grub_uint32_t first_record_offset;
+  grub_uint32_t next_record_offset;
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_MCFG			9
+
+struct grub_txt_heap_mcfg_element
+{
+  /* Copy of ACPI MCFG table */
+} GRUB_PACKED;
+
+/* TXT Heap Tables */
+
+struct grub_txt_bios_data
+{
+  grub_uint32_t version; /* Currently 5 for TPM 1.2 and 6 for TPM 2.0 */
+  grub_uint32_t bios_sinit_size;
+  grub_uint64_t reserved1;
+  grub_uint64_t reserved22;
+  grub_uint32_t num_logical_procs;
+  /* Versions >= 5 with updates in version 6 */
+  grub_uint32_t sinit_flags;
+  grub_uint32_t mle_flags;
+  /* Versions >= 4 */
+  /* Ext Data Elements */
+} GRUB_PACKED;
+
+/* GRUB SLAUNCH specific definitions OS-MLE data */
+#define GRUB_SL_BOOTPARAMS_OFFSET	0x12c
+#define GRUB_SL_MAX_EVENT_LOG_SIZE	(5*4*1024)   /* 4k*5 */
+#define GRUB_SL_MAX_VARIABLE_MTRRS	32
+#define GRUB_SL_OS_MLE_STRUCT_VERSION	1
+
+struct grub_slaunch_mtrr_pair
+{
+  grub_uint64_t mtrr_physbase;
+  grub_uint64_t mtrr_physmask;
+} GRUB_PACKED;
+
+struct grub_slaunch_mtrr_state
+{
+  grub_uint64_t default_mem_type;
+  grub_uint64_t mtrr_vcnt;
+  struct grub_slaunch_mtrr_pair mtrr_pair[GRUB_SL_MAX_VARIABLE_MTRRS];
+} GRUB_PACKED;
+
+struct grub_txt_os_mle_data
+{
+  grub_uint32_t version;
+  grub_uint32_t zero_page_addr;
+  grub_uint8_t msb_key_hash[20];
+  grub_uint64_t saved_misc_enable_msr;
+  struct grub_slaunch_mtrr_state saved_bsp_mtrrs;
+  grub_uint64_t ap_wake_ebp;
+  grub_uint64_t ap_wake_block;
+  grub_uint8_t event_log_buffer[GRUB_SL_MAX_EVENT_LOG_SIZE];
+} GRUB_PACKED;
+
+struct grub_txt_os_sinit_data
+{
+  grub_uint32_t version; /* Currently 6 for TPM 1.2 and 7 for TPM 2.0 */
+  grub_uint32_t flags;
+  grub_uint64_t mle_ptab;
+  grub_uint64_t mle_size;
+  grub_uint64_t mle_hdr_base;
+  grub_uint64_t vtd_pmr_lo_base;
+  grub_uint64_t vtd_pmr_lo_size;
+  grub_uint64_t vtd_pmr_hi_base;
+  grub_uint64_t vtd_pmr_hi_size;
+  grub_uint64_t lcp_po_base;
+  grub_uint64_t lcp_po_size;
+  grub_uint32_t capabilities;
+  /* Version = 5 */
+  grub_uint64_t    efi_rsdt_ptr;
+  /* Versions >= 6 */
+  /* Ext Data Elements */
+  grub_uint8_t ext_data_elts[];
+} GRUB_PACKED;
+
+struct grub_txt_sinit_mle_data
+{
+  grub_uint32_t version;             /* Current values are 6 through 9 */
+  /* Versions <= 8 */
+  grub_uint8_t bios_acm_id[20];
+  grub_uint32_t edx_senter_flags;
+  grub_uint64_t mseg_valid;
+  grub_uint8_t sinit_hash[20];
+  grub_uint8_t mle_hash[20];
+  grub_uint8_t stm_hash[20];
+  grub_uint8_t lcp_policy_hash[20];
+  grub_uint32_t lcp_policy_control;
+  /* Versions >= 7 */
+  grub_uint32_t rlp_wakeup_addr;
+  grub_uint32_t reserved;
+  grub_uint32_t num_of_sinit_mdrs;
+  grub_uint32_t sinit_mdrs_table_offset;
+  grub_uint32_t sinit_vtd_dmar_table_size;
+  grub_uint32_t sinit_vtd_dmar_table_offset;
+  /* Versions >= 8 */
+  grub_uint32_t processor_scrtm_status;
+  /* Versions >= 9 */
+  /* Ext Data Elements */
+} GRUB_PACKED;
+
+struct grub_txt_sinit_memory_descriptor_records
+{
+  grub_uint64_t address;
+  grub_uint64_t length;
+  grub_uint8_t type;
+  grub_uint8_t reserved[7];
+} GRUB_PACKED;
+
+/* Section 2 Measured Launch Environment */
+/* 2.1 MLE Architecture Overview */
+/* Table 1. MLE Header structure */
+
+struct grub_txt_mle_header
+{
+  grub_uint8_t uuid[16];
+  grub_uint32_t header_len;
+  grub_uint32_t version;
+  grub_uint32_t entry_point;
+  grub_uint32_t first_valid_page;
+  grub_uint32_t mle_start;
+  grub_uint32_t mle_end;
+  grub_uint32_t capabilities;
+  grub_uint32_t cmdline_start;
+  grub_uint32_t cmdline_end;
+} GRUB_PACKED;
+
+struct grub_txt_heap_event_log_ptr_elt
+{
+  grub_uint64_t event_log_phys_addr;
+} GRUB_PACKED;
+
+struct grub_txt_heap_event_log_ptr_elt2_1
+{
+  grub_uint64_t phys_addr;
+  grub_uint32_t allcoated_event_container_size;
+  grub_uint32_t first_record_offset;
+  grub_uint32_t next_record_offset;
+} GRUB_PACKED;
+
+/* TXT register and heap access */
+
+static inline grub_uint64_t
+grub_txt_reg_pub_readq (grub_uint32_t reg)
+{
+  return grub_readq ((void *) (GRUB_TXT_CFG_REGS_PUB + reg));
+}
+
+static inline grub_uint8_t *
+grub_txt_get_heap (void)
+{
+  return (grub_uint8_t *)(grub_addr_t) grub_txt_reg_pub_readq (GRUB_TXT_HEAP_BASE);
+}
+
+static inline grub_uint64_t
+grub_txt_bios_data_size (grub_uint8_t *heap)
+{
+  return *(grub_uint64_t *)heap;
+}
+
+static inline struct grub_txt_bios_data*
+grub_txt_bios_data_start (grub_uint8_t *heap)
+{
+  return (struct grub_txt_bios_data*)(heap + sizeof (grub_uint64_t));
+}
+
+static inline grub_uint64_t
+grub_txt_os_mle_data_size (grub_uint8_t *heap)
+{
+  return *(grub_uint64_t *)(heap + grub_txt_bios_data_size (heap));
+}
+
+static inline struct grub_txt_os_mle_data*
+grub_txt_os_mle_data_start (grub_uint8_t *heap)
+{
+  return (struct grub_txt_os_mle_data*)(heap + grub_txt_bios_data_size (heap) +
+                                        sizeof (grub_uint64_t));
+}
+
+static inline grub_uint64_t
+grub_txt_os_sinit_data_size (grub_uint8_t *heap)
+{
+  return *(grub_uint64_t *)(heap + grub_txt_bios_data_size (heap) +
+                            grub_txt_os_mle_data_size (heap));
+}
+
+static inline struct grub_txt_os_sinit_data *
+grub_txt_os_sinit_data_start (grub_uint8_t *heap)
+{
+  return (struct grub_txt_os_sinit_data*)(heap +
+                 grub_txt_bios_data_size (heap) +
+                 grub_txt_os_mle_data_size (heap) + sizeof (grub_uint64_t));
+}
+
+static inline grub_uint64_t
+grub_txt_sinit_mle_data_size (grub_uint8_t *heap)
+{
+  return *(grub_uint64_t *)(heap + grub_txt_bios_data_size (heap) +
+                            grub_txt_os_mle_data_size (heap) +
+                            grub_txt_os_sinit_data_size (heap));
+}
+
+static inline struct grub_txt_sinit_mle_data*
+grub_txt_sinit_mle_data_start (grub_uint8_t *heap)
+{
+  return (struct grub_txt_sinit_mle_data*)(heap +
+                 grub_txt_bios_data_size (heap) +
+                 grub_txt_os_mle_data_size (heap) +
+                 grub_txt_os_sinit_data_size (heap) +
+                 sizeof (grub_uint64_t));
+}
+
+/* Intel 64 and IA-32 Architectures Software Developer’s Manual */
+/* Volume 2 (2A, 2B, 2C & 2D): Instruction Set Reference, A-Z */
+
+/* CHAPTER 6 SAFER MODE EXTENSIONS REFERENCE */
+
+#define GRUB_SMX_LEAF_CAPABILITIES	0
+#define GRUB_SMX_LEAF_UNDEFINED		1
+#define GRUB_SMX_LEAF_ENTERACCS		2
+#define GRUB_SMX_LEAF_EXITAC 		3
+#define GRUB_SMX_LEAF_SENTER		4
+#define GRUB_SMX_LEAF_SEXIT		5
+#define GRUB_SMX_LEAF_PARAMETERS	6
+#define GRUB_SMX_LEAF_SMCTRL		7
+#define GRUB_SMX_LEAF_WAKEUP		8
+
+#define GRUB_SMX_CAPABILITY_CHIPSET_PRESENT	(1<<0)
+#define GRUB_SMX_CAPABILITY_UNDEFINED		(1<<1)
+#define GRUB_SMX_CAPABILITY_ENTERACCS		(1<<2)
+#define GRUB_SMX_CAPABILITY_EXITAC		(1<<3)
+#define GRUB_SMX_CAPABILITY_SENTER		(1<<4)
+#define GRUB_SMX_CAPABILITY_SEXIT		(1<<5)
+#define GRUB_SMX_CAPABILITY_PARAMETERS		(1<<6)
+#define GRUB_SMX_CAPABILITY_SMCTRL		(1<<7)
+#define GRUB_SMX_CAPABILITY_WAKEUP		(1<<8)
+#define GRUB_SMX_CAPABILITY_EXTENDED_LEAFS	(1<<31)
+
+static inline grub_uint32_t
+grub_txt_getsec_capabilities (grub_uint32_t index)
+{
+  grub_uint32_t caps;
+
+  asm volatile (".byte 0x0f,0x37\n"
+                        : "=a" (caps)
+                        : "a" (GRUB_SMX_LEAF_CAPABILITIES), "b" (index));
+  return caps;
+}
+
+static inline void
+grub_txt_getsec_enteraccs (grub_uint32_t acm_phys_addr, grub_uint32_t acm_size)
+{
+  asm volatile (".byte 0x0f,0x37\n" :
+                        : "a" (GRUB_SMX_LEAF_ENTERACCS),
+                          "b" (acm_phys_addr), "c" (acm_size));
+}
+
+static inline void
+grub_txt_getsec_exitac (grub_uint32_t near_jump)
+{
+  asm volatile (".byte 0x0f,0x37\n" :
+                        : "a" (GRUB_SMX_LEAF_EXITAC), "b" (near_jump));
+}
+
+static inline void
+grub_txt_getsec_senter (grub_uint32_t acm_phys_addr, grub_uint32_t acm_size)
+{
+  asm volatile (".byte 0x0f,0x37\n" :
+                        : "a" (GRUB_SMX_LEAF_SENTER),
+                          "b" (acm_phys_addr), "c" (acm_size));
+}
+
+static inline void
+grub_txt_getsec_sexit (void)
+{
+  asm volatile (".byte 0x0f,0x37\n" : : "a" (GRUB_SMX_LEAF_SEXIT));
+}
+
+#define GRUB_SMX_PARAMETER_TYPE_MASK		0x1f
+#define GRUB_SMX_PARAMETER_NULL			0
+#define GRUB_SMX_PARAMETER_ACM_VERSIONS		1
+#define GRUB_SMX_PARAMETER_MAX_ACM_SIZE		2
+#define GRUB_SMX_PARAMETER_ACM_MEMORY_TYPES	3
+#define GRUB_SMX_PARAMETER_SENTER_CONTROLS	4
+#define GRUB_SMX_PARAMETER_TXT_EXTENSIONS	5
+
+
+#define GRUB_SMX_PARAMETER_MAX_VERSIONS	0x20
+
+#define GRUB_SMX_GET_MAX_ACM_SIZE(v)	((v & ~GRUB_SMX_PARAMETER_TYPE_MASK)*0x20)
+
+#define GRUB_SMX_ACM_MEMORY_TYPE_UC	0x00000100
+#define GRUB_SMX_ACM_MEMORY_TYPE_WC	0x00000200
+#define GRUB_SMX_ACM_MEMORY_TYPE_WT	0x00001000
+#define GRUB_SMX_ACM_MEMORY_TYPE_WP	0x00002000
+#define GRUB_SMX_ACM_MEMORY_TYPE_WB	0x00004000
+
+#define GRUB_SMX_GET_ACM_MEMORY_TYPES(v) (v & ~GRUB_SMX_PARAMETER_TYPE_MASK)
+
+#define GRUB_SMX_GET_SENTER_CONTROLS(v)	((v & 0x7f00) >> 8)
+
+#define GRUB_SMX_PROCESSOR_BASE_SCRTM	0x00000020
+#define GRUB_SMX_MACHINE_CHECK_HANLDING	0x00000040
+#define GRUB_SMX_GET_TXT_EXT_FEATURES(v) (v & (GRUB_SMX_PROCESSOR_BASE_SCRTM|GRUB_SMX_MACHINE_CHECK_HANLDING))
+
+#define GRUB_SMX_DEFAULT_VERSION	0x0
+#define GRUB_SMX_DEFAULT_VERSION_MASK	0xffffffff
+#define GRUB_SMX_DEFAULT_MAX_ACM_SIZE	0x8000 /* 32K */
+#define GRUB_SMX_DEFAULT_ACM_MEMORY_TYPE GRUB_SMX_ACM_MEMORY_TYPE_UC
+#define GRUB_SMX_DEFAULT_SENTER_CONTROLS 0x0
+
+#define GRUB_TXT_PMR_ALIGN_SHIFT	21
+#define GRUB_TXT_PMR_ALIGN		(1 << GRUB_TXT_PMR_ALIGN_SHIFT)
+
+struct grub_smx_supported_versions
+{
+  grub_uint32_t mask;
+  grub_uint32_t version;
+} GRUB_PACKED;
+
+struct grub_smx_parameters
+{
+  struct grub_smx_supported_versions versions[GRUB_SMX_PARAMETER_MAX_VERSIONS];
+  grub_uint32_t version_count;
+  grub_uint32_t max_acm_size;
+  grub_uint32_t acm_memory_types;
+  grub_uint32_t senter_controls;
+  grub_uint32_t txt_feature_ext_flags;
+} GRUB_PACKED;
+
+static inline void
+grub_txt_getsec_parameters (grub_uint32_t index, grub_uint32_t *eax_out,
+                            grub_uint32_t *ebx_out, grub_uint32_t *ecx_out)
+{
+  if (!eax_out || !ebx_out || !ecx_out)
+    return;
+
+  asm volatile (".byte 0x0f,0x37\n"
+                        : "=a" (*eax_out), "=b" (*ebx_out), "=c" (*ecx_out)
+                        : "0" (GRUB_SMX_LEAF_PARAMETERS), "1" (index));
+}
+
+extern grub_uint32_t grub_txt_supported_os_sinit_data_ver (struct grub_txt_acm_header* hdr);
+
+extern grub_uint32_t grub_txt_get_sinit_capabilities (struct grub_txt_acm_header* hdr);
+
+extern int grub_txt_is_sinit_acmod (const void *acmod_base, grub_uint32_t acmod_size);
+
+extern int grub_txt_acmod_match_platform (struct grub_txt_acm_header *hdr);
+
+extern struct grub_txt_acm_header* grub_txt_sinit_select (struct grub_txt_acm_header *sinit);
+
+extern grub_err_t grub_txt_verify_platform (void);
+extern grub_err_t grub_txt_prepare_cpu (void);
+
+extern grub_uint32_t grub_txt_get_mle_ptab_size (grub_uint32_t mle_size);
+extern void grub_txt_setup_mle_ptab (struct grub_slaunch_params *slparams);
+
+extern grub_err_t grub_txt_init (void);
+extern void grub_txt_shutdown (void);
+extern void grub_txt_state_show (void);
+extern grub_err_t grub_txt_boot_prepare (struct grub_slaunch_params *slparams);
+
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 15/18] i386/txt: Add Intel TXT core implementation
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (13 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 14/18] i386/txt: Add Intel TXT definitions header file Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-22 13:24   ` Krystian Hebel
  2020-05-04 23:21 ` [GRUB PATCH RFC 16/18] i386/txt: Add Intel TXT ACM module support Daniel Kiper
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

From: Ross Philipson <ross.philipson@oracle.com>

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/loader/i386/txt/txt.c | 887 ++++++++++++++++++++++++++++++++++++++++
 include/grub/i386/memory.h      |   5 +
 2 files changed, 892 insertions(+)
 create mode 100644 grub-core/loader/i386/txt/txt.c

diff --git a/grub-core/loader/i386/txt/txt.c b/grub-core/loader/i386/txt/txt.c
new file mode 100644
index 000000000..3e25890c3
--- /dev/null
+++ b/grub-core/loader/i386/txt/txt.c
@@ -0,0 +1,887 @@
+/*
+ * txt.c: Intel(r) TXT support functions, including initiating measured
+ *        launch, post-launch, AP wakeup, etc.
+ *
+ * Copyright (c) 2003-2011, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of the Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  Oracle and/or its affiliates.
+ *
+ *  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/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/memory.h>
+#include <grub/normal.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/acpi.h>
+#include <grub/cpu/relocator.h>
+#include <grub/i386/cpuid.h>
+#include <grub/i386/msr.h>
+#include <grub/i386/crfr.h>
+#include <grub/i386/txt.h>
+#include <grub/i386/linux.h>
+#include <grub/i386/memory.h>
+#include <grub/i386/slaunch.h>
+#include <grub/i386/tpm.h>
+
+#define OS_SINIT_DATA_TPM_12_VER	6
+#define OS_SINIT_DATA_TPM_20_VER	7
+
+#define OS_SINIT_DATA_MIN_VER		OS_SINIT_DATA_TPM_12_VER
+
+static grub_err_t
+enable_smx_mode (void)
+{
+  grub_uint32_t caps;
+
+  /* Enable SMX mode. */
+  grub_write_cr4 (grub_read_cr4 () | GRUB_CR4_X86_SMXE);
+
+  caps = grub_txt_getsec_capabilities (0);
+
+  if (!(caps & GRUB_SMX_CAPABILITY_CHIPSET_PRESENT))
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, N_("TXT-capable chipset is not present"));
+      goto fail;
+    }
+
+  if (!(caps & GRUB_SMX_CAPABILITY_SENTER))
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, N_("GETSEC[SENTER] is not available"));
+      goto fail;
+    }
+
+  if (!(caps & GRUB_SMX_CAPABILITY_PARAMETERS))
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, N_("GETSEC[PARAMETERS] is not available"));
+      goto fail;
+    }
+
+  return GRUB_ERR_NONE;
+
+ fail:
+  /* Disable SMX mode on failure. */
+  grub_write_cr4 (grub_read_cr4 () & ~GRUB_CR4_X86_SMXE);
+
+  return grub_errno;
+}
+
+static void
+grub_txt_smx_parameters (struct grub_smx_parameters *params)
+{
+  grub_uint32_t index = 0, eax, ebx, ecx, param_type;
+
+  grub_memset (params, 0, sizeof(struct grub_smx_supported_versions));
+
+  params->max_acm_size = GRUB_SMX_DEFAULT_MAX_ACM_SIZE;
+  params->acm_memory_types = GRUB_SMX_DEFAULT_ACM_MEMORY_TYPE;
+  params->senter_controls = GRUB_SMX_DEFAULT_SENTER_CONTROLS;
+
+  do
+    {
+      grub_txt_getsec_parameters (index, &eax, &ebx, &ecx);
+      param_type = eax & GRUB_SMX_PARAMETER_TYPE_MASK;
+
+      switch (param_type)
+        {
+        case GRUB_SMX_PARAMETER_NULL:
+          break; /* This means done. */
+
+        case GRUB_SMX_PARAMETER_ACM_VERSIONS:
+          if (params->version_count == GRUB_SMX_PARAMETER_MAX_VERSIONS)
+            {
+	      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("Too many ACM versions"));
+	      break;
+            }
+          params->versions[params->version_count].mask = ebx;
+          params->versions[params->version_count++].version = ecx;
+          break;
+
+      case GRUB_SMX_PARAMETER_MAX_ACM_SIZE:
+        params->max_acm_size = GRUB_SMX_GET_MAX_ACM_SIZE (eax);
+        break;
+
+      case GRUB_SMX_PARAMETER_ACM_MEMORY_TYPES:
+        params->acm_memory_types = GRUB_SMX_GET_ACM_MEMORY_TYPES (eax);
+        break;
+
+      case GRUB_SMX_PARAMETER_SENTER_CONTROLS:
+        params->senter_controls = GRUB_SMX_GET_SENTER_CONTROLS (eax);
+        break;
+
+      case GRUB_SMX_PARAMETER_TXT_EXTENSIONS:
+        params->txt_feature_ext_flags = GRUB_SMX_GET_TXT_EXT_FEATURES (eax);
+        break;
+
+      default:
+	grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Unknown SMX parameter"));
+	param_type = GRUB_SMX_PARAMETER_NULL;
+    }
+
+    ++index;
+
+  } while (param_type != GRUB_SMX_PARAMETER_NULL);
+
+  /* If no ACM versions were found, set the default one. */
+  if (!params->version_count)
+    {
+      params->versions[0].mask = GRUB_SMX_DEFAULT_VERSION_MASK;
+      params->versions[0].version = GRUB_SMX_DEFAULT_VERSION;
+      params->version_count++;
+    }
+}
+
+grub_err_t
+grub_txt_prepare_cpu (void)
+{
+  struct grub_smx_parameters params;
+  grub_uint32_t i;
+  grub_uint64_t mcg_cap, mcg_stat;
+  unsigned long cr0;
+
+  cr0 = grub_read_control_register (GRUB_CR0);
+
+  /* Cache must be enabled (CR0.CD = CR0.NW = 0). */
+  cr0 &= ~(GRUB_CR0_X86_CD | GRUB_CR0_X86_NW);
+
+  /* Native FPU error reporting must be enabled for proper interaction behavior. */
+  cr0 |= GRUB_CR0_X86_NE;
+
+  grub_write_control_register (GRUB_CR0, cr0);
+
+  /* Disable virtual-8086 mode (EFLAGS.VM = 0). */
+  grub_write_flags_register (grub_read_flags_register () & ~GRUB_EFLAGS_X86_VM);
+
+  /*
+   * Verify all machine check status registers are clear (unless
+   * support preserving them).
+   */
+
+  /* Is machine check in progress? */
+  if ( grub_rdmsr (GRUB_MSR_X86_MCG_STATUS) & GRUB_MSR_MCG_STATUS_MCIP )
+    return grub_error (GRUB_ERR_BAD_DEVICE,
+		       N_("machine check in progress during secure launch"));
+
+  grub_txt_smx_parameters (&params);
+
+  if (params.txt_feature_ext_flags & GRUB_SMX_PROCESSOR_BASE_SCRTM)
+    grub_dprintf ("slaunch", "CPU supports processor-based S-CRTM\n");
+
+  if (params.txt_feature_ext_flags & GRUB_SMX_MACHINE_CHECK_HANLDING)
+    grub_dprintf ("slaunch", "CPU supports preserving machine check errors\n");
+  else
+    {
+      grub_dprintf ("slaunch", "CPU does not support preserving machine check errors\n");
+
+      /* Check if all machine check registers are clear. */
+      mcg_cap = grub_rdmsr (GRUB_MSR_X86_MCG_CAP);
+      for (i = 0; i < (mcg_cap & GRUB_MSR_MCG_BANKCNT_MASK); ++i)
+	{
+	  mcg_stat = grub_rdmsr (GRUB_MSR_X86_MC0_STATUS + i * 4);
+	  if (mcg_stat & (1ULL << 63))
+	    return grub_error (GRUB_ERR_BAD_DEVICE,
+			       N_("secure launch MCG[%u] = %Lx ERROR"), i, mcg_stat);
+        }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+save_mtrrs (struct grub_txt_os_mle_data *os_mle_data)
+{
+  grub_uint64_t i;
+
+  os_mle_data->saved_bsp_mtrrs.default_mem_type =
+    grub_rdmsr (GRUB_MSR_X86_MTRR_DEF_TYPE);
+
+  os_mle_data->saved_bsp_mtrrs.mtrr_vcnt =
+    grub_rdmsr (GRUB_MSR_X86_MTRRCAP) & GRUB_MSR_X86_VCNT_MASK;
+
+  if (os_mle_data->saved_bsp_mtrrs.mtrr_vcnt > GRUB_SL_MAX_VARIABLE_MTRRS)
+    {
+      /* Print warning but continue saving what we can... */
+      grub_printf ("WARNING: Actual number of variable MTRRs (%" PRIuGRUB_UINT64_T
+		   ") > GRUB_SL_MAX_VARIABLE_MTRRS (%d)\n",
+		   os_mle_data->saved_bsp_mtrrs.mtrr_vcnt,
+		   GRUB_SL_MAX_VARIABLE_MTRRS);
+      os_mle_data->saved_bsp_mtrrs.mtrr_vcnt = GRUB_SL_MAX_VARIABLE_MTRRS;
+    }
+
+  for (i = 0; i < os_mle_data->saved_bsp_mtrrs.mtrr_vcnt; ++i)
+    {
+      os_mle_data->saved_bsp_mtrrs.mtrr_pair[i].mtrr_physmask =
+        grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSMASK0 + i * 2);
+      os_mle_data->saved_bsp_mtrrs.mtrr_pair[i].mtrr_physbase =
+        grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSBASE0 + i * 2);
+    }
+}
+
+static void
+set_all_mtrrs (int enable)
+{
+  grub_uint64_t mtrr_def_type;
+
+  mtrr_def_type = grub_rdmsr (GRUB_MSR_X86_MTRR_DEF_TYPE);
+
+  if ( enable )
+    mtrr_def_type |= GRUB_MSR_X86_MTRR_ENABLE;
+  else
+    mtrr_def_type &= ~GRUB_MSR_X86_MTRR_ENABLE;
+
+  grub_wrmsr (GRUB_MSR_X86_MTRR_DEF_TYPE, mtrr_def_type);
+}
+
+#define SINIT_MTRR_MASK         0xFFFFFF  /* SINIT requires 36b mask */
+
+union mtrr_physbase_t
+{
+  grub_uint64_t raw;
+  struct
+  {
+    grub_uint64_t type      : 8;
+    grub_uint64_t reserved1 : 4;
+    grub_uint64_t base      : 52; /* Define as max width and mask w/ */
+                                  /* MAXPHYADDR when using */
+  };
+} GRUB_PACKED;
+
+union mtrr_physmask_t
+{
+  grub_uint64_t raw;
+  struct
+  {
+    grub_uint64_t reserved1 : 11;
+    grub_uint64_t v         : 1;      /* valid */
+    grub_uint64_t mask      : 52;     /* define as max width and mask w/ */
+                                      /* MAXPHYADDR when using */
+  };
+} GRUB_PACKED;
+
+static inline grub_uint32_t
+bsrl (grub_uint32_t mask)
+{
+  grub_uint32_t result;
+
+  asm ("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc");
+
+  return result;
+}
+
+static inline int
+fls (int mask)
+{
+  return (mask == 0 ? mask : (int)bsrl ((grub_uint32_t)mask) + 1);
+}
+
+/*
+ * set the memory type for specified range (base to base+size)
+ * to mem_type and everything else to UC
+ */
+static grub_err_t
+set_mtrr_mem_type (const grub_uint8_t *base, grub_uint32_t size,
+                   grub_uint32_t mem_type)
+{
+  grub_uint64_t mtrr_def_type;
+  grub_uint64_t mtrr_cap;
+  union mtrr_physbase_t mtrr_physbase;
+  union mtrr_physmask_t mtrr_physmask;
+  grub_uint32_t vcnt, pages_in_range;
+  unsigned long ndx, base_v;
+  int i = 0, j, num_pages, mtrr_s;
+
+  /* Disable all fixed MTRRs, set default type to UC */
+  mtrr_def_type = grub_rdmsr (GRUB_MSR_X86_MTRR_DEF_TYPE);
+  mtrr_def_type &= ~(GRUB_MSR_X86_MTRR_ENABLE_FIXED | GRUB_MSR_X86_DEF_TYPE_MASK);
+  mtrr_def_type |= GRUB_MTRR_MEMORY_TYPE_UC;
+  grub_wrmsr (GRUB_MSR_X86_MTRR_DEF_TYPE, mtrr_def_type);
+
+  /* Initially disable all variable MTRRs (we'll enable the ones we use) */
+  mtrr_cap = grub_rdmsr (GRUB_MSR_X86_MTRRCAP);
+  vcnt = (mtrr_cap & GRUB_MSR_X86_VCNT_MASK);
+
+  for ( ndx = 0; ndx < vcnt; ndx++ )
+    {
+      mtrr_physmask.raw = grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSMASK0 + ndx*2);
+      mtrr_physmask.v = 0;
+      grub_wrmsr (GRUB_MSR_X86_MTRR_PHYSMASK0 + ndx*2, mtrr_physmask.raw);
+    }
+
+  /* Map all AC module pages as mem_type */
+  num_pages = GRUB_PAGE_UP(size) >> GRUB_PAGE_SHIFT;
+
+  grub_dprintf ("slaunch", "setting MTRRs for acmod: base=%p, size=%x, num_pages=%d\n",
+           base, size, num_pages);
+
+  /* Each VAR MTRR base must be a multiple if that MTRR's Size */
+  base_v = (unsigned long)base;
+  /* MTRR size in pages */
+  mtrr_s = 1;
+
+  while ( (base_v & 0x01) == 0 )
+    {
+      i++;
+      base_v = base_v >> 1;
+    }
+
+  for (j = i - 12; j > 0; j--)
+     mtrr_s = mtrr_s*2; /* mtrr_s = mtrr_s << 1 */
+
+  grub_dprintf ("slaunch", "The maximum allowed MTRR range size=%d Pages \n", mtrr_s);
+
+  ndx = 0;
+
+  while ( num_pages >= mtrr_s )
+    {
+      mtrr_physbase.raw = grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSBASE0 + ndx*2);
+      mtrr_physbase.base = ((unsigned long)base >> GRUB_PAGE_SHIFT) &
+	                     SINIT_MTRR_MASK;
+      mtrr_physbase.type = mem_type;
+      grub_wrmsr (GRUB_MSR_X86_MTRR_PHYSBASE0 + ndx*2, mtrr_physbase.raw);
+
+      mtrr_physmask.raw = grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSMASK0 + ndx*2);
+      mtrr_physmask.mask = ~(mtrr_s - 1) & SINIT_MTRR_MASK;
+      mtrr_physmask.v = 1;
+      grub_wrmsr (GRUB_MSR_X86_MTRR_PHYSMASK0 + ndx*2, mtrr_physmask.raw);
+
+      base += (mtrr_s * GRUB_PAGE_SIZE);
+      num_pages -= mtrr_s;
+      ndx++;
+      if ( ndx == vcnt )
+          return grub_error (GRUB_ERR_BAD_DEVICE,
+			     N_("exceeded number of var MTRRs when mapping range"));
+    }
+
+  ndx = 0;
+
+  while ( num_pages > 0 )
+    {
+      /* Set the base of the current MTRR */
+      mtrr_physbase.raw = grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSBASE0 + ndx*2);
+      mtrr_physbase.base = ((unsigned long)base >> GRUB_PAGE_SHIFT) &
+                            SINIT_MTRR_MASK;
+      mtrr_physbase.type = mem_type;
+      grub_wrmsr (GRUB_MSR_X86_MTRR_PHYSBASE0 + ndx*2, mtrr_physbase.raw);
+
+      /*
+       * Calculate MTRR mask
+       * MTRRs can map pages in power of 2
+       * may need to use multiple MTRRS to map all of region
+       */
+      pages_in_range = 1 << (fls (num_pages) - 1);
+
+      mtrr_physmask.raw = grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSMASK0 + ndx*2);
+      mtrr_physmask.mask = ~(pages_in_range - 1) & SINIT_MTRR_MASK;
+      mtrr_physmask.v = 1;
+      grub_wrmsr (GRUB_MSR_X86_MTRR_PHYSMASK0 + ndx*2, mtrr_physmask.raw);
+
+      /*
+       * Prepare for the next loop depending on number of pages
+       * We figure out from the above how many pages could be used in this
+       * mtrr. Then we decrement the count, increment the base,
+       * increment the mtrr we are dealing with, and if num_pages is
+       * still not zero, we do it again.
+       */
+      base += (pages_in_range * GRUB_PAGE_SIZE);
+      num_pages -= pages_in_range;
+      ndx++;
+      if ( ndx == vcnt )
+          return grub_error (GRUB_ERR_BAD_DEVICE,
+			     N_("exceeded number of var MTRRs when mapping range"));
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+/*
+ * this must be done for each processor so that all have the same
+ * memory types
+ */
+static grub_err_t
+set_mtrrs_for_acmod (struct grub_txt_acm_header *hdr)
+{
+  unsigned long eflags;
+  unsigned long cr0, cr4;
+  grub_err_t err;
+
+  /*
+   * need to do some things before we start changing MTRRs
+   *
+   * since this will modify some of the MTRRs, they should be saved first
+   * so that they can be restored once the AC mod is done
+   */
+
+  /* Disable interrupts */
+  eflags = grub_read_flags_register ();
+  grub_write_flags_register (eflags & ~GRUB_EFLAGS_X86_IF);
+
+  /* Save CR0 then disable cache (CRO.CD=1, CR0.NW=0) */
+  cr0 = grub_read_control_register (GRUB_CR0);
+  grub_write_control_register (GRUB_CR0,
+                               (cr0 & ~GRUB_CR0_X86_NW) | GRUB_CR0_X86_CD);
+
+  /* Flush caches */
+  asm volatile ("wbinvd");
+
+  /* Save CR4 and disable global pages (CR4.PGE=0) */
+  cr4 = grub_read_control_register (GRUB_CR4);
+  grub_write_control_register (GRUB_CR4, cr4 & ~GRUB_CR4_X86_PGE);
+
+  /* Disable MTRRs */
+  set_all_mtrrs (0);
+
+  /* Set MTRRs for AC mod and rest of memory */
+  err = set_mtrr_mem_type ((grub_uint8_t*)hdr, hdr->size*4,
+                           GRUB_MTRR_MEMORY_TYPE_WB);
+  if ( err )
+    return err;
+
+  /* Undo some of earlier changes and enable our new settings */
+
+  /* Flush caches */
+  asm volatile ("wbinvd");
+
+  /* Enable MTRRs */
+  set_all_mtrrs (1);
+
+  /* Restore CR0 (cacheing) */
+  grub_write_control_register (GRUB_CR0, cr0);
+
+  /* Restore CR4 (global pages) */
+  grub_write_control_register (GRUB_CR4, cr4);
+
+  /* Restore flags */
+  grub_write_flags_register (eflags);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header *sinit)
+{
+  grub_uint8_t *txt_heap;
+  grub_uint32_t os_sinit_data_ver, sinit_caps;
+  grub_uint64_t *size;
+  struct grub_txt_os_mle_data *os_mle_data;
+  struct grub_txt_os_sinit_data *os_sinit_data;
+  struct grub_txt_heap_end_element *heap_end_element;
+  struct grub_txt_heap_event_log_pointer2_1_element *heap_event_log_pointer2_1_element;
+#ifdef GRUB_MACHINE_EFI
+  struct grub_acpi_rsdp_v20 *rsdp;
+#endif
+
+  /* BIOS data already verified in grub_txt_verify_platform(). */
+
+  txt_heap = grub_txt_get_heap ();
+
+  /* OS/loader to MLE data. */
+
+  os_mle_data = grub_txt_os_mle_data_start (txt_heap);
+  size = (grub_uint64_t *) ((grub_addr_t) os_mle_data - sizeof (grub_uint64_t));
+  *size = sizeof (*os_mle_data) + sizeof (grub_uint64_t);
+
+  grub_memset (os_mle_data, 0, sizeof (*os_mle_data));
+
+  os_mle_data->version = GRUB_SL_OS_MLE_STRUCT_VERSION;
+  os_mle_data->zero_page_addr = (grub_uint32_t)(grub_addr_t) slparams->params;
+  os_mle_data->saved_misc_enable_msr = grub_rdmsr (GRUB_MSR_X86_MISC_ENABLE);
+
+  os_mle_data->ap_wake_block = slparams->ap_wake_block;
+
+  save_mtrrs (os_mle_data);
+
+  /* OS/loader to SINIT data. */
+
+  os_sinit_data_ver = grub_txt_supported_os_sinit_data_ver (sinit);
+
+  if (os_sinit_data_ver < OS_SINIT_DATA_MIN_VER)
+    return grub_error (GRUB_ERR_BAD_DEVICE,
+		       N_("unsupported OS to SINIT data version in SINIT ACM: %d"
+		       " expected >= %d"), os_sinit_data_ver, OS_SINIT_DATA_MIN_VER);
+
+  os_sinit_data = grub_txt_os_sinit_data_start (txt_heap);
+  size = (grub_uint64_t *) ((grub_addr_t) os_sinit_data - sizeof (grub_uint64_t));
+
+  *size = sizeof(grub_uint64_t) + sizeof (struct grub_txt_os_sinit_data) +
+	  sizeof (struct grub_txt_heap_end_element);
+
+  if (grub_get_tpm_ver () == GRUB_TPM_12)
+    *size += sizeof (struct grub_txt_heap_tpm_event_log_element);
+  else if (grub_get_tpm_ver () == GRUB_TPM_20)
+    *size += sizeof (struct grub_txt_heap_event_log_pointer2_1_element);
+  else
+    return grub_error (GRUB_ERR_BAD_DEVICE, N_("unsupported TPM version"));
+
+  grub_memset (os_sinit_data, 0, *size);
+
+#ifdef GRUB_MACHINE_EFI
+  rsdp = grub_acpi_get_rsdpv2 ();
+
+  if (rsdp == NULL)
+    return grub_printf ("WARNING: ACPI RSDP 2.0 missing\n");
+
+  os_sinit_data->efi_rsdt_ptr = (grub_uint64_t)(grub_addr_t) rsdp;
+#endif
+
+  os_sinit_data->mle_ptab = slparams->mle_ptab_target;
+  os_sinit_data->mle_size = slparams->mle_size;
+
+  os_sinit_data->mle_hdr_base = slparams->mle_header_offset;
+
+  /* TODO: Check low PMR with RMRR. Look at relevant tboot code too. */
+  /* TODO: Kernel should not allocate any memory outside of PMRs regions!!! */
+  os_sinit_data->vtd_pmr_lo_base = 0;
+  os_sinit_data->vtd_pmr_lo_size = ALIGN_DOWN (grub_mmap_get_highest (0x100000000),
+					       GRUB_TXT_PMR_ALIGN);
+
+  os_sinit_data->vtd_pmr_hi_base = ALIGN_UP (grub_mmap_get_lowest (0x100000000),
+					     GRUB_TXT_PMR_ALIGN);
+  os_sinit_data->vtd_pmr_hi_size = ALIGN_DOWN (grub_mmap_get_highest (0xffffffffffffffff),
+					       GRUB_TXT_PMR_ALIGN);
+  os_sinit_data->vtd_pmr_hi_size -= os_sinit_data->vtd_pmr_hi_base;
+
+  grub_dprintf ("slaunch",
+		"vtd_pmr_lo_base: 0x%" PRIxGRUB_UINT64_T " vtd_pmr_lo_size: 0x%"
+		PRIxGRUB_UINT64_T " vtd_pmr_hi_base: 0x%" PRIxGRUB_UINT64_T
+		" vtd_pmr_hi_size: 0x%" PRIxGRUB_UINT64_T "\n",
+		os_sinit_data->vtd_pmr_lo_base, os_sinit_data->vtd_pmr_lo_size,
+		os_sinit_data->vtd_pmr_hi_base, os_sinit_data->vtd_pmr_hi_size);
+
+  sinit_caps = grub_txt_get_sinit_capabilities (sinit);
+
+  /* CBnT bits 5:4 must be 11b, since D/A mapping is the only one supported. */
+  os_sinit_data->capabilities = GRUB_TXT_CAPS_TPM_12_NO_LEGACY_PCR_USAGE |
+				GRUB_TXT_CAPS_TPM_12_AUTH_PCR_USAGE;
+
+  /* Choose monitor RLP wakeup mechanism first. */
+  if (sinit_caps & GRUB_TXT_CAPS_MONITOR_SUPPORT)
+    os_sinit_data->capabilities |= GRUB_TXT_CAPS_MONITOR_SUPPORT;
+  else if (sinit_caps & GRUB_TXT_CAPS_GETSEC_WAKE_SUPPORT)
+    os_sinit_data->capabilities |= GRUB_TXT_CAPS_GETSEC_WAKE_SUPPORT;
+  else
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("lack of RLP wakeup mechanism"));
+
+  if (sinit_caps & GRUB_TXT_CAPS_ECX_PT_SUPPORT)
+    os_sinit_data->capabilities |= GRUB_TXT_CAPS_ECX_PT_SUPPORT;
+
+  if (grub_get_tpm_ver () == GRUB_TPM_12)
+    return grub_error (GRUB_ERR_BAD_DEVICE, N_("TPM 1.2 is not supported"));
+  else
+    {
+      if (!(sinit_caps & GRUB_TXT_CAPS_TPM_20_EVTLOG_SUPPORT))
+	return grub_error (GRUB_ERR_BAD_ARGUMENT,
+			   N_("original TXT TPM 2.0 event log format is not supported"));
+
+      os_sinit_data->capabilities |= GRUB_TXT_CAPS_TPM_20_EVTLOG_SUPPORT;
+
+      os_sinit_data->flags = GRUB_TXT_PCR_EXT_MAX_PERF_POLICY;
+
+      os_sinit_data->version = OS_SINIT_DATA_TPM_20_VER;
+
+      heap_event_log_pointer2_1_element =
+	(struct grub_txt_heap_event_log_pointer2_1_element *) os_sinit_data->ext_data_elts;
+      heap_event_log_pointer2_1_element->type = GRUB_TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1;
+      heap_event_log_pointer2_1_element->size = sizeof (*heap_event_log_pointer2_1_element);
+      heap_event_log_pointer2_1_element->phys_addr = slparams->tpm_evt_log_base;
+      heap_event_log_pointer2_1_element->allocated_event_container_size = slparams->tpm_evt_log_size;
+
+      heap_end_element = (struct grub_txt_heap_end_element *)
+	((grub_addr_t) heap_event_log_pointer2_1_element + heap_event_log_pointer2_1_element->size);
+      heap_end_element->type = GRUB_TXT_HEAP_EXTDATA_TYPE_END;
+      heap_end_element->size = sizeof (*heap_end_element);
+    }
+
+  /*
+   * TODO: TXT spec: Note: BiosDataSize + OsMleDataSize + OsSinitDataSize + SinitMleDataSize
+   * must be less than or equal to TXT.HEAP.SIZE, TXT spec, p. 102.
+   */
+
+  return GRUB_ERR_NONE;
+}
+
+/*
+ * TODO: Why 1 GiB limit? It does not seem that it is required by TXT spec.
+ * If there is a limit then it should be checked before allocation and image load.
+ *
+ * If enough room is available in front of the MLE, the maximum size of an
+ * MLE that can be covered is 1G. This is due to having 512 PDEs pointing
+ * to 512 page tables with 512 PTEs each.
+ */
+grub_uint32_t
+grub_txt_get_mle_ptab_size (grub_uint32_t mle_size)
+{
+  /*
+   * #PT + 1 PT + #PD + 1 PD + 1 PDT
+   *
+   * Why do we need 2 extra PTEs and PDEs? Yes, because MLE image may not
+   * start and end at PTE (page) and PDE (2 MiB) boundary...
+   */
+  return ((((mle_size / GRUB_PAGE_SIZE) + 2) / 512) + 1 +
+	  (((mle_size / (512 * GRUB_PAGE_SIZE)) + 2) / 512) + 1 + 1) * GRUB_PAGE_SIZE;
+}
+
+/* Page directory and table entries only need Present set */
+#define MAKE_PT_MLE_ENTRY(addr)  (((grub_uint64_t)(grub_addr_t)(addr) & GRUB_PAGE_MASK) | 0x01)
+
+/*
+ * The MLE page tables have to be below the MLE and have no special regions in
+ * between them and the MLE (this is a bit of an unwritten rule).
+ * 20 pages are carved out of memory below the MLE. That leave 18 page table
+ * pages that can cover up to 36M .
+ * can only contain 4k pages
+ *
+ * TODO: TXT Spec p.32; List section name and number with PT MLE requirments here.
+ *
+ * TODO: This function is not able to cover MLEs larger than 1 GiB. Fix it!!!
+ * After fixing inrease GRUB_TXT_MLE_MAX_SIZE too.
+ */
+void
+grub_txt_setup_mle_ptab (struct grub_slaunch_params *slparams)
+{
+  grub_uint8_t *pg_dir, *pg_dir_ptr_tab = slparams->mle_ptab_mem, *pg_tab;
+  grub_uint32_t mle_off = 0, pd_off = 0;
+  grub_uint64_t *pde, *pte;
+
+  grub_memset (pg_dir_ptr_tab, 0, slparams->mle_ptab_size);
+
+  pg_dir         = pg_dir_ptr_tab + GRUB_PAGE_SIZE;
+  pg_tab         = pg_dir + GRUB_PAGE_SIZE;
+
+  /* Only use first entry in page dir ptr table */
+  *(grub_uint64_t *)pg_dir_ptr_tab = MAKE_PT_MLE_ENTRY(pg_dir);
+
+  /* Start with first entry in page dir */
+  *(grub_uint64_t *)pg_dir = MAKE_PT_MLE_ENTRY(pg_tab);
+
+  pte = (grub_uint64_t *)pg_tab;
+  pde = (grub_uint64_t *)pg_dir;
+
+  do
+    {
+      *pte = MAKE_PT_MLE_ENTRY(slparams->mle_start + mle_off);
+
+      pte++;
+      mle_off += GRUB_PAGE_SIZE;
+
+      if (!(++pd_off % 512))
+        {
+          /* Break if we don't need any additional page entries */
+          if (mle_off >= slparams->mle_size)
+            break;
+          pde++;
+          *pde = MAKE_PT_MLE_ENTRY(pte);
+        }
+    } while (mle_off < slparams->mle_size);
+}
+
+grub_err_t
+grub_txt_init (void)
+{
+  grub_err_t err;
+
+  err = grub_txt_verify_platform ();
+
+  if (err != GRUB_ERR_NONE)
+    return err;
+
+  err = enable_smx_mode ();
+
+  if (err != GRUB_ERR_NONE)
+    return err;
+
+  return GRUB_ERR_NONE;
+}
+
+void
+grub_txt_shutdown (void)
+{
+  /* Disable SMX mode. */
+  grub_write_cr4 (grub_read_cr4 () & ~GRUB_CR4_X86_SMXE);
+}
+
+void
+grub_txt_state_show (void)
+{
+  grub_uint64_t data;
+  grub_uint8_t *data8 = (grub_uint8_t *) &data;
+  int i;
+
+  data = grub_txt_reg_pub_readq (GRUB_TXT_STS);
+  grub_printf ("  TXT.STS: 0x%016" PRIxGRUB_UINT64_T "\n"
+	       "    SENTER.DONE.STS:        %d\n"
+	       "    SEXIT.DONE.STS:         %d\n"
+	       "    MEM-CONFIGLOCK.STS:     %d\n"
+	       "    PRIVATEOPEN.STS:        %d\n"
+	       "    TXT.LOCALITY1.OPEN.STS: %d\n"
+	       "    TXT.LOCALITY2.OPEN.STS: %d\n",
+	       data, !!(data & GRUB_TXT_STS_SENTER_DONE),
+	       !!(data & GRUB_TXT_STS_SEXIT_DONE),
+	       !!(data & GRUB_TXT_STS_MEM_CONFIG_LOCK),
+	       !!(data & GRUB_TXT_STS_PRIVATE_OPEN),
+	       !!(data & GRUB_TXT_STS_LOCALITY1_OPEN),
+	       !!(data & GRUB_TXT_STS_LOCALITY2_OPEN));
+
+  /* Only least significant byte has a meaning. */
+  data = grub_txt_reg_pub_readq (GRUB_TXT_ESTS) & 0x00000000000000ff;
+  grub_printf ("  TXT.ESTS: 0x%02" PRIxGRUB_UINT64_T "\n"
+	       "    TXT_RESET.STS: %d\n", data,
+	       !!(data & GRUB_TXT_ESTS_TXT_RESET));
+
+  data = grub_txt_reg_pub_readq (GRUB_TXT_E2STS);
+  grub_printf ("  TXT.E2STS: 0x%016" PRIxGRUB_UINT64_T "\n"
+	       "    SECRETS.STS: %d\n", data,
+	       !!(data & GRUB_TXT_E2STS_SECRETS));
+
+  /* Only least significant 4 bytes have a meaning. */
+  data = grub_txt_reg_pub_readq (GRUB_TXT_ERRORCODE) & 0x00000000ffffffff;
+  grub_printf ("  TXT.ERRORCODE: 0x%08" PRIxGRUB_UINT64_T "\n", data);
+
+  data = grub_txt_reg_pub_readq (GRUB_TXT_DIDVID);
+  grub_printf ("  TXT.DIDVID: 0x%016" PRIxGRUB_UINT64_T "\n"
+	       "    VID:    0x%04" PRIxGRUB_UINT64_T "\n"
+	       "    DID:    0x%04" PRIxGRUB_UINT64_T "\n"
+	       "    RID:    0x%04" PRIxGRUB_UINT64_T "\n"
+	       "    ID-EXT: 0x%04" PRIxGRUB_UINT64_T "\n",
+	       data, data & 0x000000000000ffff,
+	       (data & 0x00000000ffff0000) >> 16,
+	       (data & 0x0000ffff00000000) >> 32, data >> 48);
+
+  /* Only least significant 4 bytes have a meaning. */
+  data = grub_txt_reg_pub_readq (GRUB_TXT_VER_FSBIF) & 0x00000000ffffffff;
+  grub_printf ("  TXT.VER.FSBIF: 0x%08" PRIxGRUB_UINT64_T "\n", data);
+
+  if ((data != 0x00000000) && (data != 0xffffffff))
+    grub_printf ("    DEBUG.FUSE: %d\n", !!(data & GRUB_TXT_VER_FSBIF_DEBUG_FUSE));
+  else
+    {
+      /* Only least significant 4 bytes have a meaning. */
+      data = grub_txt_reg_pub_readq (GRUB_TXT_VER_QPIIF) & 0x00000000ffffffff;
+      grub_printf ("  TXT.VER.QPIIF: 0x%08" PRIxGRUB_UINT64_T "\n"
+		   "    DEBUG.FUSE: %d\n", data,
+		   !!(data & GRUB_TXT_VER_QPIIF_DEBUG_FUSE));
+    }
+
+  /* Only least significant 4 bytes have a meaning. */
+  data = grub_txt_reg_pub_readq (GRUB_TXT_SINIT_BASE) & 0x00000000ffffffff;
+  grub_printf ("  TXT.SINIT.BASE: 0x%08" PRIxGRUB_UINT64_T "\n", data);
+
+  /* Only least significant 4 bytes have a meaning. */
+  data = grub_txt_reg_pub_readq (GRUB_TXT_SINIT_SIZE) & 0x00000000ffffffff;
+  grub_printf ("  TXT.SINIT.SIZE: %" PRIuGRUB_UINT64_T
+	       " B (0x%" PRIxGRUB_UINT64_T ")\n", data, data);
+
+  /* Only least significant 4 bytes have a meaning. */
+  data = grub_txt_reg_pub_readq (GRUB_TXT_HEAP_BASE) & 0x00000000ffffffff;
+  grub_printf ("  TXT.HEAP.BASE: 0x%08" PRIxGRUB_UINT64_T "\n", data);
+
+  /* Only least significant 4 bytes have a meaning. */
+  data = grub_txt_reg_pub_readq (GRUB_TXT_HEAP_SIZE) & 0x00000000ffffffff;
+  grub_printf ("  TXT.HEAP.SIZE: %" PRIuGRUB_UINT64_T
+	       " B (0x%" PRIxGRUB_UINT64_T ")\n", data, data);
+
+  /* Only least significant 4 bytes have a meaning. */
+  data = grub_txt_reg_pub_readq (GRUB_TXT_DPR) & 0x00000000ffffffff;
+  grub_printf ("  TXT.DPR: 0x%08" PRIxGRUB_UINT64_T "\n"
+	       "    LOCK: %d\n"
+	       "    TOP:  0x%08" PRIxGRUB_UINT64_T "\n"
+	       "    SIZE: %" PRIuGRUB_UINT64_T " MiB\n",
+	       data, !!(data & (1 << 0)), (data & 0xfff00000),
+	       (data & 0x00000ff0) >> 4);
+
+  grub_printf ("  TXT.PUBLIC.KEY:\n");
+
+  for (i = 0; i < 4; ++i)
+    {
+      /* TODO: Check relevant MSRs on SGX platforms. */
+      data = grub_txt_reg_pub_readq (GRUB_TXT_PUBLIC_KEY + i * sizeof (grub_uint64_t));
+      grub_printf ("    %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x%s", data8[0], data8[1],
+		   data8[2], data8[3], data8[4], data8[5], data8[6], data8[7],
+		   (i < 3) ? ":\n" : "\n");
+    }
+}
+
+grub_err_t
+grub_txt_boot_prepare (struct grub_slaunch_params *slparams)
+{
+  grub_err_t err;
+  struct grub_txt_mle_header *mle_header;
+  struct grub_txt_acm_header *sinit_base;
+
+  sinit_base = grub_txt_sinit_select (grub_slaunch_module ());
+
+  if (sinit_base == NULL)
+    return grub_errno;
+
+  err = init_txt_heap (slparams, sinit_base);
+
+  if (err != GRUB_ERR_NONE)
+    return err;
+
+  /* Update the MLE header. */
+  mle_header = (struct grub_txt_mle_header *)(grub_addr_t) (slparams->mle_start + slparams->mle_header_offset);
+  mle_header->first_valid_page = 0;
+  mle_header->mle_end = slparams->mle_size;
+
+  slparams->sinit_acm_base = (grub_uint32_t)(grub_addr_t) sinit_base;
+  slparams->sinit_acm_size = sinit_base->size * 4;
+
+  grub_tpm_relinquish_lcl (0);
+
+  err = set_mtrrs_for_acmod (sinit_base);
+  if (err)
+    return grub_error (err, N_("secure launch failed to set MTRRs for ACM"));
+
+  err = grub_txt_prepare_cpu ();
+  if ( err )
+    return err;
+
+  if (!(grub_rdmsr (GRUB_MSR_X86_APICBASE) & GRUB_MSR_X86_APICBASE_BSP))
+    return grub_error (GRUB_ERR_BAD_DEVICE, N_("secure launch must run on BSP"));
+
+  return GRUB_ERR_NONE;
+}
diff --git a/include/grub/i386/memory.h b/include/grub/i386/memory.h
index c64529630..56f64855b 100644
--- a/include/grub/i386/memory.h
+++ b/include/grub/i386/memory.h
@@ -22,6 +22,7 @@
 
 #define GRUB_PAGE_SHIFT		12
 #define GRUB_PAGE_SIZE		(1UL << GRUB_PAGE_SHIFT)
+#define GRUB_PAGE_MASK		(~(GRUB_PAGE_SIZE - 1))
 
 /* The flag for protected mode.  */
 #define GRUB_MEMORY_CPU_CR0_PE_ON		0x1
@@ -43,8 +44,12 @@
 
 #define GRUB_MMAP_MALLOC_LOW 1
 
+#include <grub/misc.h>
 #include <grub/types.h>
 
+#define GRUB_PAGE_UP(p)		ALIGN_UP (p, GRUB_PAGE_SIZE)
+#define GRUB_PAGE_DOWN(p)	ALIGN_DOWN (p, GRUB_PAGE_SIZE)
+
 struct grub_e820_mmap_entry
 {
   grub_uint64_t addr;
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 16/18] i386/txt: Add Intel TXT ACM module support
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (14 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 15/18] i386/txt: Add Intel TXT core implementation Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 17/18] i386/txt: Add Intel TXT verification routines Daniel Kiper
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

From: Ross Philipson <ross.philipson@oracle.com>

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/loader/i386/txt/acmod.c | 575 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 575 insertions(+)
 create mode 100644 grub-core/loader/i386/txt/acmod.c

diff --git a/grub-core/loader/i386/txt/acmod.c b/grub-core/loader/i386/txt/acmod.c
new file mode 100644
index 000000000..ed2fbab7b
--- /dev/null
+++ b/grub-core/loader/i386/txt/acmod.c
@@ -0,0 +1,575 @@
+/*
+ * acmod.c: support functions for use of Intel(r) TXT Authenticated
+ *          Code (AC) Modules
+ *
+ * Copyright (c) 2003-2011, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of the Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  Oracle and/or its affiliates.
+ *
+ *  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/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/memory.h>
+#include <grub/normal.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/cpu/relocator.h>
+#include <grub/i386/cpuid.h>
+#include <grub/i386/msr.h>
+#include <grub/i386/txt.h>
+
+/*
+ * This checks to see if two numbers multiplied together are larger
+ *   than the type that they are.  Returns TRUE if OVERFLOWING.
+ *   If the first parameter "x" is greater than zero and
+ *   if that is true, that the largest possible value 0xFFFFFFFF / "x"
+ *   is less than the second parameter "y".  If "y" is zero then
+ *   it will also fail because no unsigned number is less than zero.
+ */
+static inline int
+multiply_overflow_u32 (grub_uint32_t x, grub_uint32_t y)
+{
+  /* Use x instead of (x > 0)? */
+  return (x > 0) ? ((((grub_uint32_t)(~0))/x) < y) : 0;
+}
+
+/*
+ *  These three "plus overflow" functions take a "x" value
+ *    and add the "y" value to it and if the two values are
+ *    greater than the size of the variable type, they will
+ *    overflow the type and end up with a smaller value and
+ *    return TRUE - that they did overflow.  i.e.
+ */
+static inline int plus_overflow_u32 (grub_uint32_t x, grub_uint32_t y)
+{
+  return ((((grub_uint32_t)(~0)) - x) < y);
+}
+
+static struct grub_txt_acm_info_table*
+get_acmod_info_table (struct grub_txt_acm_header* hdr)
+{
+  grub_uint32_t user_area_off;
+
+  /* Overflow? */
+  if ( plus_overflow_u32 (hdr->header_len, hdr->scratch_size) )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("ACM header length plus scratch size overflows"));
+      return NULL;
+    }
+
+  if ( multiply_overflow_u32 ((hdr->header_len + hdr->scratch_size), 4) )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("ACM header length and scratch size in bytes overflows"));
+      return NULL;
+    }
+
+  /*
+   * This fn assumes that the ACM has already passed at least the initial
+   * is_acmod() checks.
+   */
+
+  user_area_off = (hdr->header_len + hdr->scratch_size) * 4;
+
+  /* Overflow? */
+  if ( plus_overflow_u32 (user_area_off, sizeof(struct grub_txt_acm_info_table)) )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("user_area_off plus acm_info_table_t size overflows"));
+      return NULL;
+    }
+
+  /* Check that table is within module. */
+  if ( user_area_off + sizeof(struct grub_txt_acm_info_table) > hdr->size * 4 )
+    {
+      /* TODO: Is (grub_uint32_t) correct??? */
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("ACM info table size too large: %x > %x"),
+		  user_area_off + (grub_uint32_t)sizeof(struct grub_txt_acm_info_table), hdr->size * 4);
+      return NULL;
+    }
+
+  /* Overflow? */
+  if ( plus_overflow_u32 ((grub_uint32_t)(unsigned long)hdr, user_area_off) )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("hdr plus user_area_off overflows"));
+      return NULL;
+    }
+
+    return (struct grub_txt_acm_info_table *)((unsigned long)hdr + user_area_off);
+}
+
+static struct grub_txt_acm_chipset_id_list*
+get_acmod_chipset_list (struct grub_txt_acm_header *hdr)
+{
+  struct grub_txt_acm_info_table *info_table;
+  grub_uint32_t size, id_list_off;
+  struct grub_txt_acm_chipset_id_list *chipset_id_list;
+
+  /* This fn assumes that the ACM has already passed the is_acmod() checks */
+
+  info_table = get_acmod_info_table (hdr);
+  if ( !info_table )
+    return NULL;
+  id_list_off = info_table->chipset_id_list;
+
+  size = hdr->size * 4;
+
+  /* Overflow? */
+  if ( plus_overflow_u32 (id_list_off, sizeof(struct grub_txt_acm_chipset_id)) )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("id_list_off plus acm_chipset_id_t size overflows"));
+      return NULL;
+    }
+
+  /* Check that chipset id table is w/in ACM */
+  if ( id_list_off + sizeof(struct grub_txt_acm_chipset_id) > size )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("chipset id list is too big: %x"), id_list_off);
+      return NULL;
+    }
+
+  /* Overflow? */
+  if ( plus_overflow_u32 ((grub_uint32_t)(unsigned long)hdr, id_list_off) )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("hdr plus id_list_off overflows"));
+      return NULL;
+    }
+
+  chipset_id_list = (struct grub_txt_acm_chipset_id_list*)
+                    ((unsigned long)hdr + id_list_off);
+
+  /* Overflows? */
+  if ( multiply_overflow_u32 (chipset_id_list->count,
+                              sizeof(struct grub_txt_acm_chipset_id)) )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("size of acm_chipset_id_list overflows"));
+      return NULL;
+    }
+
+  if ( plus_overflow_u32 (id_list_off + sizeof(struct grub_txt_acm_chipset_id),
+        chipset_id_list->count * sizeof(struct grub_txt_acm_chipset_id)) )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("size of all entries overflows"));
+      return NULL;
+    }
+
+  /* Check that all entries are w/in ACM */
+  if ( id_list_off + sizeof(struct grub_txt_acm_chipset_id) +
+       chipset_id_list->count * sizeof(struct grub_txt_acm_chipset_id) > size )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("ACM chipset id entries are too big: %x"),
+		  chipset_id_list->count);
+      return NULL;
+    }
+
+  return chipset_id_list;
+}
+
+static struct grub_txt_acm_processor_id_list*
+get_acmod_processor_list (struct grub_txt_acm_header* hdr)
+{
+  struct grub_txt_acm_info_table *info_table;
+  grub_uint32_t size, id_list_off;
+  struct grub_txt_acm_processor_id_list *proc_id_list;
+
+  /* This fn assumes that the ACM has already passed the is_acmod() checks */
+
+  info_table = get_acmod_info_table(hdr);
+  if ( info_table == NULL )
+    return NULL;
+  id_list_off = info_table->processor_id_list;
+
+  size = hdr->size * 4;
+
+  /* Overflow? */
+  if ( plus_overflow_u32 (id_list_off, sizeof(struct grub_txt_acm_processor_id)) )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("id_list_off plus acm_processor_id_t size overflows"));
+      return NULL;
+    }
+
+  /* Check that processor id table is w/in ACM */
+  if ( id_list_off + sizeof(struct grub_txt_acm_processor_id) > size )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("ACM processor id list is too big: %x"), id_list_off);
+      return NULL;
+    }
+
+  /* Overflow? */
+  if ( plus_overflow_u32 ((unsigned long)hdr, id_list_off) )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("hdr plus id_list_off overflows"));
+      return NULL;
+    }
+
+  proc_id_list = (struct grub_txt_acm_processor_id_list *)
+                             ((unsigned long)hdr + id_list_off);
+
+  /* Overflows? */
+  if ( multiply_overflow_u32 (proc_id_list->count,
+             sizeof(struct grub_txt_acm_processor_id)) )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("size of acm_processor_id_list overflows"));
+      return NULL;
+    }
+
+  if ( plus_overflow_u32 (id_list_off + sizeof(struct grub_txt_acm_processor_id),
+        proc_id_list->count * sizeof(struct grub_txt_acm_processor_id)) )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("size of all entries overflows"));
+      return NULL;
+    }
+
+  /* Check that all entries are w/in ACM */
+  if ( id_list_off + sizeof(struct grub_txt_acm_processor_id) +
+         proc_id_list->count * sizeof(struct grub_txt_acm_processor_id) > size )
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("ACM processor id entries are too big: %x"),
+		  proc_id_list->count);
+      return NULL;
+    }
+
+  return proc_id_list;
+}
+
+static int
+is_acmod (const void *acmod_base, grub_uint32_t acmod_size,
+         grub_uint8_t *type_out)
+{
+  struct grub_txt_acm_header *acm_hdr = (struct grub_txt_acm_header *)acmod_base;
+  struct grub_txt_acm_info_table *info_table;
+
+  /* First check size */
+  if ( acmod_size < sizeof (struct grub_txt_acm_header) )
+    return 0;
+
+  /* Then check overflow */
+  if ( multiply_overflow_u32 (acm_hdr->size, 4) )
+    return 0;
+
+  /* Then check size equivalency */
+  if ( acmod_size != acm_hdr->size * 4 )
+    return 0;
+
+  /* Then check type and vendor */
+  if ( (acm_hdr->module_type != GRUB_TXT_ACM_MODULE_TYPE) ||
+       (acm_hdr->module_vendor != GRUB_TXT_ACM_MODULE_VENDOR_INTEL) )
+    return 0;
+
+  info_table = get_acmod_info_table (acm_hdr);
+  if ( !info_table )
+    return 0;
+
+  /* Check if ACM UUID is present */
+  if ( grub_memcmp (&(info_table->uuid), GRUB_TXT_ACM_UUID, 16) )
+    return 0;
+
+  if ( type_out )
+    *type_out = info_table->chipset_acm_type;
+
+  return 1;
+}
+
+static struct grub_txt_acm_header*
+get_bios_sinit (void *sinit_region_base)
+{
+  grub_uint8_t *txt_heap = grub_txt_get_heap ();
+  struct grub_txt_bios_data *bios_data = grub_txt_bios_data_start (txt_heap);
+  struct grub_txt_acm_header *bios_sinit;
+
+  if ( !sinit_region_base )
+     return NULL;
+
+  if ( bios_data->bios_sinit_size == 0 )
+    return NULL;
+
+  /* BIOS has loaded an SINIT module, so verify that it is valid */
+  grub_dprintf ("slaunch", "BIOS has already loaded an SINIT module\n");
+
+  bios_sinit = (struct grub_txt_acm_header *)sinit_region_base;
+
+  /* Is it a valid SINIT module? */
+  if ( !grub_txt_is_sinit_acmod (sinit_region_base, bios_data->bios_sinit_size) ||
+       !grub_txt_acmod_match_platform (bios_sinit) )
+    return NULL;
+
+  return bios_sinit;
+}
+
+grub_uint32_t
+grub_txt_supported_os_sinit_data_ver (struct grub_txt_acm_header* hdr)
+{
+  static struct grub_txt_acm_info_table *info_table;
+
+  /* Assumes that it passed is_sinit_acmod() */
+  info_table = get_acmod_info_table (hdr);
+
+  if ( info_table == NULL )
+    return 0;
+
+  return info_table->os_sinit_data_ver;
+}
+
+grub_uint32_t
+grub_txt_get_sinit_capabilities (struct grub_txt_acm_header* hdr)
+{
+  static struct grub_txt_acm_info_table *info_table;
+
+  /* Assumes that it passed is_sinit_acmod() */
+  info_table = get_acmod_info_table (hdr);
+
+  if ( info_table == NULL || info_table->version < 3 )
+    return 0;
+
+  return info_table->capabilities;
+}
+
+int
+grub_txt_is_sinit_acmod (const void *acmod_base, grub_uint32_t acmod_size)
+{
+  grub_uint8_t type;
+
+  if ( !is_acmod (acmod_base, acmod_size, &type) )
+    return 0;
+
+  if ( type != GRUB_TXT_ACM_CHIPSET_TYPE_SINIT )
+    return 0;
+
+  return 1;
+}
+
+/* Format of VER.FSBIF and VER.QPIIF registers. */
+typedef union {
+  grub_uint64_t _raw;
+  struct {
+     grub_uint64_t reserved   : 31;
+     grub_uint64_t prod_fused : 1;
+  };
+} grub_txt_ver_fsbif_qpiif_t;
+
+int
+grub_txt_acmod_match_platform (struct grub_txt_acm_header *hdr)
+{
+  union grub_txt_didvid didvid;
+  grub_uint32_t fms, ign, i;
+  grub_uint64_t platform_id;
+  grub_txt_ver_fsbif_qpiif_t ver;
+  struct grub_txt_acm_chipset_id_list *chipset_id_list;
+  struct grub_txt_acm_chipset_id *chipset_id;
+  struct grub_txt_acm_processor_id_list *proc_id_list;
+  struct grub_txt_acm_processor_id *proc_id;
+  struct grub_txt_acm_info_table *info_table;
+
+  /* This fn assumes that the ACM has already passed the is_acmod() checks */
+
+  /* Get chipset fusing, device, and vendor id info */
+  didvid.value = grub_txt_reg_pub_readq (GRUB_TXT_DIDVID);
+
+  ver._raw = grub_txt_reg_pub_readq (GRUB_TXT_VER_FSBIF);
+  if ( (ver._raw & 0xffffffff) == 0xffffffff ||
+       (ver._raw & 0xffffffff) == 0x00 ) /* Need to use VER.QPIIF */
+    ver._raw = grub_txt_reg_pub_readq (GRUB_TXT_VER_QPIIF);
+
+  grub_dprintf ("slaunch", "chipset production fused: %x, "
+		"chipset vendor: 0x%x, device: 0x%x, revision: 0x%x\n",
+		ver.prod_fused, didvid.vid, didvid.did, didvid.rid);
+
+  grub_cpuid (1, fms, ign, ign, ign);
+  platform_id = grub_rdmsr (GRUB_MSR_X86_PLATFORM_ID);
+
+  grub_dprintf ("slaunch", "processor family/model/stepping: 0x%x, "
+		"platform id: 0x%" PRIxGRUB_UINT64_T "\n", fms, platform_id);
+
+  /*
+   * Check if chipset fusing is same. Note the DEBUG.FUSE bit in the version
+   * is 0 when debug fused so the logic below checking a mismatch is valid.
+   */
+  if ( (ver._raw & GRUB_TXT_VERSION_DEBUG_FUSED) &&
+       (hdr->flags & GRUB_TXT_ACM_FLAG_DEBUG_SIGNED) )
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, N_("production/debug mismatch between chipset and ACM"));
+      return 0;
+    }
+
+  /* Check if chipset vendor/device/revision IDs match */
+  chipset_id_list = get_acmod_chipset_list (hdr);
+  if ( !chipset_id_list )
+    return 0;
+
+  grub_dprintf ("slaunch", "%d SINIT ACM chipset id entries:\n", chipset_id_list->count);
+
+  chipset_id = (struct grub_txt_acm_chipset_id *) ((grub_addr_t)chipset_id_list + sizeof (chipset_id_list->count));
+  for (i = 0; i < chipset_id_list->count; i++, chipset_id++)
+    {
+      grub_dprintf ("slaunch", "  vendor: 0x%x, device: 0x%x, flags: 0x%x, "
+		    "revision: 0x%x, extended: 0x%x\n", chipset_id->vendor_id,
+		    chipset_id->device_id, chipset_id->flags,
+		    chipset_id->revision_id, chipset_id->extended_id);
+
+      if ( (didvid.vid == chipset_id->vendor_id ) &&
+           (didvid.did == chipset_id->device_id ) &&
+           ( ( ( (chipset_id->flags & GRUB_TXT_ACM_REVISION_ID_MASK) == 0) &&
+                 (didvid.rid == chipset_id->revision_id) ) ||
+               ( ( (chipset_id->flags & GRUB_TXT_ACM_REVISION_ID_MASK) == 1) &&
+                 ( (didvid.rid & chipset_id->revision_id) != 0 ) ) ) )
+            break;
+    }
+
+  if ( i >= chipset_id_list->count )
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, N_("chipset id mismatch"));
+      return 0;
+    }
+
+  /* Check if processor family/model/stepping and platform IDs match */
+  info_table = get_acmod_info_table (hdr);
+  if ( !info_table )
+    return 0;
+
+  /*
+   * Logic inverted from oringal to avoid the if block. Not sure what drives
+   * the logic of not checking processor infrmation for version 4 or less.
+   */
+  if ( info_table->version < 4 )
+    return 1;
+
+  proc_id_list = get_acmod_processor_list(hdr);
+  if ( !proc_id_list )
+    return 1;
+
+  grub_dprintf ("slaunch", "%d SINIT ACM processor id entries:\n", proc_id_list->count);
+
+  proc_id = (struct grub_txt_acm_processor_id *) ((grub_addr_t)proc_id_list + sizeof (proc_id_list->count));
+  for (i = 0; i < proc_id_list->count; i++, proc_id++)
+    {
+      grub_dprintf ("slaunch", "  fms: 0x%x, fms_mask: 0x%x, platform_id: 0x%" PRIxGRUB_UINT64_T
+		    ", platform_mask: 0x%" PRIxGRUB_UINT64_T "\n", proc_id->fms, proc_id->fms_mask,
+		    proc_id->platform_id, proc_id->platform_mask);
+
+      if ( (proc_id->fms == (fms & proc_id->fms_mask)) &&
+           (proc_id->platform_id == (platform_id & proc_id->platform_mask)) )
+        break;
+    }
+
+  if ( i >= proc_id_list->count )
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, N_("chipset id mismatch"));
+      return 0;
+    }
+
+  return 1;
+}
+
+struct grub_txt_acm_header *
+grub_txt_sinit_select (struct grub_txt_acm_header *sinit)
+{
+  struct grub_txt_acm_header *bios_sinit;
+  void *sinit_region_base;
+  grub_uint32_t sinit_region_size;
+
+  sinit_region_base = (void *)(grub_addr_t) grub_txt_reg_pub_readq (GRUB_TXT_SINIT_BASE);
+  sinit_region_size = (grub_uint32_t) grub_txt_reg_pub_readq (GRUB_TXT_SINIT_SIZE);
+
+  grub_dprintf ("slaunch", "TXT.SINIT.BASE: %p\nTXT.SINIT.SIZE: 0x%"
+		PRIxGRUB_UINT32_T "\n", sinit_region_base, sinit_region_size);
+
+  if (sinit_region_base == NULL)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("no SINIT ACM final resting place"));
+      return NULL;
+    }
+
+  if (sinit != NULL)
+    grub_dprintf ("slaunch", "SINIT ACM date: %" PRIxGRUB_UINT32_T "\n", sinit->date);
+
+  bios_sinit = get_bios_sinit (sinit_region_base);
+
+  /* Does BIOS provide SINIT ACM? */
+  if (bios_sinit != NULL)
+    {
+      grub_dprintf ("slaunch", "BIOS SINIT ACM date: %" PRIxGRUB_UINT32_T "\n",
+		    bios_sinit->date);
+
+      if (sinit == NULL)
+        {
+	  grub_dprintf ("slaunch", "no SINIT ACM provided. Using BIOS SINIT ACM\n");
+          return bios_sinit;
+        }
+
+      if (bios_sinit->date >= sinit->date)
+        {
+          grub_dprintf ("slaunch", "BIOS provides newer or same SINIT ACM, so, using BIOS one\n");
+          return bios_sinit;
+        }
+
+      grub_dprintf ("slaunch", "BIOS provides older SINIT ACM, so, ignoring BIOS one\n");
+    }
+
+  /* Fail if there is no SINIT ACM. */
+  if (sinit == NULL)
+    return NULL;
+
+  /* Our SINIT ACM is newer than BIOS one or BIOS does not have one. */
+
+  if (multiply_overflow_u32 (sinit->size, 4))
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("SINIT ACM size in bytes overflows"));
+      return NULL;
+    }
+
+  if ((sinit->size * 4) > sinit_region_size)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY,
+		  N_("SINIT ACM does not fit into final resting place: 0x%"
+		  PRIxGRUB_UINT32_T "\n"), sinit->size * 4);
+      return NULL;
+    }
+
+  grub_memcpy (sinit_region_base, sinit, sinit->size * 4);
+
+  return sinit_region_base;
+}
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 17/18] i386/txt: Add Intel TXT verification routines
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (15 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 16/18] i386/txt: Add Intel TXT ACM module support Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-04 23:21 ` [GRUB PATCH RFC 18/18] i386/slaunch: Add secure launch framework and commands Daniel Kiper
  2020-05-05 14:38 ` [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Lukasz Hawrylko
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

From: Ross Philipson <ross.philipson@oracle.com>

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/loader/i386/txt/verify.c | 297 +++++++++++++++++++++++++++++++++++++
 1 file changed, 297 insertions(+)
 create mode 100644 grub-core/loader/i386/txt/verify.c

diff --git a/grub-core/loader/i386/txt/verify.c b/grub-core/loader/i386/txt/verify.c
new file mode 100644
index 000000000..97f3b325d
--- /dev/null
+++ b/grub-core/loader/i386/txt/verify.c
@@ -0,0 +1,297 @@
+/*
+ * verify.c: verify that platform and processor supports Intel(r) TXT
+ *
+ * Copyright (c) 2003-2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of the Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  Oracle and/or its affiliates.
+ *
+ *  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/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/memory.h>
+#include <grub/normal.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/cpu/relocator.h>
+#include <grub/i386/cpuid.h>
+#include <grub/i386/msr.h>
+#include <grub/i386/txt.h>
+
+/* Current max that the secure launch can handle */
+#define TXT_MAX_CPUS	512
+
+static grub_err_t
+verify_bios_spec_ver_elt (struct grub_txt_heap_ext_data_element *elt)
+{
+  grub_uint8_t *ptr = (grub_uint8_t *)elt;
+  struct grub_txt_heap_bios_spec_ver_element *bios_spec_ver_elt =
+         (struct grub_txt_heap_bios_spec_ver_element *)ptr;
+
+  if ( elt->size != sizeof(*elt) + sizeof(*bios_spec_ver_elt) )
+    return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                N_("HEAP_BIOS_SPEC_VER element has wrong size (%d)"),
+                elt->size);
+
+  /* Any values are allowed */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+verify_acm_elt (struct grub_txt_heap_ext_data_element *elt)
+{
+  grub_uint8_t *ptr = ((grub_uint8_t *)elt + sizeof(*elt));
+  struct grub_txt_heap_acm_element *acm_elt =
+         (struct grub_txt_heap_acm_element *)ptr;
+  grub_uint64_t *acm_addrs;
+  grub_uint32_t i;
+
+  if ( elt->size != sizeof(*elt) + sizeof(*acm_elt) +
+       acm_elt->num_acms*sizeof(grub_uint64_t) )
+    return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                N_("HEAP_ACM element has wrong size (%d)"),
+                elt->size);
+
+  /* No addrs is not error, but print warning. */
+  if ( acm_elt->num_acms == 0 )
+    grub_printf ("WARNING: HEAP_ACM element has no ACM addrs\n");
+
+  acm_addrs = (grub_uint64_t *)(ptr + sizeof(*acm_elt));
+  for ( i = 0; i < acm_elt->num_acms; i++ )
+    {
+      if ( acm_addrs[i] == 0 )
+        return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                    N_("HEAP_ACM element ACM addr (%d) is NULL"), i);
+
+      if ( acm_addrs[i] >= 0x100000000UL )
+        return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                    N_("HEAP_ACM element ACM addr (%d) is >4GB"), i);
+
+      /* Not going to check if ACM addrs are valid ACMs */
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+verify_custom_elt (struct grub_txt_heap_ext_data_element *elt)
+{
+  grub_uint8_t *ptr = (grub_uint8_t *)elt;
+  struct grub_txt_heap_custom_element *custom_elt =
+         (struct grub_txt_heap_custom_element *)ptr;
+
+  if ( elt->size < sizeof(*elt) + sizeof(*custom_elt) )
+     return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                 N_("HEAP_CUSTOM element has wrong size (%d)"),
+                 elt->size);
+
+  /* Any values are allowed */
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+verify_evt_log_ptr_elt (struct grub_txt_heap_ext_data_element *elt)
+{
+  grub_uint8_t *ptr = (grub_uint8_t *)elt;
+  struct grub_txt_heap_tpm_event_log_element *elog_elt =
+         (struct grub_txt_heap_tpm_event_log_element *)ptr;
+
+  if ( elt->size != sizeof(*elt) + sizeof(*elog_elt) )
+     return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                 N_("HEAP_EVENT_LOG_POINTER element has wrong size (%d)"),
+                 elt->size);
+
+  /* TODO: Sort out how to do this verifier once the event log handling is in place
+   *
+   * return verify_evt_log((event_log_container_t *)(unsigned long)
+   *                       elog_elt->event_log_phys_addr);
+   */
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+verify_ext_data_elts(struct grub_txt_heap_ext_data_element *elts,
+                     grub_uint64_t elts_size)
+{
+  struct grub_txt_heap_ext_data_element *elt = elts;
+  grub_err_t err;
+
+  if ( elts_size < sizeof(*elt) )
+     return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                 N_("TXT heap ext data elements too small"));
+
+  for ( ; ; )
+    {
+      if ( elts_size < elt->size || elt->size == 0 )
+        return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                    N_("TXT heap invalid element size: type: %d, size: %d"),
+                    elt->type, elt->size);
+
+      switch ( elt->type )
+        {
+          case GRUB_TXT_HEAP_EXTDATA_TYPE_END:
+            return GRUB_ERR_NONE;
+          case GRUB_TXT_HEAP_EXTDATA_TYPE_BIOS_SPEC_VER:
+            err = verify_bios_spec_ver_elt (elt);
+            if ( err )
+              return err;
+            break;
+          case GRUB_TXT_HEAP_EXTDATA_TYPE_ACM:
+            err = verify_acm_elt (elt);
+            if ( err )
+              return err;
+            break;
+          case GRUB_TXT_HEAP_EXTDATA_TYPE_STM:
+            /* Nothing to check, platform specific */
+            break;
+          case GRUB_TXT_HEAP_EXTDATA_TYPE_CUSTOM:
+            err = verify_custom_elt (elt);
+            if ( err )
+              return err;
+            break;
+          case GRUB_TXT_HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR:
+            err = verify_evt_log_ptr_elt (elt);
+            if ( err )
+              return err;
+            break;
+          case GRUB_TXT_HEAP_EXTDATA_TYPE_MADT:
+            /* Copy of ACPI MADT, not validating */
+            break;
+          case GRUB_TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1:
+            /* TODO TBOOT did not verify this, not sure why or how to do it */
+            break;
+          case GRUB_TXT_HEAP_EXTDATA_TYPE_MCFG:
+            /* Copy of ACPI MCFG, not validating */
+            break;
+          default:
+	    /* TODO: What kind of element??? Improve the message. */
+	    grub_printf ("WARNING: unknown element: type: %u, size: %u\n", elt->type, elt->size);
+            break;
+        }
+
+      elts_size -= elt->size;
+      elt = (struct grub_txt_heap_ext_data_element *)((grub_uint8_t *)elt + elt->size);
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_txt_verify_platform (void)
+{
+  grub_uint8_t *txt_heap;
+  grub_uint32_t eax, ebx, ecx, edx;
+  grub_uint64_t bios_size, heap_base, heap_size, msr;
+  grub_err_t err = GRUB_ERR_NONE;
+  struct grub_txt_bios_data *bios_data;
+  struct grub_txt_heap_ext_data_element *elts;
+
+  grub_cpuid (GRUB_X86_CPUID_FEATURES, eax, ebx, ecx, edx);
+
+  if (!(ecx & GRUB_SMX_CPUID_FEATURE))
+    return grub_error (GRUB_ERR_BAD_DEVICE, N_("CPU does not support SMX"));
+
+  msr = grub_rdmsr (GRUB_MSR_X86_FEATURE_CONTROL);
+
+  if ((msr & (GRUB_MSR_X86_SENTER_FUNCTIONS | GRUB_MSR_X86_SENTER_ENABLE)) !=
+      (GRUB_MSR_X86_SENTER_FUNCTIONS | GRUB_MSR_X86_SENTER_ENABLE))
+    return grub_error (GRUB_ERR_BAD_DEVICE, N_("GETSEC[SENTER] is not enabled"));
+
+  /*
+   * TODO
+   * TXT Specification
+   * 4.5 SGX Requirement for TXT Platform
+   * Secure Launch currently does not support interop with SGX since it does
+   * not have TPM support to write the SE NVRAM index.
+   * Eventually need the verify_IA32_se_svn_status routine to be called here.
+   */
+
+  if (grub_txt_reg_pub_readq (GRUB_TXT_ESTS) & GRUB_TXT_ESTS_TXT_RESET)
+     return grub_error (GRUB_ERR_BAD_DEVICE,
+			N_("TXT_RESET.STS is set and GETSEC[SENTER] is disabled"));
+
+  /*
+   * Verify that the BIOS information in the TXT heap that was setup by the
+   * BIOS ACM is sane.
+   */
+
+  txt_heap = grub_txt_get_heap ();
+  heap_base = grub_txt_reg_pub_readq (GRUB_TXT_HEAP_BASE);
+  heap_size = grub_txt_reg_pub_readq (GRUB_TXT_HEAP_SIZE);
+
+  if ( txt_heap == NULL || heap_base == 0 || heap_size == 0 )
+     return grub_error (GRUB_ERR_BAD_DEVICE,
+                 N_("TXT heap is not configured correctly"));
+
+  bios_size = grub_txt_bios_data_size (txt_heap);
+  if ( bios_size == 0 || bios_size > heap_size )
+     return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                 N_("invalid size of the TXT heap BIOS data table"));
+
+  bios_data = grub_txt_bios_data_start (txt_heap);
+
+  /* Check version */
+  if ( bios_data->version < 5 )
+     return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                 N_("unsupported BIOS data version (%d)"), bios_data->version);
+
+  if ( bios_data->num_logical_procs > TXT_MAX_CPUS )
+     return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                 N_("BIOS reports too many CPUs for secure launch (%d)"),
+                 bios_data->num_logical_procs);
+
+  if ( bios_data->version >= 4 && bios_size > sizeof(*bios_data) + sizeof(bios_size) )
+    {
+      elts = (struct grub_txt_heap_ext_data_element *) ((grub_uint8_t *)bios_data + sizeof(*bios_data));
+      err = verify_ext_data_elts(elts, bios_size - sizeof(*bios_data));
+    }
+
+  return err;
+}
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [GRUB PATCH RFC 18/18] i386/slaunch: Add secure launch framework and commands
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (16 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 17/18] i386/txt: Add Intel TXT verification routines Daniel Kiper
@ 2020-05-04 23:21 ` Daniel Kiper
  2020-05-05 14:38 ` [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Lukasz Hawrylko
  18 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-04 23:21 UTC (permalink / raw)
  To: grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski, mjg59, phcoder,
	pirot.krol, pjones, ross.philipson

From: Ross Philipson <ross.philipson@oracle.com>

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/Makefile.am            |   3 +
 grub-core/Makefile.core.def      |  15 +++
 grub-core/lib/i386/relocator32.S |   8 ++
 grub-core/loader/i386/bsd.c      |   7 ++
 grub-core/loader/i386/linux.c    | 206 ++++++++++++++++++++++++++++++++++++---
 grub-core/loader/i386/slaunch.c  | 194 ++++++++++++++++++++++++++++++++++++
 grub-core/loader/i386/xnu.c      |   3 +
 grub-core/loader/multiboot.c     |   5 +
 include/grub/file.h              |   3 +
 include/grub/i386/linux.h        |  14 ++-
 include/grub/i386/slaunch.h      |  56 +++++++++++
 11 files changed, 500 insertions(+), 14 deletions(-)
 create mode 100644 grub-core/loader/i386/slaunch.c
 create mode 100644 include/grub/i386/slaunch.h

diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 3ea8e7ff4..ae6676e6f 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -99,6 +99,7 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
 KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h
 KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/slaunch.h
 endif
 
 if COND_i386_xen_pvh
@@ -118,6 +119,7 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/slaunch.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h
@@ -179,6 +181,7 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/slaunch.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index b74a34f0c..a07811b51 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1824,6 +1824,15 @@ module = {
 };
 
 module = {
+  name = slaunch;
+  x86 = loader/i386/slaunch.c;
+  x86 = loader/i386/txt/txt.c;
+  x86 = loader/i386/txt/acmod.c;
+  x86 = loader/i386/txt/verify.c;
+  enable = x86;
+};
+
+module = {
   name = fdt;
   efi = loader/efi/fdt.c;
   common = lib/fdt.c;
@@ -2497,6 +2506,12 @@ module = {
 };
 
 module = {
+  name = tpm;
+  x86 = commands/i386/tpm.c;
+  enable = x86;
+};
+
+module = {
   name = tpm_verifier;
   common = commands/tpm_verifier.c;
   efi = commands/efi/tpm.c;
diff --git a/grub-core/lib/i386/relocator32.S b/grub-core/lib/i386/relocator32.S
index 09ce56ad0..a2b377197 100644
--- a/grub-core/lib/i386/relocator32.S
+++ b/grub-core/lib/i386/relocator32.S
@@ -24,6 +24,8 @@
 
 #include "relocator_common.S"
 
+#include <grub/i386/slaunch.h>
+
 	.p2align	4	/* force 16-byte alignment */
 
 VARIABLE(grub_relocator32_start)
@@ -110,11 +112,17 @@ VARIABLE(grub_relocator32_edx)
 	   payload and makes this implementation easier.  */
 	cld
 
+	cmpl	$SLP_INTEL_TXT, %edi
+	je	LOCAL(intel_txt)
+
 	.byte	0xea
 VARIABLE(grub_relocator32_eip)
 	.long	0
 	.word	CODE_SEGMENT
 
+LOCAL(intel_txt):
+	getsec
+
 	/* GDT. Copied from loader/i386/linux.c. */
 	.p2align	4
 LOCAL(gdt):
diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
index eb82391db..53bb2af93 100644
--- a/grub-core/loader/i386/bsd.c
+++ b/grub-core/loader/i386/bsd.c
@@ -21,6 +21,10 @@
 #include <grub/i386/cpuid.h>
 #include <grub/memory.h>
 #include <grub/i386/memory.h>
+#if 0
+#include <grub/i386/slaunch.h>
+#endif
+#define SLP_NONE 0
 #include <grub/file.h>
 #include <grub/err.h>
 #include <grub/dl.h>
@@ -791,6 +795,7 @@ grub_freebsd_boot (void)
 #endif
 
       grub_memcpy (&stack[9], &bi, sizeof (bi));
+      state.edi = SLP_NONE;
       state.eip = entry;
       state.esp = stack_target;
       state.ebp = stack_target;
@@ -906,6 +911,7 @@ grub_openbsd_boot (void)
     return err;
 #endif
 
+  state.edi = SLP_NONE;
   state.eip = entry;
   state.ebp = state.esp
     = ((grub_uint8_t *) stack - (grub_uint8_t *) buf0) + buf_target;
@@ -1223,6 +1229,7 @@ grub_netbsd_boot (void)
     return err;
 #endif
 
+  state.edi = SLP_NONE;
   state.eip = entry;
   state.esp = stack_target;
   state.ebp = stack_target;
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index 952eb1191..da8be621e 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -34,6 +34,8 @@
 #include <grub/i386/relocator.h>
 #include <grub/i18n.h>
 #include <grub/lib/cmdline.h>
+#include <grub/i386/slaunch.h>
+#include <grub/i386/txt.h>
 #include <grub/linux.h>
 #include <grub/machine/kernel.h>
 
@@ -61,18 +63,23 @@ GRUB_MOD_LICENSE ("GPLv3+");
 #define ACCEPTS_PURE_TEXT 1
 #endif
 
+#define KERNEL_INFO_HEADER		"LToP"
+#define KERNEL_INFO_MIN_SIZE_TOTAL	12
+
 static grub_dl_t my_mod;
 
 static grub_size_t linux_mem_size;
 static int loaded;
 static void *prot_mode_mem;
 static grub_addr_t prot_mode_target;
+static grub_size_t prot_file_size;
 static void *initrd_mem;
 static grub_addr_t initrd_mem_target;
 static grub_size_t prot_init_space;
 static struct grub_relocator *relocator = NULL;
 static void *efi_mmap_buf;
 static grub_size_t maximal_cmdline_size;
+static struct linux_kernel_info *linux_info;
 static struct linux_kernel_params linux_params;
 static char *linux_cmdline;
 #ifdef GRUB_MACHINE_EFI
@@ -80,6 +87,7 @@ static grub_efi_uintn_t efi_mmap_size;
 #else
 static const grub_size_t efi_mmap_size = 0;
 #endif
+static struct grub_slaunch_params slparams;
 
 /* FIXME */
 #if 0
@@ -96,6 +104,8 @@ static struct idt_descriptor idt_desc =
   };
 #endif
 
+#define OFFSET_OF(x, y) ((grub_size_t)((grub_uint8_t *)(&(y)->x) - (grub_uint8_t *)(y)))
+
 static inline grub_size_t
 page_align (grub_size_t size)
 {
@@ -148,11 +158,35 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align,
 		grub_uint64_t preferred_address)
 {
   grub_err_t err;
+  grub_size_t total_size;
 
   if (prot_size == 0)
     prot_size = 1;
 
-  prot_size = page_align (prot_size);
+  if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+    {
+      prot_size = ALIGN_UP (prot_size, GRUB_TXT_PMR_ALIGN);
+
+      if (prot_size > GRUB_TXT_MLE_MAX_SIZE)
+	{
+	  err = GRUB_ERR_OUT_OF_RANGE;
+	  goto fail;
+	}
+
+      slparams.mle_ptab_size = grub_txt_get_mle_ptab_size (prot_size);
+      slparams.mle_ptab_size = ALIGN_UP (slparams.mle_ptab_size, GRUB_TXT_PMR_ALIGN);
+      /* Do not go below GRUB_TXT_PMR_ALIGN. */
+      preferred_address = (preferred_address > slparams.mle_ptab_size) ?
+			    (preferred_address - slparams.mle_ptab_size) : GRUB_TXT_PMR_ALIGN;
+      preferred_address = ALIGN_UP (preferred_address, GRUB_TXT_PMR_ALIGN);
+    }
+  else
+    {
+      prot_size = page_align (prot_size);
+      slparams.mle_ptab_size = 0;
+    }
+
+  total_size = prot_size + slparams.mle_ptab_size;
 
   /* Initialize the memory pointers with NULL for convenience.  */
   free_pages ();
@@ -174,7 +208,7 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align,
 	err = grub_relocator_alloc_chunk_align (relocator, &ch,
 						preferred_address,
 						preferred_address,
-						prot_size, 1,
+						total_size, 1,
 						GRUB_RELOCATOR_PREFERENCE_LOW,
 						1);
 	for (; err && *align + 1 > min_align; (*align)--)
@@ -182,8 +216,8 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align,
 	    grub_errno = GRUB_ERR_NONE;
 	    err = grub_relocator_alloc_chunk_align (relocator, &ch,
 						    0x1000000,
-						    0xffffffff & ~prot_size,
-						    prot_size, 1 << *align,
+						    0xffffffff & ~total_size,
+						    total_size, 1 << *align,
 						    GRUB_RELOCATOR_PREFERENCE_LOW,
 						    1);
 	  }
@@ -193,11 +227,42 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align,
     else
       err = grub_relocator_alloc_chunk_addr (relocator, &ch,
 					     preferred_address,
-					     prot_size);
+					     total_size);
     if (err)
       goto fail;
     prot_mode_mem = get_virtual_current_address (ch);
     prot_mode_target = get_physical_target_address (ch);
+
+    if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+      {
+	slparams.mle_ptab_mem = prot_mode_mem;
+	slparams.mle_ptab_target = prot_mode_target;
+
+	prot_mode_mem = (char *)prot_mode_mem + slparams.mle_ptab_size;
+	prot_mode_target += slparams.mle_ptab_size;
+
+	slparams.mle_start = prot_mode_target;
+	slparams.mle_size = prot_size;
+
+	grub_dprintf ("linux", "mle_ptab_mem = %p, mle_ptab_target = %lx, mle_ptab_size = %x\n",
+		      slparams.mle_ptab_mem, (unsigned long) slparams.mle_ptab_target,
+		      (unsigned) slparams.mle_ptab_size);
+
+	if (grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000000,
+					      0xffffffff - GRUB_SLAUNCH_TPM_EVT_LOG_SIZE,
+					      GRUB_SLAUNCH_TPM_EVT_LOG_SIZE, GRUB_PAGE_SIZE,
+					      GRUB_RELOCATOR_PREFERENCE_NONE, 1))
+	  goto fail;
+
+	slparams.tpm_evt_log_base = get_physical_target_address (ch);
+	slparams.tpm_evt_log_size = GRUB_SLAUNCH_TPM_EVT_LOG_SIZE;
+
+	grub_memset (get_virtual_current_address (ch), 0, slparams.tpm_evt_log_size);
+
+	grub_dprintf ("linux", "tpm_evt_log_base = %lx, tpm_evt_log_size = %x\n",
+		      (unsigned long) slparams.tpm_evt_log_base,
+		      (unsigned) slparams.tpm_evt_log_size);
+      }
   }
 
   grub_dprintf ("linux", "prot_mode_mem = %p, prot_mode_target = %lx, prot_size = %x\n",
@@ -491,6 +556,7 @@ grub_linux_boot (void)
   };
   grub_size_t mmap_size;
   grub_size_t cl_offset;
+  grub_size_t ap_wake_block_size = 0;
 
 #ifdef GRUB_MACHINE_IEEE1275
   {
@@ -623,6 +689,9 @@ grub_linux_boot (void)
 		(unsigned) ctx.real_size,
 		(unsigned) efi_mmap_size);
 
+  if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+    ap_wake_block_size = GRUB_MLE_AP_WAKE_BLOCK_SIZE;
+
   if (! ctx.real_mode_target)
     return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
 
@@ -630,13 +699,24 @@ grub_linux_boot (void)
     grub_relocator_chunk_t ch;
     err = grub_relocator_alloc_chunk_addr (relocator, &ch,
 					   ctx.real_mode_target,
-					   (ctx.real_size + efi_mmap_size));
+					   (ctx.real_size + efi_mmap_size +
+					    ap_wake_block_size));
     if (err)
      return err;
     real_mode_mem = get_virtual_current_address (ch);
   }
   efi_mmap_buf = (grub_uint8_t *) real_mode_mem + ctx.real_size;
 
+  if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+    {
+      slparams.ap_wake_block = ctx.real_mode_target + ctx.real_size + efi_mmap_size;
+      grub_memset ((void *) ((grub_addr_t) real_mode_mem + ctx.real_size +
+					   efi_mmap_size), 0, ap_wake_block_size);
+      grub_dprintf ("linux", "ap_wake_block = %lx, ap_wake_block_size = %lx\n",
+		    (unsigned long) slparams.ap_wake_block,
+		    (unsigned long) ap_wake_block_size);
+    }
+
   grub_dprintf ("linux", "real_mode_mem = %p\n",
                 real_mode_mem);
 
@@ -700,12 +780,33 @@ grub_linux_boot (void)
   }
 #endif
 
-  /* FIXME.  */
-  /*  asm volatile ("lidt %0" : : "m" (idt_desc)); */
-  state.ebp = state.edi = state.ebx = 0;
-  state.esi = ctx.real_mode_target;
-  state.esp = ctx.real_mode_target;
-  state.eip = ctx.params->code32_start;
+  state.edi = grub_slaunch_platform_type ();
+
+  if (state.edi == SLP_INTEL_TXT)
+    {
+      slparams.params = ctx.params;
+
+      err = grub_txt_boot_prepare (&slparams);
+
+      if (err != GRUB_ERR_NONE)
+	return err;
+
+      /* Configure relocator GETSEC[SENTER] call. */
+      state.eax = GRUB_SMX_LEAF_SENTER;
+      state.ebx = slparams.sinit_acm_base;
+      state.ecx = slparams.sinit_acm_size;
+      state.edx = 0;
+    }
+  else
+    {
+      /* FIXME.  */
+      /*  asm volatile ("lidt %0" : : "m" (idt_desc)); */
+      state.ebp = state.edi = state.ebx = 0;
+      state.esi = ctx.real_mode_target;
+      state.esp = ctx.real_mode_target;
+      state.eip = ctx.params->code32_start;
+    }
+
   return grub_relocator32_boot (relocator, state, 0);
 }
 
@@ -726,7 +827,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   grub_file_t file = 0;
   struct linux_i386_kernel_header lh;
   grub_uint8_t setup_sects;
-  grub_size_t real_size, prot_size, prot_file_size;
+  grub_size_t real_size, prot_size;
   grub_ssize_t len;
   int i;
   grub_size_t align, min_align;
@@ -839,6 +940,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
       prot_init_space = page_align (prot_size) * 3;
     }
 
+  if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+    {
+      /* PMRs require GRUB_TXT_PMR_ALIGN_SHIFT aligments. */
+      min_align = grub_max (min_align, GRUB_TXT_PMR_ALIGN_SHIFT);
+      align = grub_max (align, GRUB_TXT_PMR_ALIGN_SHIFT);
+    }
+
   if (allocate_pages (prot_size, &align,
 		      min_align, relocatable,
 		      preferred_address))
@@ -846,6 +954,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 
   grub_memset (&linux_params, 0, sizeof (linux_params));
 
+  if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+    grub_txt_setup_mle_ptab (&slparams);
+
   /*
    * The Linux 32-bit boot protocol defines the setup header end
    * to be at 0x202 + the byte value at 0x201.
@@ -872,6 +983,75 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
       goto fail;
     }
 
+  /* Read the kernel_info struct. */
+  if (grub_le_to_cpu16 (lh.version) >= 0x020f)
+    {
+      if (grub_file_seek (file, grub_le_to_cpu32 (lh.kernel_info_offset) +
+				real_size + GRUB_DISK_SECTOR_SIZE) == ((grub_off_t) -1))
+	goto fail;
+
+      linux_info = grub_malloc (KERNEL_INFO_MIN_SIZE_TOTAL);
+
+      if (!linux_info)
+	{
+	  grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate memory for kernel_info"));
+	  goto fail;
+	}
+
+      /* Load minimal kernel_info struct. */
+      if (grub_file_read (file, linux_info,
+			  KERNEL_INFO_MIN_SIZE_TOTAL) != KERNEL_INFO_MIN_SIZE_TOTAL)
+	{
+	  if (!grub_errno)
+	    grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
+	  goto fail;
+	}
+
+      if (grub_memcmp (&linux_info->header, KERNEL_INFO_HEADER, sizeof (linux_info->header)))
+	{
+	  grub_error (GRUB_ERR_BAD_OS, N_("incorrect kernel_info header"));
+	  goto fail;
+	}
+
+      linux_info->size_total = grub_le_to_cpu32 (linux_info->size_total);
+
+      linux_info = grub_realloc (linux_info, linux_info->size_total);
+
+      if (!linux_info)
+	{
+	  grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot reallocate memory for kernel_info"));
+	  goto fail;
+	}
+
+      /* Load the rest of kernel_info struct. */
+      if (grub_file_read (file, &linux_info->setup_type_max,
+			  linux_info->size_total - KERNEL_INFO_MIN_SIZE_TOTAL) !=
+				(grub_ssize_t)(linux_info->size_total - KERNEL_INFO_MIN_SIZE_TOTAL))
+	{
+	  if (!grub_errno)
+	    grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
+	  goto fail;
+	}
+
+      if (grub_slaunch_platform_type () != SLP_NONE)
+	{
+	  if (OFFSET_OF (mle_header_offset, linux_info) >=
+	      grub_le_to_cpu32 (linux_info->size))
+	    {
+	      if (!grub_errno)
+		grub_error (GRUB_ERR_BAD_OS, N_("not slaunch kernel: lack of mle_header_offset"));
+	      goto fail;
+	    }
+
+	  slparams.mle_header_offset = grub_le_to_cpu32 (linux_info->mle_header_offset);
+	}
+    }
+  else if (grub_slaunch_platform_type () != SLP_NONE)
+    {
+      grub_error (GRUB_ERR_BAD_OS, N_("not slaunch kernel: boot protocol too old"));
+      goto fail;
+    }
+
   linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR;
   linux_params.kernel_alignment = (1 << align);
   linux_params.ps_mouse = linux_params.padding11 = 0;
diff --git a/grub-core/loader/i386/slaunch.c b/grub-core/loader/i386/slaunch.c
new file mode 100644
index 000000000..72d09236b
--- /dev/null
+++ b/grub-core/loader/i386/slaunch.c
@@ -0,0 +1,194 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  Oracle and/or its affiliates.
+ *
+ *  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/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/memory.h>
+#include <grub/normal.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/cpu/relocator.h>
+#include <grub/i386/cpuid.h>
+#include <grub/i386/msr.h>
+#include <grub/i386/mmio.h>
+#include <grub/i386/slaunch.h>
+#include <grub/i386/txt.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_uint32_t slp = SLP_NONE;
+
+static void *slaunch_module = NULL;
+
+grub_uint32_t
+grub_slaunch_platform_type (void)
+{
+  return slp;
+}
+
+void *
+grub_slaunch_module (void)
+{
+  return slaunch_module;
+}
+
+static grub_err_t
+grub_cmd_slaunch (grub_command_t cmd __attribute__ ((unused)),
+		  int argc __attribute__ ((unused)),
+		  char *argv[] __attribute__ ((unused)))
+{
+  grub_uint32_t manufacturer[3];
+  grub_uint32_t eax;
+  grub_err_t err;
+
+  if (!grub_cpu_is_cpuid_supported ())
+    return grub_error (GRUB_ERR_BAD_DEVICE, N_("CPUID is unsupported"));
+
+  err = grub_cpu_is_msr_supported ();
+
+  if (err != GRUB_ERR_NONE)
+    return grub_error (err, N_("MSRs are unsupported"));
+
+  grub_cpuid (0, eax, manufacturer[0], manufacturer[2], manufacturer[1]);
+
+  if (!grub_memcmp (manufacturer, "GenuineIntel", 12))
+    {
+      err = grub_txt_init ();
+
+      if (err != GRUB_ERR_NONE)
+	return err;
+
+      slp = SLP_INTEL_TXT;
+    }
+  else
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("CPU is unsupported"));
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_slaunch_module (grub_command_t cmd __attribute__ ((unused)),
+			 int argc, char *argv[])
+{
+  grub_file_t file;
+  grub_ssize_t size;
+
+  if (!argc)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+
+  if (slp == SLP_NONE)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("secure launch not enabled"));
+
+  grub_errno = GRUB_ERR_NONE;
+
+  file = grub_file_open (argv[0], GRUB_FILE_TYPE_SLAUNCH_MODULE);
+
+  if (file == NULL)
+    return grub_errno;
+
+  size = grub_file_size (file);
+
+  if (!size)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("file size is zero"));
+      goto fail;
+    }
+
+  slaunch_module = grub_malloc (size);
+
+  if (slaunch_module == NULL)
+    goto fail;
+
+  if (grub_file_read (file, slaunch_module, size) != size)
+    {
+      if (grub_errno == GRUB_ERR_NONE)
+	grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file: %s"),
+		    argv[0]);
+      goto fail;
+    }
+
+  if (slp == SLP_INTEL_TXT)
+    {
+      if (!grub_txt_is_sinit_acmod (slaunch_module, size))
+	{
+	  grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("it does not look like SINIT ACM"));
+	  goto fail;
+	}
+
+      if (!grub_txt_acmod_match_platform (slaunch_module))
+	{
+	  grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("SINIT ACM does not match platform"));
+	  goto fail;
+	}
+    }
+
+  grub_file_close (file);
+
+  return GRUB_ERR_NONE;
+
+ fail:
+  grub_error_push ();
+
+  grub_free (slaunch_module);
+  grub_file_close (file);
+
+  slaunch_module = NULL;
+
+  grub_error_pop ();
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_slaunch_state (grub_command_t cmd __attribute__ ((unused)),
+			int argc __attribute__ ((unused)),
+			char *argv[] __attribute__ ((unused)))
+{
+  if (slp == SLP_NONE)
+    grub_printf ("Secure launcher: Disabled\n");
+  else if (slp == SLP_INTEL_TXT)
+    {
+      grub_printf ("Secure launcher: Intel TXT\n");
+      grub_txt_state_show ();
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd_slaunch, cmd_slaunch_module, cmd_slaunch_state;
+
+GRUB_MOD_INIT (slaunch)
+{
+  cmd_slaunch = grub_register_command ("slaunch", grub_cmd_slaunch,
+				       NULL, N_("Enable secure launcher"));
+  cmd_slaunch_module = grub_register_command ("slaunch_module", grub_cmd_slaunch_module,
+					      NULL, N_("Secure launcher module command"));
+  cmd_slaunch_state = grub_register_command ("slaunch_state", grub_cmd_slaunch_state,
+					     NULL, N_("Display secure launcher state"));
+}
+
+GRUB_MOD_FINI (slaunch)
+{
+  grub_unregister_command (cmd_slaunch_state);
+  grub_unregister_command (cmd_slaunch_module);
+  grub_unregister_command (cmd_slaunch);
+
+  if (slp == SLP_INTEL_TXT)
+    grub_txt_shutdown ();
+}
diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c
index e64ed08f5..e586967b0 100644
--- a/grub-core/loader/i386/xnu.c
+++ b/grub-core/loader/i386/xnu.c
@@ -28,6 +28,7 @@
 #include <grub/i386/cpuid.h>
 #include <grub/efi/api.h>
 #include <grub/i386/pit.h>
+#include <grub/i386/slaunch.h>
 #include <grub/misc.h>
 #include <grub/charset.h>
 #include <grub/term.h>
@@ -807,6 +808,7 @@ grub_xnu_boot_resume (void)
 {
   struct grub_relocator32_state state;
 
+  state.edi = SLP_NONE;
   state.esp = grub_xnu_stack;
   state.ebp = grub_xnu_stack;
   state.eip = grub_xnu_entry_point;
@@ -1134,6 +1136,7 @@ grub_xnu_boot (void)
   grub_autoefi_set_virtual_address_map (memory_map_size, descriptor_size,
 					descriptor_version, memory_map);
 
+  state.edi = SLP_NONE;
   state.eip = grub_xnu_entry_point;
   state.eax = grub_xnu_arg1;
   state.esp = grub_xnu_stack;
diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index 4a98d7082..6efb59e8f 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -50,6 +50,9 @@
 #include <grub/video.h>
 #include <grub/memory.h>
 #include <grub/i18n.h>
+#if defined (__i386__) || defined (__x86_64__)
+#include <grub/i386/slaunch.h>
+#endif
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -161,6 +164,8 @@ efi_boot (struct grub_relocator *rel __attribute__ ((unused)),
 static void
 normal_boot (struct grub_relocator *rel, struct grub_relocator32_state state)
 {
+  state.edi = SLP_NONE;
+
   grub_relocator32_boot (rel, state, 0);
 }
 #else
diff --git a/include/grub/file.h b/include/grub/file.h
index 31567483c..f08fcda74 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -128,6 +128,9 @@ enum grub_file_type
 
     GRUB_FILE_TYPE_VERIFY_SIGNATURE,
 
+    /* Secure Launch module.  */
+    GRUB_FILE_TYPE_SLAUNCH_MODULE,
+
     GRUB_FILE_TYPE_MASK = 0xffff,
 
     /* --skip-sig is specified.  */
diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
index 6aea73ddb..fade29fab 100644
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -152,6 +152,17 @@ struct linux_i386_kernel_header
   grub_uint64_t pref_address;
   grub_uint32_t init_size;
   grub_uint32_t handover_offset;
+  grub_uint32_t kernel_info_offset;
+} GRUB_PACKED;
+
+struct linux_kernel_info
+{
+  grub_uint32_t header;
+  grub_uint32_t size;
+  grub_uint32_t size_total;
+  grub_uint32_t setup_type_max;
+  grub_uint32_t mle_header_offset;
+  grub_uint8_t  var_len_data[0];
 } GRUB_PACKED;
 
 /* Boot parameters for Linux based on 2.6.12. This is used by the setup
@@ -329,9 +340,10 @@ struct linux_kernel_params
   grub_uint64_t pref_address;
   grub_uint32_t init_size;
   grub_uint32_t handover_offset;
+  grub_uint32_t kernel_info_offset;
   /* Linux setup header copy - END. */
 
-  grub_uint8_t _pad7[40];
+  grub_uint8_t _pad7[36];
   grub_uint32_t edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];	/* 290 */
   struct grub_e820_mmap e820_map[(0x400 - 0x2d0) / 20];	/* 2d0 */
 } GRUB_PACKED;
diff --git a/include/grub/i386/slaunch.h b/include/grub/i386/slaunch.h
new file mode 100644
index 000000000..e5eebd58c
--- /dev/null
+++ b/include/grub/i386/slaunch.h
@@ -0,0 +1,56 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  Oracle and/or its affiliates.
+ *
+ *  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/>.
+ *
+ *  Main secure launch definitions header file.
+ */
+
+#ifndef GRUB_I386_SLAUNCH_H
+#define GRUB_I386_SLAUNCH_H 1
+
+/* Secure launch platform types. */
+#define SLP_NONE	0
+#define SLP_INTEL_TXT	1
+
+#define GRUB_SLAUNCH_TPM_EVT_LOG_SIZE	(8 * GRUB_PAGE_SIZE)
+
+#ifndef ASM_FILE
+
+#include <grub/i386/linux.h>
+#include <grub/types.h>
+
+struct grub_slaunch_params
+{
+  struct linux_kernel_params *params;
+  grub_uint32_t mle_start;
+  grub_uint32_t mle_size;
+  void *mle_ptab_mem;
+  grub_uint64_t mle_ptab_target;
+  grub_uint32_t mle_ptab_size;
+  grub_uint32_t mle_header_offset;
+  grub_uint64_t ap_wake_block;
+  grub_uint32_t sinit_acm_base;
+  grub_uint32_t sinit_acm_size;
+  grub_uint64_t tpm_evt_log_base;
+  grub_uint32_t tpm_evt_log_size;
+};
+
+extern grub_uint32_t grub_slaunch_platform_type (void);
+extern void *grub_slaunch_module (void);
+
+#endif /* ASM_FILE */
+
+#endif /* GRUB_I386_SLAUNCH_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher
  2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
                   ` (17 preceding siblings ...)
  2020-05-04 23:21 ` [GRUB PATCH RFC 18/18] i386/slaunch: Add secure launch framework and commands Daniel Kiper
@ 2020-05-05 14:38 ` Lukasz Hawrylko
  2020-05-07 11:06   ` Daniel Kiper
  18 siblings, 1 reply; 36+ messages in thread
From: Lukasz Hawrylko @ 2020-05-05 14:38 UTC (permalink / raw)
  To: Daniel Kiper, grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, michal.zygowski, mjg59, phcoder, pirot.krol,
	pjones, ross.philipson

On Tue, 2020-05-05 at 01:21 +0200, Daniel Kiper wrote:
> Hi,
> 
> This is an RFC patchset for the GRUB introducing the Intel TXT secure launcher.
> This is a part of larger work known as the TrenchBoot. Patchset can be split
> into two distinct parts:
>   - 01-12: preparatory patches,
>   - 13-18: the Intel TXT secure launcher itself.
> 
> The initial implementation of the Intel TXT secure launcher works. However,
> there are still some missing bits and pieces, e.g.:
>   - SINIT ACM auto loader,
>   - lack of RMRR support,
>   - lack of support for MLEs larger than 1 GiB,
>   - lack of TPM 1.2 support.
>   - various fixes and cleanups.
> 
> Commands introduced by this patchset: tpm_type, slaunch, slaunch_module (not
> required on server platforms) and slaunch_state (useful for checking platform
> configuration and state; based on tboot's txt-stat).
> 
> Daniel
> 

Hi Daniel

Your patch looks promising, however I have few concerns.

In OS-MLE table there is a buffer for TPM event log, however I see that
you are not using it, but instead allocate space somewhere in the
memory. I am just wondering if, from security perspective, it will be
better to use memory from TXT heap for event log, like we do in TBOOT.

There is a function that verifies if platform is TXT capable
-grub_txt_verify_platform(), it only checks SMX and GETSEC features.
Although BIOS should enforce both VMX and VT-d enabled when enabling
TXT, I think that adding these check here as redundancy may be a good
idea. The same situation is with TPM presence.

I suggest to add possibility to skip TXT launch when last boot ended
with TXT error. This option can avoid boot loops when something goes
wrong.

How will you read LCP from storage? I see that there is slaunch_module
command that currently you are using only for loading SINIT. In the
future it can be expanded to support LCP file too, what do you think?

Do not forget to apply changes required by latest Intel's platforms, you
should check following commits in TBOOT's repository: 2f03b57ffdba,
fe2dddd742dc.

Lukasz 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 12/18] i386/efi: Report UEFI Secure Boot status to the Linux kernel
  2020-05-04 23:21 ` [GRUB PATCH RFC 12/18] i386/efi: Report UEFI Secure Boot status to the Linux kernel Daniel Kiper
@ 2020-05-05 17:29   ` Matthew Garrett
  2020-05-06 13:33     ` Daniel Kiper
  0 siblings, 1 reply; 36+ messages in thread
From: Matthew Garrett @ 2020-05-05 17:29 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: The development of GNU GRUB, Linux Kernel Mailing List,
	trenchboot-devel, the arch/x86 maintainers, alexander.burmashev,
	Andrew Cooper, Ard Biesheuvel, Daniel P. Smith, eric.snowberg,
	Javier Martinez Canillas, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski,
	Vladimir 'phcoder' Serbinenko, pirot.krol, Peter Jones,
	Ross Philipson

On Mon, May 4, 2020 at 4:25 PM Daniel Kiper <daniel.kiper@oracle.com> wrote:
>
> Otherwise the kernel does not know its state and cannot enable various
> security features depending on UEFI Secure Boot.

I think this needs more context. If the kernel is loaded via the EFI
boot stub, the kernel is aware of the UEFI secure boot state. Why
duplicate this functionality in order to avoid the EFI stub?

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 12/18] i386/efi: Report UEFI Secure Boot status to the Linux kernel
  2020-05-05 17:29   ` Matthew Garrett
@ 2020-05-06 13:33     ` Daniel Kiper
  2020-05-06 18:36       ` Matthew Garrett
  0 siblings, 1 reply; 36+ messages in thread
From: Daniel Kiper @ 2020-05-06 13:33 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: The development of GNU GRUB, Linux Kernel Mailing List,
	trenchboot-devel, the arch/x86 maintainers, alexander.burmashev,
	Andrew Cooper, Ard Biesheuvel, Daniel P. Smith, eric.snowberg,
	Javier Martinez Canillas, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski,
	Vladimir 'phcoder' Serbinenko, pirot.krol, Peter Jones,
	Ross Philipson

On Tue, May 05, 2020 at 10:29:05AM -0700, Matthew Garrett wrote:
> On Mon, May 4, 2020 at 4:25 PM Daniel Kiper <daniel.kiper@oracle.com> wrote:
> >
> > Otherwise the kernel does not know its state and cannot enable various
> > security features depending on UEFI Secure Boot.
>
> I think this needs more context. If the kernel is loaded via the EFI
> boot stub, the kernel is aware of the UEFI secure boot state. Why
> duplicate this functionality in order to avoid the EFI stub?

It seems to me that this issue was discussed here [1] and here [2].
So, if you want me to improve the commit message I am OK with that.

Additionally, FYI I am not happy with that patch too. So, if somebody
has better idea how to do that then I am happy to discuss it here.

Daniel

[1] https://lkml.org/lkml/2020/3/25/982
[2] https://lkml.org/lkml/2020/3/26/985

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 12/18] i386/efi: Report UEFI Secure Boot status to the Linux kernel
  2020-05-06 13:33     ` Daniel Kiper
@ 2020-05-06 18:36       ` Matthew Garrett
  2020-05-07 10:46         ` Daniel Kiper
  0 siblings, 1 reply; 36+ messages in thread
From: Matthew Garrett @ 2020-05-06 18:36 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: The development of GNU GRUB, Linux Kernel Mailing List,
	trenchboot-devel, the arch/x86 maintainers, alexander.burmashev,
	Andrew Cooper, Ard Biesheuvel, Daniel P. Smith, eric.snowberg,
	Javier Martinez Canillas, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski,
	Vladimir 'phcoder' Serbinenko, pirot.krol, Peter Jones,
	Ross Philipson

On Wed, May 6, 2020 at 6:33 AM Daniel Kiper <daniel.kiper@oracle.com> wrote:
>
> On Tue, May 05, 2020 at 10:29:05AM -0700, Matthew Garrett wrote:
> > On Mon, May 4, 2020 at 4:25 PM Daniel Kiper <daniel.kiper@oracle.com> wrote:
> > >
> > > Otherwise the kernel does not know its state and cannot enable various
> > > security features depending on UEFI Secure Boot.
> >
> > I think this needs more context. If the kernel is loaded via the EFI
> > boot stub, the kernel is aware of the UEFI secure boot state. Why
> > duplicate this functionality in order to avoid the EFI stub?
>
> It seems to me that this issue was discussed here [1] and here [2].
> So, if you want me to improve the commit message I am OK with that.

Yes, I think just providing an explanation for why it's currently
necessary for you to duplicate this is reasonable.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 12/18] i386/efi: Report UEFI Secure Boot status to the Linux kernel
  2020-05-06 18:36       ` Matthew Garrett
@ 2020-05-07 10:46         ` Daniel Kiper
  0 siblings, 0 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-07 10:46 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: The development of GNU GRUB, Linux Kernel Mailing List,
	trenchboot-devel, the arch/x86 maintainers, alexander.burmashev,
	Andrew Cooper, Ard Biesheuvel, Daniel P. Smith, eric.snowberg,
	Javier Martinez Canillas, kanth.ghatraju, konrad.wilk,
	krystian.hebel, lukasz.hawrylko, michal.zygowski,
	Vladimir 'phcoder' Serbinenko, pirot.krol, Peter Jones,
	Ross Philipson

On Wed, May 06, 2020 at 11:36:49AM -0700, Matthew Garrett wrote:
> On Wed, May 6, 2020 at 6:33 AM Daniel Kiper <daniel.kiper@oracle.com> wrote:
> >
> > On Tue, May 05, 2020 at 10:29:05AM -0700, Matthew Garrett wrote:
> > > On Mon, May 4, 2020 at 4:25 PM Daniel Kiper <daniel.kiper@oracle.com> wrote:
> > > >
> > > > Otherwise the kernel does not know its state and cannot enable various
> > > > security features depending on UEFI Secure Boot.
> > >
> > > I think this needs more context. If the kernel is loaded via the EFI
> > > boot stub, the kernel is aware of the UEFI secure boot state. Why
> > > duplicate this functionality in order to avoid the EFI stub?
> >
> > It seems to me that this issue was discussed here [1] and here [2].
> > So, if you want me to improve the commit message I am OK with that.
>
> Yes, I think just providing an explanation for why it's currently
> necessary for you to duplicate this is reasonable.

Sure, will do!

Daniel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher
  2020-05-05 14:38 ` [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Lukasz Hawrylko
@ 2020-05-07 11:06   ` Daniel Kiper
  2020-05-13 13:47     ` Lukasz Hawrylko
  2020-06-01 15:32     ` Daniel P. Smith
  0 siblings, 2 replies; 36+ messages in thread
From: Daniel Kiper @ 2020-05-07 11:06 UTC (permalink / raw)
  To: Lukasz Hawrylko
  Cc: grub-devel, linux-kernel, trenchboot-devel, x86,
	alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, michal.zygowski, mjg59, phcoder, piotr.krol,
	pjones, ross.philipson

Hi Łukasz,

On Tue, May 05, 2020 at 04:38:02PM +0200, Lukasz Hawrylko wrote:
> On Tue, 2020-05-05 at 01:21 +0200, Daniel Kiper wrote:
> > Hi,
> >
> > This is an RFC patchset for the GRUB introducing the Intel TXT secure launcher.
> > This is a part of larger work known as the TrenchBoot. Patchset can be split
> > into two distinct parts:
> >   - 01-12: preparatory patches,
> >   - 13-18: the Intel TXT secure launcher itself.
> >
> > The initial implementation of the Intel TXT secure launcher works. However,
> > there are still some missing bits and pieces, e.g.:
> >   - SINIT ACM auto loader,
> >   - lack of RMRR support,
> >   - lack of support for MLEs larger than 1 GiB,
> >   - lack of TPM 1.2 support.
> >   - various fixes and cleanups.
> >
> > Commands introduced by this patchset: tpm_type, slaunch, slaunch_module (not
> > required on server platforms) and slaunch_state (useful for checking platform
> > configuration and state; based on tboot's txt-stat).
> >
> > Daniel
> >
>
> Hi Daniel
>
> Your patch looks promising, however I have few concerns.

Below I will be referring to the Intel Trusted Execution Technology
(Intel TXT), Software Development Guide, December 2019, Revision 016.
So, the latest and greatest...

> In OS-MLE table there is a buffer for TPM event log, however I see that
> you are not using it, but instead allocate space somewhere in the

I think that this part requires more discussion. In my opinion we should
have this region dynamically allocated because it gives us more flexibility.
Of course there is a question about the size of this buffer too. I am
not sure about that because I have not checked yet how many log entries
are created by the SINIT ACM. Though probably it should not be large...

> memory. I am just wondering if, from security perspective, it will be
> better to use memory from TXT heap for event log, like we do in TBOOT.

Appendix F, TPM Event Log, has following sentence: There are no
requirements for event log to be in DMA protected memory – SINIT will
not enforce it.

I was thinking about it and it seems to me that the TPM event log does
not require any special protections. Any changes in it can be quickly
detected by comparing hashes with the TPM PCRs. Does not it?

> There is a function that verifies if platform is TXT capable
> -grub_txt_verify_platform(), it only checks SMX and GETSEC features.
> Although BIOS should enforce both VMX and VT-d enabled when enabling
> TXT, I think that adding these check here as redundancy may be a good

The TXT spec has the following pseudocode:

  //
  // Intel TXT detection
  // Execute on all logical processors for compatibility with
  // multiple processor systems
  //
  1. CPUID(EAX=1);
  2. IF (SMX not supported) OR (VMX not supported) {
  3. Fail measured environment startup;
  4. }

However, a few lines above you can find this:

  Lines 1 - 4: Before attempting to launch the measured environment, the
  system software should check that all logical processors support VMX and
  SMX (the check for VMX support is not necessary if the environment to be
  launched will not use VMX).

Hence, AIUI, I am allowed to check SMX only. And I do not think that the
bootloader should enforce VMX. If the kernel wants VMX then it should
check the platform config. The booloader should just look for features
which are really required to properly execute GETSEC[SENTER].

> idea. The same situation is with TPM presence.

The TPM presence is checked in init_txt_heap(). However, we can do it earlier.

> I suggest to add possibility to skip TXT launch when last boot ended
> with TXT error. This option can avoid boot loops when something goes
> wrong.

grub_txt_verify_platform() checks TXT_RESET.STS bit and fails if it is
set. This produces an error during boot. Well, but it does not prevent
it... :-( Probably I have to fix it...

> How will you read LCP from storage? I see that there is slaunch_module
> command that currently you are using only for loading SINIT. In the
> future it can be expanded to support LCP file too, what do you think?

I think that we should add e.g. slaunch_lcp command and do not overload
slaunch_module command. However, I am not planning support for it in the
near feature. I mean I will not be working on it...

> Do not forget to apply changes required by latest Intel's platforms, you
> should check following commits in TBOOT's repository: 2f03b57ffdba,
> fe2dddd742dc.

Sure, will take that into account.

Thank you for your comments,

Daniel

PS By the way, I found an issue in TXT spec. TXT.VER.FSBIF refers to
   TXT.VER.EMIF which does not exist in spec. I suppose that it is
   remnant from previous TXT spec versions. It seems to me that it
   should be changed to TXT.VER.QPIIF. TXT.VER.QPIIF descriptions
   properly, IMO, refers back to TXT.VER.FSBIF.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher
  2020-05-07 11:06   ` Daniel Kiper
@ 2020-05-13 13:47     ` Lukasz Hawrylko
  2020-06-01 15:32     ` Daniel P. Smith
  1 sibling, 0 replies; 36+ messages in thread
From: Lukasz Hawrylko @ 2020-05-13 13:47 UTC (permalink / raw)
  To: The development of GNU GRUB
  Cc: linux-kernel, trenchboot-devel, x86, alexander.burmashev,
	andrew.cooper3, ard.biesheuvel, dpsmith, eric.snowberg, javierm,
	kanth.ghatraju, konrad.wilk, krystian.hebel, michal.zygowski,
	mjg59, phcoder, piotr.krol, pjones, ross.philipson

Hi Daniel

On Thu, 2020-05-07 at 13:06 +0200, Daniel Kiper wrote:
> > There is a function that verifies if platform is TXT capable
> > -grub_txt_verify_platform(), it only checks SMX and GETSEC features.
> > Although BIOS should enforce both VMX and VT-d enabled when enabling
> > TXT, I think that adding these check here as redundancy may be a good
> 
> The TXT spec has the following pseudocode:
> 
>   //
>   // Intel TXT detection
>   // Execute on all logical processors for compatibility with
>   // multiple processor systems
>   //
>   1. CPUID(EAX=1);
>   2. IF (SMX not supported) OR (VMX not supported) {
>   3. Fail measured environment startup;
>   4. }
> 
> However, a few lines above you can find this:
> 
>   Lines 1 - 4: Before attempting to launch the measured environment, the
>   system software should check that all logical processors support VMX and
>   SMX (the check for VMX support is not necessary if the environment to be
>   launched will not use VMX).
> 
> Hence, AIUI, I am allowed to check SMX only. And I do not think that the
> bootloader should enforce VMX. If the kernel wants VMX then it should
> check the platform config. The booloader should just look for features
> which are really required to properly execute GETSEC[SENTER].

I agree with you that spec does not clearly define if VMX is required or
not. In theory you can use TXT without VMX, however this is highly
impractical because in that configuration it is impossible to use STM to
protect MLE from SMI handler as STM feature requires VMX.

All real-life MLE implementations should use STM to be compliant with
TXT idea that MLE does not have a security dependency on the pre-
existing software environment. You can find more information about STM
here: 

https://software.intel.com/content/dam/develop/external/us/en/documents/stm-user-guide-001-819978.pdf

Anyway, I have asked TXT spec owner to clarify VMX situation in next
document revision.

> 
> PS By the way, I found an issue in TXT spec. TXT.VER.FSBIF refers to
>    TXT.VER.EMIF which does not exist in spec. I suppose that it is
>    remnant from previous TXT spec versions. It seems to me that it
>    should be changed to TXT.VER.QPIIF. TXT.VER.QPIIF descriptions
>    properly, IMO, refers back to TXT.VER.FSBIF.

Yes, this is remnant from old document versions, thank you for finding
that issue. Here are changes that will go to next revision:

 * register 0x100 (TXT.VER.FSBIF) does not exist for many years and will
   be removed from TXT spec
 * register 0x200 is called TXT.VER.EMIF and indicates if chipset is
   debug of production fused

Thanks,
Lukasz


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 15/18] i386/txt: Add Intel TXT core implementation
  2020-05-04 23:21 ` [GRUB PATCH RFC 15/18] i386/txt: Add Intel TXT core implementation Daniel Kiper
@ 2020-05-22 13:24   ` Krystian Hebel
  2020-06-01 14:16     ` Ross Philipson
  0 siblings, 1 reply; 36+ messages in thread
From: Krystian Hebel @ 2020-05-22 13:24 UTC (permalink / raw)
  To: Daniel Kiper, grub-devel, linux-kernel, trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	lukasz.hawrylko, michal.zygowski, mjg59, phcoder, pirot.krol,
	pjones, ross.philipson


On 05.05.2020 01:21, Daniel Kiper wrote:
> +static grub_err_t
> +init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header *sinit)
> +{
> +  grub_uint8_t *txt_heap;
> +  grub_uint32_t os_sinit_data_ver, sinit_caps;
> +  grub_uint64_t *size;
> +  struct grub_txt_os_mle_data *os_mle_data;
> +  struct grub_txt_os_sinit_data *os_sinit_data;
> +  struct grub_txt_heap_end_element *heap_end_element;
> +  struct grub_txt_heap_event_log_pointer2_1_element *heap_event_log_pointer2_1_element;
> +#ifdef GRUB_MACHINE_EFI
> +  struct grub_acpi_rsdp_v20 *rsdp;
> +#endif
> +
> +  /* BIOS data already verified in grub_txt_verify_platform(). */
> +
> +  txt_heap = grub_txt_get_heap ();
> +
> +  /* OS/loader to MLE data. */
> +
> +  os_mle_data = grub_txt_os_mle_data_start (txt_heap);
> +  size = (grub_uint64_t *) ((grub_addr_t) os_mle_data - sizeof (grub_uint64_t));
There is 'grub_txt_os_mle_data_size()' in previous patch, it would look 
better.
> +  *size = sizeof (*os_mle_data) + sizeof (grub_uint64_t);
> +
> +  grub_memset (os_mle_data, 0, sizeof (*os_mle_data));
> +
> +  os_mle_data->version = GRUB_SL_OS_MLE_STRUCT_VERSION;
> +  os_mle_data->zero_page_addr = (grub_uint32_t)(grub_addr_t) slparams->params;
> +  os_mle_data->saved_misc_enable_msr = grub_rdmsr (GRUB_MSR_X86_MISC_ENABLE);
> +
> +  os_mle_data->ap_wake_block = slparams->ap_wake_block;
> +
> +  save_mtrrs (os_mle_data);
> +
> +  /* OS/loader to SINIT data. */
> +
> +  os_sinit_data_ver = grub_txt_supported_os_sinit_data_ver (sinit);
> +
> +  if (os_sinit_data_ver < OS_SINIT_DATA_MIN_VER)
> +    return grub_error (GRUB_ERR_BAD_DEVICE,
> +		       N_("unsupported OS to SINIT data version in SINIT ACM: %d"
> +		       " expected >= %d"), os_sinit_data_ver, OS_SINIT_DATA_MIN_VER);
> +
> +  os_sinit_data = grub_txt_os_sinit_data_start (txt_heap);
> +  size = (grub_uint64_t *) ((grub_addr_t) os_sinit_data - sizeof (grub_uint64_t));
Ditto
> +
> +  *size = sizeof(grub_uint64_t) + sizeof (struct grub_txt_os_sinit_data) +
> +	  sizeof (struct grub_txt_heap_end_element);
> +
> +  if (grub_get_tpm_ver () == GRUB_TPM_12)
> +    *size += sizeof (struct grub_txt_heap_tpm_event_log_element);
> +  else if (grub_get_tpm_ver () == GRUB_TPM_20)
> +    *size += sizeof (struct grub_txt_heap_event_log_pointer2_1_element);
> +  else
> +    return grub_error (GRUB_ERR_BAD_DEVICE, N_("unsupported TPM version"));
> +
> +  grub_memset (os_sinit_data, 0, *size);
> +
> +#ifdef GRUB_MACHINE_EFI
> +  rsdp = grub_acpi_get_rsdpv2 ();
> +
> +  if (rsdp == NULL)
> +    return grub_printf ("WARNING: ACPI RSDP 2.0 missing\n");
> +
> +  os_sinit_data->efi_rsdt_ptr = (grub_uint64_t)(grub_addr_t) rsdp;
> +#endif
> +
> +  os_sinit_data->mle_ptab = slparams->mle_ptab_target;
> +  os_sinit_data->mle_size = slparams->mle_size;
> +
> +  os_sinit_data->mle_hdr_base = slparams->mle_header_offset;
> +
> +  /* TODO: Check low PMR with RMRR. Look at relevant tboot code too. */
> +  /* TODO: Kernel should not allocate any memory outside of PMRs regions!!! */
> +  os_sinit_data->vtd_pmr_lo_base = 0;
> +  os_sinit_data->vtd_pmr_lo_size = ALIGN_DOWN (grub_mmap_get_highest (0x100000000),
> +					       GRUB_TXT_PMR_ALIGN);
> +
> +  os_sinit_data->vtd_pmr_hi_base = ALIGN_UP (grub_mmap_get_lowest (0x100000000),
> +					     GRUB_TXT_PMR_ALIGN);
> +  os_sinit_data->vtd_pmr_hi_size = ALIGN_DOWN (grub_mmap_get_highest (0xffffffffffffffff),
> +					       GRUB_TXT_PMR_ALIGN);
> +  os_sinit_data->vtd_pmr_hi_size -= os_sinit_data->vtd_pmr_hi_base;
Could it be done with just one PMR, from 0 to top of memory, or would 
TXT complain?
> +
> +  grub_dprintf ("slaunch",
> +		"vtd_pmr_lo_base: 0x%" PRIxGRUB_UINT64_T " vtd_pmr_lo_size: 0x%"
> +		PRIxGRUB_UINT64_T " vtd_pmr_hi_base: 0x%" PRIxGRUB_UINT64_T
> +		" vtd_pmr_hi_size: 0x%" PRIxGRUB_UINT64_T "\n",
> +		os_sinit_data->vtd_pmr_lo_base, os_sinit_data->vtd_pmr_lo_size,
> +		os_sinit_data->vtd_pmr_hi_base, os_sinit_data->vtd_pmr_hi_size);
> +
>
> <snip>
>
> +/*
> + * The MLE page tables have to be below the MLE and have no special regions in
> + * between them and the MLE (this is a bit of an unwritten rule).
> + * 20 pages are carved out of memory below the MLE. That leave 18 page table
> + * pages that can cover up to 36M .
> + * can only contain 4k pages
> + *
> + * TODO: TXT Spec p.32; List section name and number with PT MLE requirments here.
> + *
> + * TODO: This function is not able to cover MLEs larger than 1 GiB. Fix it!!!
> + * After fixing inrease GRUB_TXT_MLE_MAX_SIZE too.
> + */

What do you mean by "special regions"? In TXT spec it is written that 
there may be no holes
in the virtual address space:

"There may not be any invalid (not-present) page table entries after the 
first valid
entry (i.e. there may not be any gaps in the MLE’s linear address space)."

Also that spec:
"A breadth-first search of page tables must produce increasing physical 
addresses."

Maybe I misunderstood, but does it mean that the paging structures 
themselves cannot
be mapped? Or does it apply to the page tables only, not to the 
addresses of pages in PTEs?

> +void
> +grub_txt_setup_mle_ptab (struct grub_slaunch_params *slparams)
> +{
> +  grub_uint8_t *pg_dir, *pg_dir_ptr_tab = slparams->mle_ptab_mem, *pg_tab;
IMHO using 'grub_uint64_t' would result in less type casting and cleaner 
code below.
> +  grub_uint32_t mle_off = 0, pd_off = 0;
> +  grub_uint64_t *pde, *pte;
> +
> +  grub_memset (pg_dir_ptr_tab, 0, slparams->mle_ptab_size);
> +
> +  pg_dir         = pg_dir_ptr_tab + GRUB_PAGE_SIZE;
> +  pg_tab         = pg_dir + GRUB_PAGE_SIZE;
> +
> +  /* Only use first entry in page dir ptr table */
> +  *(grub_uint64_t *)pg_dir_ptr_tab = MAKE_PT_MLE_ENTRY(pg_dir);
> +
> +  /* Start with first entry in page dir */
> +  *(grub_uint64_t *)pg_dir = MAKE_PT_MLE_ENTRY(pg_tab);
> +
> +  pte = (grub_uint64_t *)pg_tab;
> +  pde = (grub_uint64_t *)pg_dir;
> +
> +  do
> +    {
> +      *pte = MAKE_PT_MLE_ENTRY(slparams->mle_start + mle_off);
> +
> +      pte++;
> +      mle_off += GRUB_PAGE_SIZE;
> +
> +      if (!(++pd_off % 512))
> +        {
> +          /* Break if we don't need any additional page entries */
> +          if (mle_off >= slparams->mle_size)
> +            break;
> +          pde++;
> +          *pde = MAKE_PT_MLE_ENTRY(pte);
> +        }
> +    } while (mle_off < slparams->mle_size);
> +}
>
> <snip>
>
> +grub_err_t
> +grub_txt_boot_prepare (struct grub_slaunch_params *slparams)
> +{
> +  grub_err_t err;
> +  struct grub_txt_mle_header *mle_header;
> +  struct grub_txt_acm_header *sinit_base;
> +
> +  sinit_base = grub_txt_sinit_select (grub_slaunch_module ());
> +
> +  if (sinit_base == NULL)
> +    return grub_errno;
> +
> +  err = init_txt_heap (slparams, sinit_base);
> +
> +  if (err != GRUB_ERR_NONE)
> +    return err;
> +
> +  /* Update the MLE header. */
> +  mle_header = (struct grub_txt_mle_header *)(grub_addr_t) (slparams->mle_start + slparams->mle_header_offset);
> +  mle_header->first_valid_page = 0;
> +  mle_header->mle_end = slparams->mle_size;
> +
> +  slparams->sinit_acm_base = (grub_uint32_t)(grub_addr_t) sinit_base;
> +  slparams->sinit_acm_size = sinit_base->size * 4;
> +
> +  grub_tpm_relinquish_lcl (0);
> +
> +  err = set_mtrrs_for_acmod (sinit_base);
> +  if (err)
> +    return grub_error (err, N_("secure launch failed to set MTRRs for ACM"));
> +
> +  err = grub_txt_prepare_cpu ();
> +  if ( err )
> +    return err;
> +
> +  if (!(grub_rdmsr (GRUB_MSR_X86_APICBASE) & GRUB_MSR_X86_APICBASE_BSP))
> +    return grub_error (GRUB_ERR_BAD_DEVICE, N_("secure launch must run on BSP"));
This test should be the first one, before messing with TPM and MTTRs.
> +
> +  return GRUB_ERR_NONE;
> +}
Best regards,

-- 
Krystian Hebel
Firmware Engineer
https://3mdeb.com | @3mdeb_com


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 15/18] i386/txt: Add Intel TXT core implementation
  2020-05-22 13:24   ` Krystian Hebel
@ 2020-06-01 14:16     ` Ross Philipson
  0 siblings, 0 replies; 36+ messages in thread
From: Ross Philipson @ 2020-06-01 14:16 UTC (permalink / raw)
  To: Krystian Hebel, Daniel Kiper, grub-devel, linux-kernel,
	trenchboot-devel, x86
  Cc: alexander.burmashev, andrew.cooper3, ard.biesheuvel, dpsmith,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	lukasz.hawrylko, michal.zygowski, mjg59, phcoder, pirot.krol,
	pjones

On 5/22/20 9:24 AM, Krystian Hebel wrote:
> 
> On 05.05.2020 01:21, Daniel Kiper wrote:
>> +static grub_err_t
>> +init_txt_heap (struct grub_slaunch_params *slparams, struct
>> grub_txt_acm_header *sinit)
>> +{
>> +  grub_uint8_t *txt_heap;
>> +  grub_uint32_t os_sinit_data_ver, sinit_caps;
>> +  grub_uint64_t *size;
>> +  struct grub_txt_os_mle_data *os_mle_data;
>> +  struct grub_txt_os_sinit_data *os_sinit_data;
>> +  struct grub_txt_heap_end_element *heap_end_element;
>> +  struct grub_txt_heap_event_log_pointer2_1_element
>> *heap_event_log_pointer2_1_element;
>> +#ifdef GRUB_MACHINE_EFI
>> +  struct grub_acpi_rsdp_v20 *rsdp;
>> +#endif
>> +
>> +  /* BIOS data already verified in grub_txt_verify_platform(). */
>> +
>> +  txt_heap = grub_txt_get_heap ();
>> +
>> +  /* OS/loader to MLE data. */
>> +
>> +  os_mle_data = grub_txt_os_mle_data_start (txt_heap);
>> +  size = (grub_uint64_t *) ((grub_addr_t) os_mle_data - sizeof
>> (grub_uint64_t));
> There is 'grub_txt_os_mle_data_size()' in previous patch, it would look
> better.
>> +  *size = sizeof (*os_mle_data) + sizeof (grub_uint64_t);
>> +
>> +  grub_memset (os_mle_data, 0, sizeof (*os_mle_data));
>> +
>> +  os_mle_data->version = GRUB_SL_OS_MLE_STRUCT_VERSION;
>> +  os_mle_data->zero_page_addr = (grub_uint32_t)(grub_addr_t)
>> slparams->params;
>> +  os_mle_data->saved_misc_enable_msr = grub_rdmsr
>> (GRUB_MSR_X86_MISC_ENABLE);
>> +
>> +  os_mle_data->ap_wake_block = slparams->ap_wake_block;
>> +
>> +  save_mtrrs (os_mle_data);
>> +
>> +  /* OS/loader to SINIT data. */
>> +
>> +  os_sinit_data_ver = grub_txt_supported_os_sinit_data_ver (sinit);
>> +
>> +  if (os_sinit_data_ver < OS_SINIT_DATA_MIN_VER)
>> +    return grub_error (GRUB_ERR_BAD_DEVICE,
>> +               N_("unsupported OS to SINIT data version in SINIT ACM:
>> %d"
>> +               " expected >= %d"), os_sinit_data_ver,
>> OS_SINIT_DATA_MIN_VER);
>> +
>> +  os_sinit_data = grub_txt_os_sinit_data_start (txt_heap);
>> +  size = (grub_uint64_t *) ((grub_addr_t) os_sinit_data - sizeof
>> (grub_uint64_t));
> Ditto
>> +
>> +  *size = sizeof(grub_uint64_t) + sizeof (struct
>> grub_txt_os_sinit_data) +
>> +      sizeof (struct grub_txt_heap_end_element);
>> +
>> +  if (grub_get_tpm_ver () == GRUB_TPM_12)
>> +    *size += sizeof (struct grub_txt_heap_tpm_event_log_element);
>> +  else if (grub_get_tpm_ver () == GRUB_TPM_20)
>> +    *size += sizeof (struct grub_txt_heap_event_log_pointer2_1_element);
>> +  else
>> +    return grub_error (GRUB_ERR_BAD_DEVICE, N_("unsupported TPM
>> version"));
>> +
>> +  grub_memset (os_sinit_data, 0, *size);
>> +
>> +#ifdef GRUB_MACHINE_EFI
>> +  rsdp = grub_acpi_get_rsdpv2 ();
>> +
>> +  if (rsdp == NULL)
>> +    return grub_printf ("WARNING: ACPI RSDP 2.0 missing\n");
>> +
>> +  os_sinit_data->efi_rsdt_ptr = (grub_uint64_t)(grub_addr_t) rsdp;
>> +#endif
>> +
>> +  os_sinit_data->mle_ptab = slparams->mle_ptab_target;
>> +  os_sinit_data->mle_size = slparams->mle_size;
>> +
>> +  os_sinit_data->mle_hdr_base = slparams->mle_header_offset;
>> +
>> +  /* TODO: Check low PMR with RMRR. Look at relevant tboot code too. */
>> +  /* TODO: Kernel should not allocate any memory outside of PMRs
>> regions!!! */
>> +  os_sinit_data->vtd_pmr_lo_base = 0;
>> +  os_sinit_data->vtd_pmr_lo_size = ALIGN_DOWN (grub_mmap_get_highest
>> (0x100000000),
>> +                           GRUB_TXT_PMR_ALIGN);
>> +
>> +  os_sinit_data->vtd_pmr_hi_base = ALIGN_UP (grub_mmap_get_lowest
>> (0x100000000),
>> +                         GRUB_TXT_PMR_ALIGN);
>> +  os_sinit_data->vtd_pmr_hi_size = ALIGN_DOWN (grub_mmap_get_highest
>> (0xffffffffffffffff),
>> +                           GRUB_TXT_PMR_ALIGN);
>> +  os_sinit_data->vtd_pmr_hi_size -= os_sinit_data->vtd_pmr_hi_base;
> Could it be done with just one PMR, from 0 to top of memory, or would

No because there could be these legacy reserved regions in somewhere
below 4G that might cause hangs if you block DMA to them. So the idea is
the high PMR covers everything > 4G and the low PMR needs special logic
to not block these reserved regions. We are working on better logic for
this now.

> TXT complain?
>> +
>> +  grub_dprintf ("slaunch",
>> +        "vtd_pmr_lo_base: 0x%" PRIxGRUB_UINT64_T " vtd_pmr_lo_size: 0x%"
>> +        PRIxGRUB_UINT64_T " vtd_pmr_hi_base: 0x%" PRIxGRUB_UINT64_T
>> +        " vtd_pmr_hi_size: 0x%" PRIxGRUB_UINT64_T "\n",
>> +        os_sinit_data->vtd_pmr_lo_base, os_sinit_data->vtd_pmr_lo_size,
>> +        os_sinit_data->vtd_pmr_hi_base, os_sinit_data->vtd_pmr_hi_size);
>> +
>>
>> <snip>
>>
>> +/*
>> + * The MLE page tables have to be below the MLE and have no special
>> regions in
>> + * between them and the MLE (this is a bit of an unwritten rule).
>> + * 20 pages are carved out of memory below the MLE. That leave 18
>> page table
>> + * pages that can cover up to 36M .
>> + * can only contain 4k pages
>> + *
>> + * TODO: TXT Spec p.32; List section name and number with PT MLE
>> requirments here.
>> + *
>> + * TODO: This function is not able to cover MLEs larger than 1 GiB.
>> Fix it!!!
>> + * After fixing inrease GRUB_TXT_MLE_MAX_SIZE too.
>> + */
> 
> What do you mean by "special regions"? In TXT spec it is written that
> there may be no holes
> in the virtual address space:
> 
> "There may not be any invalid (not-present) page table entries after the
> first valid
> entry (i.e. there may not be any gaps in the MLE’s linear address space)."
> 
> Also that spec:
> "A breadth-first search of page tables must produce increasing physical
> addresses."
> 
> Maybe I misunderstood, but does it mean that the paging structures
> themselves cannot
> be mapped? Or does it apply to the page tables only, not to the
> addresses of pages in PTEs?

One of the rules for building the page table for the ACM is the following:

Neither the MLE nor the page tables may overlap certain regions of memory:
 - device memory (PCI, PCIe*, etc.)
 - addresses between [640k, 1M] or above Top of Memory (TOM)
 - ISA hole (if enabled)
 - the Intel ® TXT heap or SINIT memory regions
 - Intel ® VT-d DMAR tables

Perhaps the comment could be better...

> 
>> +void
>> +grub_txt_setup_mle_ptab (struct grub_slaunch_params *slparams)
>> +{
>> +  grub_uint8_t *pg_dir, *pg_dir_ptr_tab = slparams->mle_ptab_mem,
>> *pg_tab;
> IMHO using 'grub_uint64_t' would result in less type casting and cleaner
> code below.
>> +  grub_uint32_t mle_off = 0, pd_off = 0;
>> +  grub_uint64_t *pde, *pte;
>> +
>> +  grub_memset (pg_dir_ptr_tab, 0, slparams->mle_ptab_size);
>> +
>> +  pg_dir         = pg_dir_ptr_tab + GRUB_PAGE_SIZE;
>> +  pg_tab         = pg_dir + GRUB_PAGE_SIZE;
>> +
>> +  /* Only use first entry in page dir ptr table */
>> +  *(grub_uint64_t *)pg_dir_ptr_tab = MAKE_PT_MLE_ENTRY(pg_dir);
>> +
>> +  /* Start with first entry in page dir */
>> +  *(grub_uint64_t *)pg_dir = MAKE_PT_MLE_ENTRY(pg_tab);
>> +
>> +  pte = (grub_uint64_t *)pg_tab;
>> +  pde = (grub_uint64_t *)pg_dir;
>> +
>> +  do
>> +    {
>> +      *pte = MAKE_PT_MLE_ENTRY(slparams->mle_start + mle_off);
>> +
>> +      pte++;
>> +      mle_off += GRUB_PAGE_SIZE;
>> +
>> +      if (!(++pd_off % 512))
>> +        {
>> +          /* Break if we don't need any additional page entries */
>> +          if (mle_off >= slparams->mle_size)
>> +            break;
>> +          pde++;
>> +          *pde = MAKE_PT_MLE_ENTRY(pte);
>> +        }
>> +    } while (mle_off < slparams->mle_size);
>> +}
>>
>> <snip>
>>
>> +grub_err_t
>> +grub_txt_boot_prepare (struct grub_slaunch_params *slparams)
>> +{
>> +  grub_err_t err;
>> +  struct grub_txt_mle_header *mle_header;
>> +  struct grub_txt_acm_header *sinit_base;
>> +
>> +  sinit_base = grub_txt_sinit_select (grub_slaunch_module ());
>> +
>> +  if (sinit_base == NULL)
>> +    return grub_errno;
>> +
>> +  err = init_txt_heap (slparams, sinit_base);
>> +
>> +  if (err != GRUB_ERR_NONE)
>> +    return err;
>> +
>> +  /* Update the MLE header. */
>> +  mle_header = (struct grub_txt_mle_header *)(grub_addr_t)
>> (slparams->mle_start + slparams->mle_header_offset);
>> +  mle_header->first_valid_page = 0;
>> +  mle_header->mle_end = slparams->mle_size;
>> +
>> +  slparams->sinit_acm_base = (grub_uint32_t)(grub_addr_t) sinit_base;
>> +  slparams->sinit_acm_size = sinit_base->size * 4;
>> +
>> +  grub_tpm_relinquish_lcl (0);
>> +
>> +  err = set_mtrrs_for_acmod (sinit_base);
>> +  if (err)
>> +    return grub_error (err, N_("secure launch failed to set MTRRs for
>> ACM"));
>> +
>> +  err = grub_txt_prepare_cpu ();
>> +  if ( err )
>> +    return err;
>> +
>> +  if (!(grub_rdmsr (GRUB_MSR_X86_APICBASE) & GRUB_MSR_X86_APICBASE_BSP))
>> +    return grub_error (GRUB_ERR_BAD_DEVICE, N_("secure launch must
>> run on BSP"));
> This test should be the first one, before messing with TPM and MTTRs.
>> +
>> +  return GRUB_ERR_NONE;
>> +}
> Best regards,
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher
  2020-05-07 11:06   ` Daniel Kiper
  2020-05-13 13:47     ` Lukasz Hawrylko
@ 2020-06-01 15:32     ` Daniel P. Smith
  2020-06-01 16:51       ` Andy Lutomirski
  1 sibling, 1 reply; 36+ messages in thread
From: Daniel P. Smith @ 2020-06-01 15:32 UTC (permalink / raw)
  To: Daniel Kiper, Lukasz Hawrylko
  Cc: grub-devel, linux-kernel, trenchboot-devel, x86,
	alexander.burmashev, andrew.cooper3, ard.biesheuvel,
	eric.snowberg, javierm, kanth.ghatraju, konrad.wilk,
	krystian.hebel, michal.zygowski, mjg59, phcoder, piotr.krol,
	pjones, ross.philipson

On 5/7/20 7:06 AM, Daniel Kiper wrote:
> Hi Łukasz,
> 
> On Tue, May 05, 2020 at 04:38:02PM +0200, Lukasz Hawrylko wrote:
>> On Tue, 2020-05-05 at 01:21 +0200, Daniel Kiper wrote:

...

>> In OS-MLE table there is a buffer for TPM event log, however I see that
>> you are not using it, but instead allocate space somewhere in the
> 
> I think that this part requires more discussion. In my opinion we should
> have this region dynamically allocated because it gives us more flexibility.
> Of course there is a question about the size of this buffer too. I am
> not sure about that because I have not checked yet how many log entries
> are created by the SINIT ACM. Though probably it should not be large...
> 
>> memory. I am just wondering if, from security perspective, it will be
>> better to use memory from TXT heap for event log, like we do in TBOOT.
> 
> Appendix F, TPM Event Log, has following sentence: There are no
> requirements for event log to be in DMA protected memory – SINIT will
> not enforce it.
> 
> I was thinking about it and it seems to me that the TPM event log does
> not require any special protections. Any changes in it can be quickly
> detected by comparing hashes with the TPM PCRs. Does not it?
> 

I think it would be beneficial to consider the following in deciding
where the log is placed. There are two areas of attack/manipulation that
need to be considered. The first area is the log contents itself, which
as Daniel has pointed out, the log contents do not really need to be
protected from tampering as that would/should be detected during
verification by the attestor. The second area that we need to consider
is the log descriptors themselves. If these are in an area that can be
manipulated, it is an opportunity for an attacker to attempt to
influence the ACM's execution. For a little perspective, the ACM
executes from CRAM to take the most possible precaution to ensure that
it cannot be tampered with during execution. This is very important
since it runs a CPU mode (ACM Mode) that I would consider to be higher
(or lower depending on how you view it) than SMM. As a result, the txt
heap is also included in what is mapped into CRAM. If the event log is
place in the heap, this ensures that the ACM is not using memory outside
of CRAM during execution. Now as Daniel has pointed out, the down side
to this is that it greatly restricts the log size and can only be
managed by a combination of limiting the number of events and
restricting what content is carried in the event data field.

With everything that has been said, I am wondering if it would it be
possible to make it configurable. Thoughts?

V/r,
DPS


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher
  2020-06-01 15:32     ` Daniel P. Smith
@ 2020-06-01 16:51       ` Andy Lutomirski
  2020-06-01 17:56         ` Daniel P. Smith
  0 siblings, 1 reply; 36+ messages in thread
From: Andy Lutomirski @ 2020-06-01 16:51 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Daniel Kiper, Lukasz Hawrylko, grub-devel, LKML,
	trenchboot-devel, X86 ML, alexander.burmashev, Andrew Cooper,
	Ard Biesheuvel, eric.snowberg, javierm, kanth.ghatraju,
	Konrad Rzeszutek Wilk, krystian.hebel, michal.zygowski,
	Matthew Garrett, phcoder, piotr.krol, Peter Jones,
	Ross Philipson

On Mon, Jun 1, 2020 at 8:33 AM Daniel P. Smith
<dpsmith@apertussolutions.com> wrote:
>
> On 5/7/20 7:06 AM, Daniel Kiper wrote:
> > Hi Łukasz,
> >
> > On Tue, May 05, 2020 at 04:38:02PM +0200, Lukasz Hawrylko wrote:
> >> On Tue, 2020-05-05 at 01:21 +0200, Daniel Kiper wrote:
>
> ...
>
> >> In OS-MLE table there is a buffer for TPM event log, however I see that
> >> you are not using it, but instead allocate space somewhere in the
> >
> > I think that this part requires more discussion. In my opinion we should
> > have this region dynamically allocated because it gives us more flexibility.
> > Of course there is a question about the size of this buffer too. I am
> > not sure about that because I have not checked yet how many log entries
> > are created by the SINIT ACM. Though probably it should not be large...
> >
> >> memory. I am just wondering if, from security perspective, it will be
> >> better to use memory from TXT heap for event log, like we do in TBOOT.
> >
> > Appendix F, TPM Event Log, has following sentence: There are no
> > requirements for event log to be in DMA protected memory – SINIT will
> > not enforce it.
> >
> > I was thinking about it and it seems to me that the TPM event log does
> > not require any special protections. Any changes in it can be quickly
> > detected by comparing hashes with the TPM PCRs. Does not it?
> >
>
> I think it would be beneficial to consider the following in deciding
> where the log is placed. There are two areas of attack/manipulation that
> need to be considered. The first area is the log contents itself, which
> as Daniel has pointed out, the log contents do not really need to be
> protected from tampering as that would/should be detected during
> verification by the attestor. The second area that we need to consider
> is the log descriptors themselves. If these are in an area that can be
> manipulated, it is an opportunity for an attacker to attempt to
> influence the ACM's execution. For a little perspective, the ACM
> executes from CRAM to take the most possible precaution to ensure that
> it cannot be tampered with during execution. This is very important
> since it runs a CPU mode (ACM Mode) that I would consider to be higher
> (or lower depending on how you view it) than SMM. As a result, the txt
> heap is also included in what is mapped into CRAM. If the event log is
> place in the heap, this ensures that the ACM is not using memory outside
> of CRAM during execution. Now as Daniel has pointed out, the down side
> to this is that it greatly restricts the log size and can only be
> managed by a combination of limiting the number of events and
> restricting what content is carried in the event data field.

Can you clarify what the actual flow of control is?  If I had to guess, it's:

GRUB (or other bootloader) writes log.

GRUB transfers control to the ACM.  At this point, GRUB is done
running and GRUB code will not run again.

ACM validates system configuration and updates TPM state using magic
privileged TPM access.

ACM transfers control to the shiny new Linux secure launch entry point

Maybe this is right, and maybe this is wrong.  But I have some
questions about this whole setup.  Is the ACM code going to inspect
this log at all?  If so, why?  Who supplies the ACM code?  If the ACM
can be attacked by putting its inputs (e.g. this log) in the wrong
place in memory, why should this be considered anything other than a
bug in the ACM?

If GRUB is indeed done by the time anyone consumes the log, why does
GRUB care where the log ends up?

And finally, the log presumably has nonzero size, and it would be nice
not to pin some physical memory forever for the log.  Could the kernel
copy it into tmpfs during boot so it's at least swappable and then
allow userspace to delete it when userspace is done with it?

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher
  2020-06-01 16:51       ` Andy Lutomirski
@ 2020-06-01 17:56         ` Daniel P. Smith
  2020-06-01 18:03           ` Ross Philipson
  2020-06-01 19:39           ` Andy Lutomirski
  0 siblings, 2 replies; 36+ messages in thread
From: Daniel P. Smith @ 2020-06-01 17:56 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Daniel Kiper, Lukasz Hawrylko, grub-devel, LKML,
	trenchboot-devel, X86 ML, alexander.burmashev, Andrew Cooper,
	Ard Biesheuvel, eric.snowberg, javierm, kanth.ghatraju,
	Konrad Rzeszutek Wilk, krystian.hebel, michal.zygowski,
	Matthew Garrett, phcoder, piotr.krol, Peter Jones,
	Ross Philipson

On 6/1/20 12:51 PM, Andy Lutomirski wrote:
> On Mon, Jun 1, 2020 at 8:33 AM Daniel P. Smith
> <dpsmith@apertussolutions.com> wrote:
>>
>> On 5/7/20 7:06 AM, Daniel Kiper wrote:
>>> Hi Łukasz,
>>>
>>> On Tue, May 05, 2020 at 04:38:02PM +0200, Lukasz Hawrylko wrote:
>>>> On Tue, 2020-05-05 at 01:21 +0200, Daniel Kiper wrote:
>>
>> ...
>>
>>>> In OS-MLE table there is a buffer for TPM event log, however I see that
>>>> you are not using it, but instead allocate space somewhere in the
>>>
>>> I think that this part requires more discussion. In my opinion we should
>>> have this region dynamically allocated because it gives us more flexibility.
>>> Of course there is a question about the size of this buffer too. I am
>>> not sure about that because I have not checked yet how many log entries
>>> are created by the SINIT ACM. Though probably it should not be large...
>>>
>>>> memory. I am just wondering if, from security perspective, it will be
>>>> better to use memory from TXT heap for event log, like we do in TBOOT.
>>>
>>> Appendix F, TPM Event Log, has following sentence: There are no
>>> requirements for event log to be in DMA protected memory – SINIT will
>>> not enforce it.
>>>
>>> I was thinking about it and it seems to me that the TPM event log does
>>> not require any special protections. Any changes in it can be quickly
>>> detected by comparing hashes with the TPM PCRs. Does not it?
>>>
>>
>> I think it would be beneficial to consider the following in deciding
>> where the log is placed. There are two areas of attack/manipulation that
>> need to be considered. The first area is the log contents itself, which
>> as Daniel has pointed out, the log contents do not really need to be
>> protected from tampering as that would/should be detected during
>> verification by the attestor. The second area that we need to consider
>> is the log descriptors themselves. If these are in an area that can be
>> manipulated, it is an opportunity for an attacker to attempt to
>> influence the ACM's execution. For a little perspective, the ACM
>> executes from CRAM to take the most possible precaution to ensure that
>> it cannot be tampered with during execution. This is very important
>> since it runs a CPU mode (ACM Mode) that I would consider to be higher
>> (or lower depending on how you view it) than SMM. As a result, the txt
>> heap is also included in what is mapped into CRAM. If the event log is
>> place in the heap, this ensures that the ACM is not using memory outside
>> of CRAM during execution. Now as Daniel has pointed out, the down side
>> to this is that it greatly restricts the log size and can only be
>> managed by a combination of limiting the number of events and
>> restricting what content is carried in the event data field.
> 
> Can you clarify what the actual flow of control is?  If I had to guess, it's:
> 
> GRUB (or other bootloader) writes log.
> 
> GRUB transfers control to the ACM.  At this point, GRUB is done
> running and GRUB code will not run again.
> 
> ACM validates system configuration and updates TPM state using magic
> privileged TPM access.
> 
> ACM transfers control to the shiny new Linux secure launch entry point
> 
> Maybe this is right, and maybe this is wrong.  But I have some
> questions about this whole setup.  Is the ACM code going to inspect
> this log at all?  If so, why?  Who supplies the ACM code?  If the ACM
> can be attacked by putting its inputs (e.g. this log) in the wrong
> place in memory, why should this be considered anything other than a
> bug in the ACM?

There is a lot behind that, so to get a complete detail of the event
sequence I would recommend looking at Section Vol. 2D 6.2.3 (pg Vol. 2D
6-5/ pdf pg 2531), 6.3 GETSEC[ENTERACCS](pg 6-10 Vol. 2D/pdf pg 2546),
and 6.3 GETSEC[SENTER](pg Vol. 2D 6-21/pdf pg 2557) in the Intel SDM[1].
Section 6.2.3 gives a slightly detailed overview. Section
GETSEC[ENTERACCS] details the requirements/procedures for entering AC
execution mode and ACRAM (Authenticated CRAM) and section GETSEC[SENTER]
will detail requirements/procedures for SENTER.

To answer you additional questions I would say if you look at all the
work that goes into protecting the ACM execution, why would you want to
then turn around and have it use memory outside of the protected region.
On the other hand, you are right, if the Developer's Guide says it
doesn't need to be protected and someone somehow finds a way to cause a
failure in the ACM through the use of a log outside of CRAM, then
rightfully that is a bug in the ACM. This is why I asked about making it
configurable, paranoid people could set the configuration to use the
heap and all others could just use an external location.

> If GRUB is indeed done by the time anyone consumes the log, why does
> GRUB care where the log ends up?

This is because the log buffer allocation was made the responsibility of
the pre-launch environment, in this case GRUB, and is communicated to
the ACM via the os_to_mle structure.

> And finally, the log presumably has nonzero size, and it would be nice
> not to pin some physical memory forever for the log.  Could the kernel
> copy it into tmpfs during boot so it's at least swappable and then
> allow userspace to delete it when userspace is done with it?
> 

Actually yes we will want to do that because when we move to enabling
relaunching, an implementation may want to preserve the log from the
last launch before triggering the new launch which will result in a
reset of the DRTM PCRs and an overwriting the log.

[1]
https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher
  2020-06-01 17:56         ` Daniel P. Smith
@ 2020-06-01 18:03           ` Ross Philipson
  2020-06-01 19:39           ` Andy Lutomirski
  1 sibling, 0 replies; 36+ messages in thread
From: Ross Philipson @ 2020-06-01 18:03 UTC (permalink / raw)
  To: Daniel P. Smith, Andy Lutomirski
  Cc: Daniel Kiper, Lukasz Hawrylko, grub-devel, LKML,
	trenchboot-devel, X86 ML, alexander.burmashev, Andrew Cooper,
	Ard Biesheuvel, eric.snowberg, javierm, kanth.ghatraju,
	Konrad Rzeszutek Wilk, krystian.hebel, michal.zygowski,
	Matthew Garrett, phcoder, piotr.krol, Peter Jones

On 6/1/20 1:56 PM, Daniel P. Smith wrote:
> On 6/1/20 12:51 PM, Andy Lutomirski wrote:
>> On Mon, Jun 1, 2020 at 8:33 AM Daniel P. Smith
>> <dpsmith@apertussolutions.com> wrote:
>>>
>>> On 5/7/20 7:06 AM, Daniel Kiper wrote:
>>>> Hi Łukasz,
>>>>
>>>> On Tue, May 05, 2020 at 04:38:02PM +0200, Lukasz Hawrylko wrote:
>>>>> On Tue, 2020-05-05 at 01:21 +0200, Daniel Kiper wrote:
>>>
>>> ...
>>>
>>>>> In OS-MLE table there is a buffer for TPM event log, however I see that
>>>>> you are not using it, but instead allocate space somewhere in the
>>>>
>>>> I think that this part requires more discussion. In my opinion we should
>>>> have this region dynamically allocated because it gives us more flexibility.
>>>> Of course there is a question about the size of this buffer too. I am
>>>> not sure about that because I have not checked yet how many log entries
>>>> are created by the SINIT ACM. Though probably it should not be large...
>>>>
>>>>> memory. I am just wondering if, from security perspective, it will be
>>>>> better to use memory from TXT heap for event log, like we do in TBOOT.
>>>>
>>>> Appendix F, TPM Event Log, has following sentence: There are no
>>>> requirements for event log to be in DMA protected memory – SINIT will
>>>> not enforce it.
>>>>
>>>> I was thinking about it and it seems to me that the TPM event log does
>>>> not require any special protections. Any changes in it can be quickly
>>>> detected by comparing hashes with the TPM PCRs. Does not it?
>>>>
>>>
>>> I think it would be beneficial to consider the following in deciding
>>> where the log is placed. There are two areas of attack/manipulation that
>>> need to be considered. The first area is the log contents itself, which
>>> as Daniel has pointed out, the log contents do not really need to be
>>> protected from tampering as that would/should be detected during
>>> verification by the attestor. The second area that we need to consider
>>> is the log descriptors themselves. If these are in an area that can be
>>> manipulated, it is an opportunity for an attacker to attempt to
>>> influence the ACM's execution. For a little perspective, the ACM
>>> executes from CRAM to take the most possible precaution to ensure that
>>> it cannot be tampered with during execution. This is very important
>>> since it runs a CPU mode (ACM Mode) that I would consider to be higher
>>> (or lower depending on how you view it) than SMM. As a result, the txt
>>> heap is also included in what is mapped into CRAM. If the event log is
>>> place in the heap, this ensures that the ACM is not using memory outside
>>> of CRAM during execution. Now as Daniel has pointed out, the down side
>>> to this is that it greatly restricts the log size and can only be
>>> managed by a combination of limiting the number of events and
>>> restricting what content is carried in the event data field.
>>
>> Can you clarify what the actual flow of control is?  If I had to guess, it's:
>>
>> GRUB (or other bootloader) writes log.
>>
>> GRUB transfers control to the ACM.  At this point, GRUB is done
>> running and GRUB code will not run again.
>>
>> ACM validates system configuration and updates TPM state using magic
>> privileged TPM access.
>>
>> ACM transfers control to the shiny new Linux secure launch entry point
>>
>> Maybe this is right, and maybe this is wrong.  But I have some
>> questions about this whole setup.  Is the ACM code going to inspect
>> this log at all?  If so, why?  Who supplies the ACM code?  If the ACM
>> can be attacked by putting its inputs (e.g. this log) in the wrong
>> place in memory, why should this be considered anything other than a
>> bug in the ACM?
> 
> There is a lot behind that, so to get a complete detail of the event
> sequence I would recommend looking at Section Vol. 2D 6.2.3 (pg Vol. 2D
> 6-5/ pdf pg 2531), 6.3 GETSEC[ENTERACCS](pg 6-10 Vol. 2D/pdf pg 2546),
> and 6.3 GETSEC[SENTER](pg Vol. 2D 6-21/pdf pg 2557) in the Intel SDM[1].
> Section 6.2.3 gives a slightly detailed overview. Section
> GETSEC[ENTERACCS] details the requirements/procedures for entering AC
> execution mode and ACRAM (Authenticated CRAM) and section GETSEC[SENTER]
> will detail requirements/procedures for SENTER.
> 
> To answer you additional questions I would say if you look at all the
> work that goes into protecting the ACM execution, why would you want to
> then turn around and have it use memory outside of the protected region.
> On the other hand, you are right, if the Developer's Guide says it
> doesn't need to be protected and someone somehow finds a way to cause a
> failure in the ACM through the use of a log outside of CRAM, then
> rightfully that is a bug in the ACM. This is why I asked about making it
> configurable, paranoid people could set the configuration to use the
> heap and all others could just use an external location.

After thinking about it, it should be easy to make it configurable since
as stated it is up the the pre-launch code to decide where the buffer
is. To do this, the static buffer will be removed from the OS-MLE
structure. In its place there will be two fields:

u64 evt_log_base;
u64 evt_log_size;

If the entity setting up the buffer wants to place the log in the TXT
heap, it simply allocates memory after the OS-MLE fixed structure and
points evt_log_base there. If a buffer outside of the heap is wanted,
just point evt_log_base there. If the MLE wants to determine if the log
is in the TXT heap, it just has to compare evt_log_base to the TXT heap
extents.

Thanks
Ross

> 
>> If GRUB is indeed done by the time anyone consumes the log, why does
>> GRUB care where the log ends up?
> 
> This is because the log buffer allocation was made the responsibility of
> the pre-launch environment, in this case GRUB, and is communicated to
> the ACM via the os_to_mle structure.
> 
>> And finally, the log presumably has nonzero size, and it would be nice
>> not to pin some physical memory forever for the log.  Could the kernel
>> copy it into tmpfs during boot so it's at least swappable and then
>> allow userspace to delete it when userspace is done with it?
>>
> 
> Actually yes we will want to do that because when we move to enabling
> relaunching, an implementation may want to preserve the log from the
> last launch before triggering the new launch which will result in a
> reset of the DRTM PCRs and an overwriting the log.
> 
> [1]
> https://urldefense.com/v3/__https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf__;!!GqivPVa7Brio!MqL6_Gyu6fCO2MyxrvWmvfkCBRXYv1rKJnUrqvQoMNSwQTA9Db9H9BqDI96S13A4HUA$ 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher
  2020-06-01 17:56         ` Daniel P. Smith
  2020-06-01 18:03           ` Ross Philipson
@ 2020-06-01 19:39           ` Andy Lutomirski
  2020-06-02  0:13             ` Daniel P. Smith
  1 sibling, 1 reply; 36+ messages in thread
From: Andy Lutomirski @ 2020-06-01 19:39 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Andy Lutomirski, Daniel Kiper, Lukasz Hawrylko, grub-devel, LKML,
	trenchboot-devel, X86 ML, alexander.burmashev, Andrew Cooper,
	Ard Biesheuvel, eric.snowberg, javierm, kanth.ghatraju,
	Konrad Rzeszutek Wilk, krystian.hebel, michal.zygowski,
	Matthew Garrett, phcoder, piotr.krol, Peter Jones,
	Ross Philipson


> On Jun 1, 2020, at 10:56 AM, Daniel P. Smith <dpsmith@apertussolutions.com> wrote:
> 
> On 6/1/20 12:51 PM, Andy Lutomirski wrote:
>>> On Mon, Jun 1, 2020 at 8:33 AM Daniel P. Smith
>>> <dpsmith@apertussolutions.com> wrote:
>>> 
>>> On 5/7/20 7:06 AM, Daniel Kiper wrote:
>>>> Hi Łukasz,
>>>> 
>>>> On Tue, May 05, 2020 at 04:38:02PM +0200, Lukasz Hawrylko wrote:
>>>>>> On Tue, 2020-05-05 at 01:21 +0200, Daniel Kiper wrote:
>>> 
>>> ...
>>> 
>>>>> In OS-MLE table there is a buffer for TPM event log, however I see that
>>>>> you are not using it, but instead allocate space somewhere in the
>>>> 
>>>> I think that this part requires more discussion. In my opinion we should
>>>> have this region dynamically allocated because it gives us more flexibility.
>>>> Of course there is a question about the size of this buffer too. I am
>>>> not sure about that because I have not checked yet how many log entries
>>>> are created by the SINIT ACM. Though probably it should not be large...
>>>> 
>>>>> memory. I am just wondering if, from security perspective, it will be
>>>>> better to use memory from TXT heap for event log, like we do in TBOOT.
>>>> 
>>>> Appendix F, TPM Event Log, has following sentence: There are no
>>>> requirements for event log to be in DMA protected memory – SINIT will
>>>> not enforce it.
>>>> 
>>>> I was thinking about it and it seems to me that the TPM event log does
>>>> not require any special protections. Any changes in it can be quickly
>>>> detected by comparing hashes with the TPM PCRs. Does not it?
>>>> 
>>> 
>>> I think it would be beneficial to consider the following in deciding
>>> where the log is placed. There are two areas of attack/manipulation that
>>> need to be considered. The first area is the log contents itself, which
>>> as Daniel has pointed out, the log contents do not really need to be
>>> protected from tampering as that would/should be detected during
>>> verification by the attestor. The second area that we need to consider
>>> is the log descriptors themselves. If these are in an area that can be
>>> manipulated, it is an opportunity for an attacker to attempt to
>>> influence the ACM's execution. For a little perspective, the ACM
>>> executes from CRAM to take the most possible precaution to ensure that
>>> it cannot be tampered with during execution. This is very important
>>> since it runs a CPU mode (ACM Mode) that I would consider to be higher
>>> (or lower depending on how you view it) than SMM. As a result, the txt
>>> heap is also included in what is mapped into CRAM. If the event log is
>>> place in the heap, this ensures that the ACM is not using memory outside
>>> of CRAM during execution. Now as Daniel has pointed out, the down side
>>> to this is that it greatly restricts the log size and can only be
>>> managed by a combination of limiting the number of events and
>>> restricting what content is carried in the event data field.
>> 
>> Can you clarify what the actual flow of control is?  If I had to guess, it's:
>> 
>> GRUB (or other bootloader) writes log.
>> 
>> GRUB transfers control to the ACM.  At this point, GRUB is done
>> running and GRUB code will not run again.
>> 
>> ACM validates system configuration and updates TPM state using magic
>> privileged TPM access.
>> 
>> ACM transfers control to the shiny new Linux secure launch entry point
>> 
>> Maybe this is right, and maybe this is wrong.  But I have some
>> questions about this whole setup.  Is the ACM code going to inspect
>> this log at all?  If so, why?  Who supplies the ACM code?  If the ACM
>> can be attacked by putting its inputs (e.g. this log) in the wrong
>> place in memory, why should this be considered anything other than a
>> bug in the ACM?
> 
> There is a lot behind that, so to get a complete detail of the event
> sequence I would recommend looking at Section Vol. 2D 6.2.3 (pg Vol. 2D
> 6-5/ pdf pg 2531), 6.3 GETSEC[ENTERACCS](pg 6-10 Vol. 2D/pdf pg 2546),
> and 6.3 GETSEC[SENTER](pg Vol. 2D 6-21/pdf pg 2557) in the Intel SDM[1].
> Section 6.2.3 gives a slightly detailed overview. Section
> GETSEC[ENTERACCS] details the requirements/procedures for entering AC
> execution mode and ACRAM (Authenticated CRAM) and section GETSEC[SENTER]
> will detail requirements/procedures for SENTER.
> 
> To answer you additional questions I would say if you look at all the
> work that goes into protecting the ACM execution, why would you want to
> then turn around and have it use memory outside of the protected region.
> On the other hand, you are right, if the Developer's Guide says it
> doesn't need to be protected and someone somehow finds a way to cause a
> failure in the ACM through the use of a log outside of CRAM, then
> rightfully that is a bug in the ACM. This is why I asked about making it
> configurable, paranoid people could set the configuration to use the
> heap and all others could just use an external location.

And this provides no protection whatsoever to paranoid people AFAICS, unless the location gets hashed before any processing occurs.

But you haven’t answered the most important question: what is the ACM doing with this log?  I feel like a lot of details are being covered but the big picture is missing.

> 
>> If GRUB is indeed done by the time anyone consumes the log, why does
>> GRUB care where the log ends up?
> 
> This is because the log buffer allocation was made the responsibility of
> the pre-launch environment, in this case GRUB, and is communicated to
> the ACM via the os_to_mle structure.
> 
>> And finally, the log presumably has nonzero size, and it would be nice
>> not to pin some physical memory forever for the log.  Could the kernel
>> copy it into tmpfs during boot so it's at least swappable and then
>> allow userspace to delete it when userspace is done with it?
>> 
> 
> Actually yes we will want to do that because when we move to enabling
> relaunching, an implementation may want to preserve the log from the
> last launch before triggering the new launch which will result in a
> reset of the DRTM PCRs and an overwriting the log.

I’m having a bit of trouble understanding how this log is useful for a relaunch. At the point that you’re relaunching, the log is even less trustworthy than on first launch. At least on first launch, if you dial up your secure and verified boot settings tight enough, you can have some degree of confidence in the boot environment. But on a relaunch, I don’t see how the log is useful for anything more than any other piece of kernel memory.

What am I missing?


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher
  2020-06-01 19:39           ` Andy Lutomirski
@ 2020-06-02  0:13             ` Daniel P. Smith
  2020-06-02  0:49               ` Andy Lutomirski
  0 siblings, 1 reply; 36+ messages in thread
From: Daniel P. Smith @ 2020-06-02  0:13 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Andy Lutomirski, Daniel Kiper, Lukasz Hawrylko, grub-devel, LKML,
	trenchboot-devel, X86 ML, alexander.burmashev, Andrew Cooper,
	Ard Biesheuvel, eric.snowberg, javierm, kanth.ghatraju,
	Konrad Rzeszutek Wilk, krystian.hebel, michal.zygowski,
	Matthew Garrett, phcoder, piotr.krol, Peter Jones,
	Ross Philipson

On 6/1/20 3:39 PM, Andy Lutomirski wrote:
> 
>> On Jun 1, 2020, at 10:56 AM, Daniel P. Smith <dpsmith@apertussolutions.com> wrote:
>>
>> On 6/1/20 12:51 PM, Andy Lutomirski wrote:
>>>> On Mon, Jun 1, 2020 at 8:33 AM Daniel P. Smith
>>>> <dpsmith@apertussolutions.com> wrote:
>>>>
>>>> On 5/7/20 7:06 AM, Daniel Kiper wrote:
>>>>> Hi Łukasz,
>>>>>
>>>>> On Tue, May 05, 2020 at 04:38:02PM +0200, Lukasz Hawrylko wrote:
>>>>>>> On Tue, 2020-05-05 at 01:21 +0200, Daniel Kiper wrote:
>>>>
>>>> ...
>>>>
>>>>>> In OS-MLE table there is a buffer for TPM event log, however I see that
>>>>>> you are not using it, but instead allocate space somewhere in the
>>>>>
>>>>> I think that this part requires more discussion. In my opinion we should
>>>>> have this region dynamically allocated because it gives us more flexibility.
>>>>> Of course there is a question about the size of this buffer too. I am
>>>>> not sure about that because I have not checked yet how many log entries
>>>>> are created by the SINIT ACM. Though probably it should not be large...
>>>>>
>>>>>> memory. I am just wondering if, from security perspective, it will be
>>>>>> better to use memory from TXT heap for event log, like we do in TBOOT.
>>>>>
>>>>> Appendix F, TPM Event Log, has following sentence: There are no
>>>>> requirements for event log to be in DMA protected memory – SINIT will
>>>>> not enforce it.
>>>>>
>>>>> I was thinking about it and it seems to me that the TPM event log does
>>>>> not require any special protections. Any changes in it can be quickly
>>>>> detected by comparing hashes with the TPM PCRs. Does not it?
>>>>>
>>>>
>>>> I think it would be beneficial to consider the following in deciding
>>>> where the log is placed. There are two areas of attack/manipulation that
>>>> need to be considered. The first area is the log contents itself, which
>>>> as Daniel has pointed out, the log contents do not really need to be
>>>> protected from tampering as that would/should be detected during
>>>> verification by the attestor. The second area that we need to consider
>>>> is the log descriptors themselves. If these are in an area that can be
>>>> manipulated, it is an opportunity for an attacker to attempt to
>>>> influence the ACM's execution. For a little perspective, the ACM
>>>> executes from CRAM to take the most possible precaution to ensure that
>>>> it cannot be tampered with during execution. This is very important
>>>> since it runs a CPU mode (ACM Mode) that I would consider to be higher
>>>> (or lower depending on how you view it) than SMM. As a result, the txt
>>>> heap is also included in what is mapped into CRAM. If the event log is
>>>> place in the heap, this ensures that the ACM is not using memory outside
>>>> of CRAM during execution. Now as Daniel has pointed out, the down side
>>>> to this is that it greatly restricts the log size and can only be
>>>> managed by a combination of limiting the number of events and
>>>> restricting what content is carried in the event data field.
>>>
>>> Can you clarify what the actual flow of control is?  If I had to guess, it's:
>>>
>>> GRUB (or other bootloader) writes log.
>>>
>>> GRUB transfers control to the ACM.  At this point, GRUB is done
>>> running and GRUB code will not run again.
>>>
>>> ACM validates system configuration and updates TPM state using magic
>>> privileged TPM access.
>>>
>>> ACM transfers control to the shiny new Linux secure launch entry point
>>>
>>> Maybe this is right, and maybe this is wrong.  But I have some
>>> questions about this whole setup.  Is the ACM code going to inspect
>>> this log at all?  If so, why?  Who supplies the ACM code?  If the ACM
>>> can be attacked by putting its inputs (e.g. this log) in the wrong
>>> place in memory, why should this be considered anything other than a
>>> bug in the ACM?
>>
>> There is a lot behind that, so to get a complete detail of the event
>> sequence I would recommend looking at Section Vol. 2D 6.2.3 (pg Vol. 2D
>> 6-5/ pdf pg 2531), 6.3 GETSEC[ENTERACCS](pg 6-10 Vol. 2D/pdf pg 2546),
>> and 6.3 GETSEC[SENTER](pg Vol. 2D 6-21/pdf pg 2557) in the Intel SDM[1].
>> Section 6.2.3 gives a slightly detailed overview. Section
>> GETSEC[ENTERACCS] details the requirements/procedures for entering AC
>> execution mode and ACRAM (Authenticated CRAM) and section GETSEC[SENTER]
>> will detail requirements/procedures for SENTER.
>>
>> To answer you additional questions I would say if you look at all the
>> work that goes into protecting the ACM execution, why would you want to
>> then turn around and have it use memory outside of the protected region.
>> On the other hand, you are right, if the Developer's Guide says it
>> doesn't need to be protected and someone somehow finds a way to cause a
>> failure in the ACM through the use of a log outside of CRAM, then
>> rightfully that is a bug in the ACM. This is why I asked about making it
>> configurable, paranoid people could set the configuration to use the
>> heap and all others could just use an external location.
> 
> And this provides no protection whatsoever to paranoid people AFAICS, unless the location gets hashed before any processing occurs.

Apologies but that is exactly what it says. From section 6.2.3,

"After the GETSEC[SENTER] rendezvous handshake is performed between all
logical processors in the platform, the ILP loads the chipset
authenticated code module (SINIT) and performs an authentication check.
If the check passes, the processor hashes the SINIT AC module and stores
the result into TPM PCR 17. It then switches execution context to the
SINIT AC module."

To get a little into the details, the ACM is signed with an RSA key that
is deeply embedded into the CPU, thus why there is an ACM per
architecture as each one gets a new key. The authentication check is
detailed in the section GETSEC[ENTERACCS], but in the end the ACM has
had a crypto signature check carried out by the CPU (not firmware) and
is also cryptographically hashed by the CPU (again not firmware). On top
of this, both operations are executed after all interrupts have been
disabled and the ACM has been loaded into ACRAM from memory that was
protected by the IOMMU. Only after all this succeeds is the ACM allowed
to execute.

> But you haven’t answered the most important question: what is the ACM doing with this log?  I feel like a lot of details are being covered but the big picture is missing.

To the ACM, this is just an allocated buffer for it to record a TPM
event log for all the measurements it takes. It has been a while since I
 have manually reviewed a TXT event log but I want to say there are
about five measurements taken before the ACM exits, including recording
the CRTM taken by the CPU. As such, it initialize the beginning of the
buffer with a TXT log header and records a UEFI TPM Event for each
measurement it takes. In theory, it will only ever write to this memory
but seeing that the ACM is a binary blob, I have never seen
programmatically if it ever tries reading from the memory.

>>
>>> If GRUB is indeed done by the time anyone consumes the log, why does
>>> GRUB care where the log ends up?
>>
>> This is because the log buffer allocation was made the responsibility of
>> the pre-launch environment, in this case GRUB, and is communicated to
>> the ACM via the os_to_mle structure.
>>
>>> And finally, the log presumably has nonzero size, and it would be nice
>>> not to pin some physical memory forever for the log.  Could the kernel
>>> copy it into tmpfs during boot so it's at least swappable and then
>>> allow userspace to delete it when userspace is done with it?
>>>
>>
>> Actually yes we will want to do that because when we move to enabling
>> relaunching, an implementation may want to preserve the log from the
>> last launch before triggering the new launch which will result in a
>> reset of the DRTM PCRs and an overwriting the log.
> 
> I’m having a bit of trouble understanding how this log is useful for a relaunch. At the point that you’re relaunching, the log is even less trustworthy than on first launch. At least on first launch, if you dial up your secure and verified boot settings tight enough, you can have some degree of confidence in the boot environment. But on a relaunch, I don’t see how the log is useful for anything more than any other piece of kernel memory.
> 
> What am I missing?
> 

Before relaunch you can have the TPM do a sign quote of the log to bind
the contents to the state of the PCRs. The why you would do that is more
about enterprise use-cases concerned with the lifecycle of enterprise
devices.When relaunch occurs, the DRTM PCRs will be reset by the CPU
before the CRTM for the relaunch is taken by the CPU and the ACM will
overwrite the existing log with new log entries. As highlighted above,
the CRTM and all measurements take by the ACM will have an extremely low
risk of external/attacker influence. When the MLE takes control,
interrupts will still be disabled and any measurements it takes prior to
enabling them will have a low risk of external/attacker influence. Once
the MLE enables the interrupts is when you have the situation whereby
the integrity you just established about the runtime can be compromised
by hostile firmware (UEFI runtime services, SMI handler, EC firmware,
PCI devices, etc.), hostile applications, and a hostile network. At this
point we could devolve into discourse over how long can load time
integrity measurements be considered trustworthy but I don't think that
is relevant to the issue at hand.

In other words, the log for the relaunch to attest what is currently
running is really no less useful than using the first launch log to
attest to the what was running in the first launch.


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher
  2020-06-02  0:13             ` Daniel P. Smith
@ 2020-06-02  0:49               ` Andy Lutomirski
  2020-06-02  1:29                 ` Daniel P. Smith
  0 siblings, 1 reply; 36+ messages in thread
From: Andy Lutomirski @ 2020-06-02  0:49 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Andy Lutomirski, Daniel Kiper, Lukasz Hawrylko, grub-devel, LKML,
	trenchboot-devel, X86 ML, alexander.burmashev, Andrew Cooper,
	Ard Biesheuvel, eric.snowberg, javierm, kanth.ghatraju,
	Konrad Rzeszutek Wilk, krystian.hebel, michal.zygowski,
	Matthew Garrett, phcoder, piotr.krol, Peter Jones,
	Ross Philipson



> On Jun 1, 2020, at 5:14 PM, Daniel P. Smith <dpsmith@apertussolutions.com> wrote:
> 
> On 6/1/20 3:39 PM, Andy Lutomirski wrote:
>>>> .
> 
> In other words, the log for the relaunch to attest what is currently
> running is really no less useful than using the first launch log to
> attest to the what was running in the first launch.
> 

Maybe it would help if you give some examples of what’s actually in this log and why anyone, Linux or otherwise, cares for any purpose other than debugging.  We’re talking about a log written by something like GRUB, right?  If so, I’m imagining things like:

GRUB: loading such-and-such module
GRUB: loading the other module
GRUB: loading Linux at /boot/vmlinuz-whatever
GRUB: about to do the DRTM launch. Bye-bye.

This is surely useful for debugging.  But, if I understand your security model correctly, it’s untrustworthy in the sense that this all comes from before the DRTM launch and it could have been tampered with by SMM code or even just a malicious USB stick.  Or even a malicious compromised kernel on the same machine. So you could hash this log into a PCR, but I don’t see what you’ve accomplished by doing so.

Or have I misunderstood what this log is?  Perhaps you’re talking about something else entirely.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher
  2020-06-02  0:49               ` Andy Lutomirski
@ 2020-06-02  1:29                 ` Daniel P. Smith
  0 siblings, 0 replies; 36+ messages in thread
From: Daniel P. Smith @ 2020-06-02  1:29 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Andy Lutomirski, Daniel Kiper, Lukasz Hawrylko, grub-devel, LKML,
	trenchboot-devel, X86 ML, alexander.burmashev, Andrew Cooper,
	Ard Biesheuvel, eric.snowberg, javierm, kanth.ghatraju,
	Konrad Rzeszutek Wilk, krystian.hebel, michal.zygowski,
	Matthew Garrett, phcoder, piotr.krol, Peter Jones,
	Ross Philipson

On 6/1/20 8:49 PM, Andy Lutomirski wrote:
> 
> 
>> On Jun 1, 2020, at 5:14 PM, Daniel P. Smith <dpsmith@apertussolutions.com> wrote:
>>
>> On 6/1/20 3:39 PM, Andy Lutomirski wrote:
>>>>> .
>>
>> In other words, the log for the relaunch to attest what is currently
>> running is really no less useful than using the first launch log to
>> attest to the what was running in the first launch.
>>
> 
> Maybe it would help if you give some examples of what’s actually in this log and why anyone, Linux or otherwise, cares for any purpose other than debugging.  We’re talking about a log written by something like GRUB, right?  If so, I’m imagining things like:
> 
> GRUB: loading such-and-such module
> GRUB: loading the other module
> GRUB: loading Linux at /boot/vmlinuz-whatever
> GRUB: about to do the DRTM launch. Bye-bye.
> 
> This is surely useful for debugging.  But, if I understand your security model correctly, it’s untrustworthy in the sense that this all comes from before the DRTM launch and it could have been tampered with by SMM code or even just a malicious USB stick.  Or even a malicious compromised kernel on the same machine. So you could hash this log into a PCR, but I don’t see what you’ve accomplished by doing so.
> 
> Or have I misunderstood what this log is?  Perhaps you’re talking about something else entirely.
> 

Oh I see! Yes we are discussing two different logs and yes there are two
"logs" in play here. The start of this thread by Lukasz was on the TPM
Event log. This is the log that is a record of TPM events for the DRTM
chain, you can see the equivalent for SRTM with `cat
/sys/kernel/security/tpm0/ascii_bios_measurements`(provided you system
configuration is set up for SRTM). The second log, which for lack of a
better name is the "debug log", is what you are referring to and is in
another proposal that just recently came out, "[BOOTLOADER SPECIFICATION
RFC] The bootloader log format for TrenchBoot"[1].

You are correct, the "debug log" is just filled with messages from
components during the DRTM launch chain. While relaunch is being kept in
mind as we work through getting first launch complete, not all aspects
have been considered. What happens to the debug log on relaunch has no
security relevance, as you called out earlier, and at this point I would
say is an exercise for those integrating relaunch when it becomes
available. I would expect them to treat it no different than the kmesg
and syslog buffers on kexec/reboot, some may opt to kept a historical
record and others will just let it disappear into the ether.

Apologies that we got disconnected, I hope we are in sync now.

[1] https://lists.gnu.org/archive/html/grub-devel/2020-05/msg00223.html


^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2020-06-02  1:29 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-04 23:21 [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 01/18] i386/msr: Merge rdmsr.h and wrmsr.h into msr.h Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 02/18] i386/msr: Rename grub_msr_read() and grub_msr_write() Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 03/18] i386/msr: Extract and improve MSR support detection code Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 04/18] i386/memory: Rename PAGE_SHIFT to GRUB_PAGE_SHIFT Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 05/18] i386/memory: Rename PAGE_SIZE to GRUB_PAGE_SIZE and make it global Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 06/18] mmap: Add grub_mmap_get_lowest() and grub_mmap_get_highest() Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 07/18] i386/tpm: Rename tpm module to tpm_verifier Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 08/18] i386/tpm: Add TPM TIS and CRB driver Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 09/18] efi: Make shim_lock GUID and protocol type public Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 10/18] efi: Return grub_efi_status_t from grub_efi_get_variable() Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 11/18] efi: Add a function to read EFI variables with attributes Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 12/18] i386/efi: Report UEFI Secure Boot status to the Linux kernel Daniel Kiper
2020-05-05 17:29   ` Matthew Garrett
2020-05-06 13:33     ` Daniel Kiper
2020-05-06 18:36       ` Matthew Garrett
2020-05-07 10:46         ` Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 13/18] i386/slaunch: Add basic platform support for secure launch Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 14/18] i386/txt: Add Intel TXT definitions header file Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 15/18] i386/txt: Add Intel TXT core implementation Daniel Kiper
2020-05-22 13:24   ` Krystian Hebel
2020-06-01 14:16     ` Ross Philipson
2020-05-04 23:21 ` [GRUB PATCH RFC 16/18] i386/txt: Add Intel TXT ACM module support Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 17/18] i386/txt: Add Intel TXT verification routines Daniel Kiper
2020-05-04 23:21 ` [GRUB PATCH RFC 18/18] i386/slaunch: Add secure launch framework and commands Daniel Kiper
2020-05-05 14:38 ` [GRUB PATCH RFC 00/18] i386: Intel TXT secure launcher Lukasz Hawrylko
2020-05-07 11:06   ` Daniel Kiper
2020-05-13 13:47     ` Lukasz Hawrylko
2020-06-01 15:32     ` Daniel P. Smith
2020-06-01 16:51       ` Andy Lutomirski
2020-06-01 17:56         ` Daniel P. Smith
2020-06-01 18:03           ` Ross Philipson
2020-06-01 19:39           ` Andy Lutomirski
2020-06-02  0:13             ` Daniel P. Smith
2020-06-02  0:49               ` Andy Lutomirski
2020-06-02  1:29                 ` Daniel P. Smith

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).