All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 00/14] x86: Trenchboot secure dynamic launch Linux kernel support
@ 2023-05-04 14:50 ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

The larger focus of the TrenchBoot project (https://github.com/TrenchBoot) is to
enhance the boot security and integrity in a unified manner. The first area of
focus has been on the Trusted Computing Group's Dynamic Launch for establishing
a hardware Root of Trust for Measurement, also know as DRTM (Dynamic Root of
Trust for Measurement). The project has been and continues to work on providing
a unified means to Dynamic Launch that is a cross-platform (Intel and AMD) and
cross-architecture (x86 and Arm), with our recent involvment in the upcoming
Arm DRTM specification. The order of introducing DRTM to the Linux kernel
follows the maturity of DRTM in the architectures. Intel's Trusted eXecution
Technology (TXT) is present today and only requires a preamble loader, e.g. a
boot loader, and an OS kernel that is TXT-aware. AMD DRTM implementation has
been present since the introduction of AMD-V but requires an additional
component that is AMD specific and referred to in the specification as the
Secure Loader, which the TrenchBoot project has an active prototype in
development. Finally Arm's implementation is in specification development stage
and the project is looking to support it when it becomes available.

This patchset provides detailed documentation of DRTM, the approach used for
adding the capbility, and relevant API/ABI documentation. In addition to the
documentation the patch set introduces Intel TXT support as the first platform
for Linux Secure Launch.

A quick note on terminology. The larger open source project itself is called
TrenchBoot, which is hosted on Github (links below). The kernel feature enabling
the use of Dynamic Launch technology is referred to as "Secure Launch" within
the kernel code. As such the prefixes sl_/SL_ or slaunch/SLAUNCH will be seen
in the code. The stub code discussed above is referred to as the SL stub.

The Secure Launch feature starts with patch #2. Patch #1 was authored by Arvind
Sankar. There is no further status on this patch at this point but
Secure Launch depends on it so it is included with the set.

Links:

The TrenchBoot project including documentation:

https://trenchboot.org

The TrenchBoot project on Github:

https://github.com/trenchboot

Intel TXT is documented in its own specification and in the SDM Instruction Set volume:

https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
https://software.intel.com/en-us/articles/intel-sdm

AMD SKINIT is documented in the System Programming manual:

https://www.amd.com/system/files/TechDocs/24593.pdf

GRUB2 pre-launch support branch (WIP):

https://github.com/TrenchBoot/grub/tree/grub-sl-fc-38-dlstub

Thanks
Ross Philipson and Daniel P. Smith

Changes in v2:

 - Modified 32b entry code to prevent causing relocations in the compressed
   kernel.
 - Dropped patches for compressed kernel TPM PCR extender.
 - Modified event log code to insert log delimiter events and not rely
   on TPM access.
 - Stop extending PCRs in the early Secure Launch stub code.
 - Removed Kconfig options for hash algorithms and use the algorithms the
   ACM used.
 - Match Secure Launch measurement algorithm use to those reported in the
   TPM 2.0 event log.
 - Read the TPM events out of the TPM and extend them into the PCRs using
   the mainline TPM driver. This is done in the late initcall module.
 - Allow use of alternate PCR 19 and 20 for post ACM measurements.
 - Add Kconfig constraints needed by Secure Launch (disable KASLR
   and add x2apic dependency).
 - Fix testing of SL_FLAGS when determining if Secure Launch is active
   and the architecture is TXT.
 - Use SYM_DATA_START_LOCAL macros in early entry point code.
 - Security audit changes:
   - Validate buffers passed to MLE do not overlap the MLE and are
     properly laid out.
   - Validate buffers and memory regions used by the MLE are
     protected by IOMMU PMRs.
 - Force IOMMU to not use passthrough mode during a Secure Launch.
 - Prevent KASLR use during a Secure Launch.

Changes in v3:

 - Introduce x86 documentation patch to provide background, overview
   and configuration/ABI information for the Secure Launch kernel
   feature.
 - Remove the IOMMU patch with special cases for disabling IOMMU
   passthrough. Configuring the IOMMU is now a documentation matter
   in the previously mentioned new patch.
 - Remove special case KASLR disabling code. Configuring KASLR is now
   a documentation matter in the previously mentioned new patch.
 - Fix incorrect panic on TXT public register read.
 - Properly handle and measure setup_indirect bootparams in the early
   launch code.
 - Use correct compressed kernel image base address when testing buffers
   in the early launch stub code. This bug was introduced by the changes
   to avoid relocation in the compressed kernel.
 - Use CPUID feature bits instead of CPUID vendor strings to determine
   if SMX mode is supported and the system is Intel.
 - Remove early NMI re-enable on the BSP. This can be safely done later
   on the BSP after an IDT is setup.

Changes in v4:
 - Expand the cover letter to provide more context to the order that DRTM
   support will be added.
 - Removed debug tracing in TPM request locality funciton and fixed
   local variable declarations.
 - Fixed missing break in default case in slmodule.c.
 - Reworded commit messages in patches 1 and 2 per suggestions.

Changes in v5:
 - Comprehensive documentation rewrite.
 - Use boot param loadflags to communicate Secure Launch status to
   kernel proper.
 - Fix incorrect check of X86_FEATURE_BIT_SMX bit.
 - Rename the alternate details and authorities PCR support.
 - Refactor the securityfs directory and file setup in slmodule.c.
 - Misc. cleanup from internal code reviews.
 - Use reverse fir tree format for variables.

Changes in v6:
 - Support for the new Secure Launch Resourse Table that standardizes
   the information passed and forms the ABI between the pre and post
   launch code.
 - Support for booting Linux through the EFI stub entry point and
   then being able to do a Secure Launch once EFI stub is done and EBS
   is called.
 - Updates to the documentation to reflect the previous two items listed.

Arvind Sankar (1):
  x86/boot: Place kernel_info at a fixed offset

Daniel P. Smith (2):
  x86: Add early SHA support for Secure Launch early measurements
  x86: Secure Launch late initcall platform module

Ross Philipson (11):
  Documentation/x86: Secure Launch kernel documentation
  x86: Secure Launch Kconfig
  x86: Secure Launch Resource Table header file
  x86: Secure Launch main header file
  x86: Secure Launch kernel early boot stub
  x86: Secure Launch kernel late boot stub
  x86: Secure Launch SMP bringup support
  kexec: Secure Launch kexec SEXIT support
  reboot: Secure Launch SEXIT support on reboot paths
  tpm: Allow locality 2 to be set when initializing the TPM for Secure
    Launch
  x86: EFI stub DRTM launch support for Secure Launch

 Documentation/arch/x86/boot.rst                    |  21 +
 Documentation/security/index.rst                   |   1 +
 Documentation/security/launch-integrity/index.rst  |  10 +
 .../security/launch-integrity/principles.rst       | 313 ++++++++++
 .../launch-integrity/secure_launch_details.rst     | 564 +++++++++++++++++
 .../launch-integrity/secure_launch_overview.rst    | 220 +++++++
 arch/x86/Kconfig                                   |  12 +
 arch/x86/boot/compressed/Makefile                  |   3 +
 arch/x86/boot/compressed/early_sha1.c              |  97 +++
 arch/x86/boot/compressed/early_sha1.h              |  17 +
 arch/x86/boot/compressed/early_sha256.c            |   7 +
 arch/x86/boot/compressed/head_64.S                 |  37 ++
 arch/x86/boot/compressed/kernel_info.S             |  53 +-
 arch/x86/boot/compressed/kernel_info.h             |  12 +
 arch/x86/boot/compressed/sl_main.c                 | 599 ++++++++++++++++++
 arch/x86/boot/compressed/sl_stub.S                 | 690 +++++++++++++++++++++
 arch/x86/boot/compressed/vmlinux.lds.S             |   6 +
 arch/x86/include/asm/realmode.h                    |   3 +
 arch/x86/include/uapi/asm/bootparam.h              |   1 +
 arch/x86/kernel/Makefile                           |   2 +
 arch/x86/kernel/asm-offsets.c                      |  20 +
 arch/x86/kernel/reboot.c                           |  10 +
 arch/x86/kernel/setup.c                            |   3 +
 arch/x86/kernel/slaunch.c                          | 566 +++++++++++++++++
 arch/x86/kernel/slmodule.c                         | 520 ++++++++++++++++
 arch/x86/kernel/smpboot.c                          |  86 +++
 arch/x86/realmode/rm/header.S                      |   3 +
 arch/x86/realmode/rm/trampoline_64.S               |  37 ++
 drivers/char/tpm/tpm-chip.c                        |   9 +-
 drivers/firmware/efi/libstub/x86-stub.c            |  55 ++
 drivers/iommu/intel/dmar.c                         |   4 +
 include/linux/slaunch.h                            | 513 +++++++++++++++
 include/linux/slr_table.h                          | 270 ++++++++
 kernel/kexec_core.c                                |   4 +
 lib/crypto/sha1.c                                  |   4 +
 lib/crypto/sha256.c                                |   8 +
 36 files changed, 4775 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/security/launch-integrity/index.rst
 create mode 100644 Documentation/security/launch-integrity/principles.rst
 create mode 100644 Documentation/security/launch-integrity/secure_launch_details.rst
 create mode 100644 Documentation/security/launch-integrity/secure_launch_overview.rst
 create mode 100644 arch/x86/boot/compressed/early_sha1.c
 create mode 100644 arch/x86/boot/compressed/early_sha1.h
 create mode 100644 arch/x86/boot/compressed/early_sha256.c
 create mode 100644 arch/x86/boot/compressed/kernel_info.h
 create mode 100644 arch/x86/boot/compressed/sl_main.c
 create mode 100644 arch/x86/boot/compressed/sl_stub.S
 create mode 100644 arch/x86/kernel/slaunch.c
 create mode 100644 arch/x86/kernel/slmodule.c
 create mode 100644 include/linux/slaunch.h
 create mode 100644 include/linux/slr_table.h

-- 
1.8.3.1


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

* [PATCH v6 00/14] x86: Trenchboot secure dynamic launch Linux kernel support
@ 2023-05-04 14:50 ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

The larger focus of the TrenchBoot project (https://github.com/TrenchBoot) is to
enhance the boot security and integrity in a unified manner. The first area of
focus has been on the Trusted Computing Group's Dynamic Launch for establishing
a hardware Root of Trust for Measurement, also know as DRTM (Dynamic Root of
Trust for Measurement). The project has been and continues to work on providing
a unified means to Dynamic Launch that is a cross-platform (Intel and AMD) and
cross-architecture (x86 and Arm), with our recent involvment in the upcoming
Arm DRTM specification. The order of introducing DRTM to the Linux kernel
follows the maturity of DRTM in the architectures. Intel's Trusted eXecution
Technology (TXT) is present today and only requires a preamble loader, e.g. a
boot loader, and an OS kernel that is TXT-aware. AMD DRTM implementation has
been present since the introduction of AMD-V but requires an additional
component that is AMD specific and referred to in the specification as the
Secure Loader, which the TrenchBoot project has an active prototype in
development. Finally Arm's implementation is in specification development stage
and the project is looking to support it when it becomes available.

This patchset provides detailed documentation of DRTM, the approach used for
adding the capbility, and relevant API/ABI documentation. In addition to the
documentation the patch set introduces Intel TXT support as the first platform
for Linux Secure Launch.

A quick note on terminology. The larger open source project itself is called
TrenchBoot, which is hosted on Github (links below). The kernel feature enabling
the use of Dynamic Launch technology is referred to as "Secure Launch" within
the kernel code. As such the prefixes sl_/SL_ or slaunch/SLAUNCH will be seen
in the code. The stub code discussed above is referred to as the SL stub.

The Secure Launch feature starts with patch #2. Patch #1 was authored by Arvind
Sankar. There is no further status on this patch at this point but
Secure Launch depends on it so it is included with the set.

Links:

The TrenchBoot project including documentation:

https://trenchboot.org

The TrenchBoot project on Github:

https://github.com/trenchboot

Intel TXT is documented in its own specification and in the SDM Instruction Set volume:

https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
https://software.intel.com/en-us/articles/intel-sdm

AMD SKINIT is documented in the System Programming manual:

https://www.amd.com/system/files/TechDocs/24593.pdf

GRUB2 pre-launch support branch (WIP):

https://github.com/TrenchBoot/grub/tree/grub-sl-fc-38-dlstub

Thanks
Ross Philipson and Daniel P. Smith

Changes in v2:

 - Modified 32b entry code to prevent causing relocations in the compressed
   kernel.
 - Dropped patches for compressed kernel TPM PCR extender.
 - Modified event log code to insert log delimiter events and not rely
   on TPM access.
 - Stop extending PCRs in the early Secure Launch stub code.
 - Removed Kconfig options for hash algorithms and use the algorithms the
   ACM used.
 - Match Secure Launch measurement algorithm use to those reported in the
   TPM 2.0 event log.
 - Read the TPM events out of the TPM and extend them into the PCRs using
   the mainline TPM driver. This is done in the late initcall module.
 - Allow use of alternate PCR 19 and 20 for post ACM measurements.
 - Add Kconfig constraints needed by Secure Launch (disable KASLR
   and add x2apic dependency).
 - Fix testing of SL_FLAGS when determining if Secure Launch is active
   and the architecture is TXT.
 - Use SYM_DATA_START_LOCAL macros in early entry point code.
 - Security audit changes:
   - Validate buffers passed to MLE do not overlap the MLE and are
     properly laid out.
   - Validate buffers and memory regions used by the MLE are
     protected by IOMMU PMRs.
 - Force IOMMU to not use passthrough mode during a Secure Launch.
 - Prevent KASLR use during a Secure Launch.

Changes in v3:

 - Introduce x86 documentation patch to provide background, overview
   and configuration/ABI information for the Secure Launch kernel
   feature.
 - Remove the IOMMU patch with special cases for disabling IOMMU
   passthrough. Configuring the IOMMU is now a documentation matter
   in the previously mentioned new patch.
 - Remove special case KASLR disabling code. Configuring KASLR is now
   a documentation matter in the previously mentioned new patch.
 - Fix incorrect panic on TXT public register read.
 - Properly handle and measure setup_indirect bootparams in the early
   launch code.
 - Use correct compressed kernel image base address when testing buffers
   in the early launch stub code. This bug was introduced by the changes
   to avoid relocation in the compressed kernel.
 - Use CPUID feature bits instead of CPUID vendor strings to determine
   if SMX mode is supported and the system is Intel.
 - Remove early NMI re-enable on the BSP. This can be safely done later
   on the BSP after an IDT is setup.

Changes in v4:
 - Expand the cover letter to provide more context to the order that DRTM
   support will be added.
 - Removed debug tracing in TPM request locality funciton and fixed
   local variable declarations.
 - Fixed missing break in default case in slmodule.c.
 - Reworded commit messages in patches 1 and 2 per suggestions.

Changes in v5:
 - Comprehensive documentation rewrite.
 - Use boot param loadflags to communicate Secure Launch status to
   kernel proper.
 - Fix incorrect check of X86_FEATURE_BIT_SMX bit.
 - Rename the alternate details and authorities PCR support.
 - Refactor the securityfs directory and file setup in slmodule.c.
 - Misc. cleanup from internal code reviews.
 - Use reverse fir tree format for variables.

Changes in v6:
 - Support for the new Secure Launch Resourse Table that standardizes
   the information passed and forms the ABI between the pre and post
   launch code.
 - Support for booting Linux through the EFI stub entry point and
   then being able to do a Secure Launch once EFI stub is done and EBS
   is called.
 - Updates to the documentation to reflect the previous two items listed.

Arvind Sankar (1):
  x86/boot: Place kernel_info at a fixed offset

Daniel P. Smith (2):
  x86: Add early SHA support for Secure Launch early measurements
  x86: Secure Launch late initcall platform module

Ross Philipson (11):
  Documentation/x86: Secure Launch kernel documentation
  x86: Secure Launch Kconfig
  x86: Secure Launch Resource Table header file
  x86: Secure Launch main header file
  x86: Secure Launch kernel early boot stub
  x86: Secure Launch kernel late boot stub
  x86: Secure Launch SMP bringup support
  kexec: Secure Launch kexec SEXIT support
  reboot: Secure Launch SEXIT support on reboot paths
  tpm: Allow locality 2 to be set when initializing the TPM for Secure
    Launch
  x86: EFI stub DRTM launch support for Secure Launch

 Documentation/arch/x86/boot.rst                    |  21 +
 Documentation/security/index.rst                   |   1 +
 Documentation/security/launch-integrity/index.rst  |  10 +
 .../security/launch-integrity/principles.rst       | 313 ++++++++++
 .../launch-integrity/secure_launch_details.rst     | 564 +++++++++++++++++
 .../launch-integrity/secure_launch_overview.rst    | 220 +++++++
 arch/x86/Kconfig                                   |  12 +
 arch/x86/boot/compressed/Makefile                  |   3 +
 arch/x86/boot/compressed/early_sha1.c              |  97 +++
 arch/x86/boot/compressed/early_sha1.h              |  17 +
 arch/x86/boot/compressed/early_sha256.c            |   7 +
 arch/x86/boot/compressed/head_64.S                 |  37 ++
 arch/x86/boot/compressed/kernel_info.S             |  53 +-
 arch/x86/boot/compressed/kernel_info.h             |  12 +
 arch/x86/boot/compressed/sl_main.c                 | 599 ++++++++++++++++++
 arch/x86/boot/compressed/sl_stub.S                 | 690 +++++++++++++++++++++
 arch/x86/boot/compressed/vmlinux.lds.S             |   6 +
 arch/x86/include/asm/realmode.h                    |   3 +
 arch/x86/include/uapi/asm/bootparam.h              |   1 +
 arch/x86/kernel/Makefile                           |   2 +
 arch/x86/kernel/asm-offsets.c                      |  20 +
 arch/x86/kernel/reboot.c                           |  10 +
 arch/x86/kernel/setup.c                            |   3 +
 arch/x86/kernel/slaunch.c                          | 566 +++++++++++++++++
 arch/x86/kernel/slmodule.c                         | 520 ++++++++++++++++
 arch/x86/kernel/smpboot.c                          |  86 +++
 arch/x86/realmode/rm/header.S                      |   3 +
 arch/x86/realmode/rm/trampoline_64.S               |  37 ++
 drivers/char/tpm/tpm-chip.c                        |   9 +-
 drivers/firmware/efi/libstub/x86-stub.c            |  55 ++
 drivers/iommu/intel/dmar.c                         |   4 +
 include/linux/slaunch.h                            | 513 +++++++++++++++
 include/linux/slr_table.h                          | 270 ++++++++
 kernel/kexec_core.c                                |   4 +
 lib/crypto/sha1.c                                  |   4 +
 lib/crypto/sha256.c                                |   8 +
 36 files changed, 4775 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/security/launch-integrity/index.rst
 create mode 100644 Documentation/security/launch-integrity/principles.rst
 create mode 100644 Documentation/security/launch-integrity/secure_launch_details.rst
 create mode 100644 Documentation/security/launch-integrity/secure_launch_overview.rst
 create mode 100644 arch/x86/boot/compressed/early_sha1.c
 create mode 100644 arch/x86/boot/compressed/early_sha1.h
 create mode 100644 arch/x86/boot/compressed/early_sha256.c
 create mode 100644 arch/x86/boot/compressed/kernel_info.h
 create mode 100644 arch/x86/boot/compressed/sl_main.c
 create mode 100644 arch/x86/boot/compressed/sl_stub.S
 create mode 100644 arch/x86/kernel/slaunch.c
 create mode 100644 arch/x86/kernel/slmodule.c
 create mode 100644 include/linux/slaunch.h
 create mode 100644 include/linux/slr_table.h

-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 01/14] x86/boot: Place kernel_info at a fixed offset
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

From: Arvind Sankar <nivedita@alum.mit.edu>

There are use cases for storing the offset of a symbol in kernel_info.
For example, the trenchboot series [0] needs to store the offset of the
Measured Launch Environment header in kernel_info.

Since commit (note: commit ID from tip/master)

commit 527afc212231 ("x86/boot: Check that there are no run-time relocations")

run-time relocations are not allowed in the compressed kernel, so simply
using the symbol in kernel_info, as

	.long	symbol

will cause a linker error because this is not position-independent.

With kernel_info being a separate object file and in a different section
from startup_32, there is no way to calculate the offset of a symbol
from the start of the image in a position-independent way.

To enable such use cases, put kernel_info into its own section which is
placed at a predetermined offset (KERNEL_INFO_OFFSET) via the linker
script. This will allow calculating the symbol offset in a
position-independent way, by adding the offset from the start of
kernel_info to KERNEL_INFO_OFFSET.

Ensure that kernel_info is aligned, and use the SYM_DATA.* macros
instead of bare labels. This stores the size of the kernel_info
structure in the ELF symbol table.

Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu>
Cc: Ross Philipson <ross.philipson@oracle.com>
Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/boot/compressed/kernel_info.S | 19 +++++++++++++++----
 arch/x86/boot/compressed/kernel_info.h | 12 ++++++++++++
 arch/x86/boot/compressed/vmlinux.lds.S |  6 ++++++
 3 files changed, 33 insertions(+), 4 deletions(-)
 create mode 100644 arch/x86/boot/compressed/kernel_info.h

diff --git a/arch/x86/boot/compressed/kernel_info.S b/arch/x86/boot/compressed/kernel_info.S
index f818ee8..c18f071 100644
--- a/arch/x86/boot/compressed/kernel_info.S
+++ b/arch/x86/boot/compressed/kernel_info.S
@@ -1,12 +1,23 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 
+#include <linux/linkage.h>
 #include <asm/bootparam.h>
+#include "kernel_info.h"
 
-	.section ".rodata.kernel_info", "a"
+/*
+ * If a field needs to hold the offset of a symbol from the start
+ * of the image, use the macro below, eg
+ *	.long	rva(symbol)
+ * This will avoid creating run-time relocations, which are not
+ * allowed in the compressed kernel.
+ */
+
+#define rva(X) (((X) - kernel_info) + KERNEL_INFO_OFFSET)
 
-	.global kernel_info
+	.section ".rodata.kernel_info", "a"
 
-kernel_info:
+	.balign	16
+SYM_DATA_START(kernel_info)
 	/* Header, Linux top (structure). */
 	.ascii	"LToP"
 	/* Size. */
@@ -19,4 +30,4 @@ kernel_info:
 
 kernel_info_var_len_data:
 	/* Empty for time being... */
-kernel_info_end:
+SYM_DATA_END_LABEL(kernel_info, SYM_L_LOCAL, kernel_info_end)
diff --git a/arch/x86/boot/compressed/kernel_info.h b/arch/x86/boot/compressed/kernel_info.h
new file mode 100644
index 0000000..c127f84
--- /dev/null
+++ b/arch/x86/boot/compressed/kernel_info.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef BOOT_COMPRESSED_KERNEL_INFO_H
+#define BOOT_COMPRESSED_KERNEL_INFO_H
+
+#ifdef CONFIG_X86_64
+#define KERNEL_INFO_OFFSET 0x500
+#else /* 32-bit */
+#define KERNEL_INFO_OFFSET 0x100
+#endif
+
+#endif /* BOOT_COMPRESSED_KERNEL_INFO_H */
diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
index b22f34b..265c88f 100644
--- a/arch/x86/boot/compressed/vmlinux.lds.S
+++ b/arch/x86/boot/compressed/vmlinux.lds.S
@@ -7,6 +7,7 @@ OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT)
 
 #include <asm/cache.h>
 #include <asm/page_types.h>
+#include "kernel_info.h"
 
 #ifdef CONFIG_X86_64
 OUTPUT_ARCH(i386:x86-64)
@@ -27,6 +28,11 @@ SECTIONS
 		HEAD_TEXT
 		_ehead = . ;
 	}
+	.rodata.kernel_info KERNEL_INFO_OFFSET : {
+		*(.rodata.kernel_info)
+	}
+	ASSERT(ABSOLUTE(kernel_info) == KERNEL_INFO_OFFSET, "kernel_info at bad address!")
+
 	.rodata..compressed : {
 		*(.rodata..compressed)
 	}
-- 
1.8.3.1


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

* [PATCH v6 01/14] x86/boot: Place kernel_info at a fixed offset
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

From: Arvind Sankar <nivedita@alum.mit.edu>

There are use cases for storing the offset of a symbol in kernel_info.
For example, the trenchboot series [0] needs to store the offset of the
Measured Launch Environment header in kernel_info.

Since commit (note: commit ID from tip/master)

commit 527afc212231 ("x86/boot: Check that there are no run-time relocations")

run-time relocations are not allowed in the compressed kernel, so simply
using the symbol in kernel_info, as

	.long	symbol

will cause a linker error because this is not position-independent.

With kernel_info being a separate object file and in a different section
from startup_32, there is no way to calculate the offset of a symbol
from the start of the image in a position-independent way.

To enable such use cases, put kernel_info into its own section which is
placed at a predetermined offset (KERNEL_INFO_OFFSET) via the linker
script. This will allow calculating the symbol offset in a
position-independent way, by adding the offset from the start of
kernel_info to KERNEL_INFO_OFFSET.

Ensure that kernel_info is aligned, and use the SYM_DATA.* macros
instead of bare labels. This stores the size of the kernel_info
structure in the ELF symbol table.

Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu>
Cc: Ross Philipson <ross.philipson@oracle.com>
Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/boot/compressed/kernel_info.S | 19 +++++++++++++++----
 arch/x86/boot/compressed/kernel_info.h | 12 ++++++++++++
 arch/x86/boot/compressed/vmlinux.lds.S |  6 ++++++
 3 files changed, 33 insertions(+), 4 deletions(-)
 create mode 100644 arch/x86/boot/compressed/kernel_info.h

diff --git a/arch/x86/boot/compressed/kernel_info.S b/arch/x86/boot/compressed/kernel_info.S
index f818ee8..c18f071 100644
--- a/arch/x86/boot/compressed/kernel_info.S
+++ b/arch/x86/boot/compressed/kernel_info.S
@@ -1,12 +1,23 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 
+#include <linux/linkage.h>
 #include <asm/bootparam.h>
+#include "kernel_info.h"
 
-	.section ".rodata.kernel_info", "a"
+/*
+ * If a field needs to hold the offset of a symbol from the start
+ * of the image, use the macro below, eg
+ *	.long	rva(symbol)
+ * This will avoid creating run-time relocations, which are not
+ * allowed in the compressed kernel.
+ */
+
+#define rva(X) (((X) - kernel_info) + KERNEL_INFO_OFFSET)
 
-	.global kernel_info
+	.section ".rodata.kernel_info", "a"
 
-kernel_info:
+	.balign	16
+SYM_DATA_START(kernel_info)
 	/* Header, Linux top (structure). */
 	.ascii	"LToP"
 	/* Size. */
@@ -19,4 +30,4 @@ kernel_info:
 
 kernel_info_var_len_data:
 	/* Empty for time being... */
-kernel_info_end:
+SYM_DATA_END_LABEL(kernel_info, SYM_L_LOCAL, kernel_info_end)
diff --git a/arch/x86/boot/compressed/kernel_info.h b/arch/x86/boot/compressed/kernel_info.h
new file mode 100644
index 0000000..c127f84
--- /dev/null
+++ b/arch/x86/boot/compressed/kernel_info.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef BOOT_COMPRESSED_KERNEL_INFO_H
+#define BOOT_COMPRESSED_KERNEL_INFO_H
+
+#ifdef CONFIG_X86_64
+#define KERNEL_INFO_OFFSET 0x500
+#else /* 32-bit */
+#define KERNEL_INFO_OFFSET 0x100
+#endif
+
+#endif /* BOOT_COMPRESSED_KERNEL_INFO_H */
diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
index b22f34b..265c88f 100644
--- a/arch/x86/boot/compressed/vmlinux.lds.S
+++ b/arch/x86/boot/compressed/vmlinux.lds.S
@@ -7,6 +7,7 @@ OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT)
 
 #include <asm/cache.h>
 #include <asm/page_types.h>
+#include "kernel_info.h"
 
 #ifdef CONFIG_X86_64
 OUTPUT_ARCH(i386:x86-64)
@@ -27,6 +28,11 @@ SECTIONS
 		HEAD_TEXT
 		_ehead = . ;
 	}
+	.rodata.kernel_info KERNEL_INFO_OFFSET : {
+		*(.rodata.kernel_info)
+	}
+	ASSERT(ABSOLUTE(kernel_info) == KERNEL_INFO_OFFSET, "kernel_info at bad address!")
+
 	.rodata..compressed : {
 		*(.rodata..compressed)
 	}
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

Introduce background, overview and configuration/ABI information
for the Secure Launch kernel feature.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 Documentation/security/index.rst                   |   1 +
 Documentation/security/launch-integrity/index.rst  |  10 +
 .../security/launch-integrity/principles.rst       | 313 ++++++++++++
 .../launch-integrity/secure_launch_details.rst     | 564 +++++++++++++++++++++
 .../launch-integrity/secure_launch_overview.rst    | 220 ++++++++
 5 files changed, 1108 insertions(+)
 create mode 100644 Documentation/security/launch-integrity/index.rst
 create mode 100644 Documentation/security/launch-integrity/principles.rst
 create mode 100644 Documentation/security/launch-integrity/secure_launch_details.rst
 create mode 100644 Documentation/security/launch-integrity/secure_launch_overview.rst

diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst
index 6ed8d2f..fade37e 100644
--- a/Documentation/security/index.rst
+++ b/Documentation/security/index.rst
@@ -18,3 +18,4 @@ Security Documentation
    digsig
    landlock
    secrets/index
+   launch-integrity/index
diff --git a/Documentation/security/launch-integrity/index.rst b/Documentation/security/launch-integrity/index.rst
new file mode 100644
index 0000000..28eed91d
--- /dev/null
+++ b/Documentation/security/launch-integrity/index.rst
@@ -0,0 +1,10 @@
+=====================================
+System Launch Integrity documentation
+=====================================
+
+.. toctree::
+
+   principles
+   secure_launch_overview
+   secure_launch_details
+
diff --git a/Documentation/security/launch-integrity/principles.rst b/Documentation/security/launch-integrity/principles.rst
new file mode 100644
index 0000000..73cf063
--- /dev/null
+++ b/Documentation/security/launch-integrity/principles.rst
@@ -0,0 +1,313 @@
+=======================
+System Launch Integrity
+=======================
+
+This document serves to establish a common understanding of what is system
+launch, the integrity concern for system launch, and why using a Root of Trust
+(RoT) from a Dynamic Launch may be desired. Through out this document
+terminology from the Trusted Computing Group (TCG) and National Institue for
+Science and Technology (NIST) is used to ensure a vendor nutrual language is
+used to describe and reference security-related concepts.
+
+System Launch
+=============
+
+There is a tendency to only consider the classical power-on boot as the only
+means to launch an Operating System (OS) on a computer system, but in fact most
+modern processors support two methods to launch the system. To provide clarity a
+common definition of a system launch should be established. This definition is
+that a during a single power life cycle of a system, a System Launch consists
+of an initialization event, typically in hardware, that is followed by an
+executing software payload that takes the system from the initialized state to
+a running state. Driven by the Trusted Computing Group (TCG) architecture,
+modern processors are able to support two methods to launch a system, these two
+types of system launch are known as Static Launch and Dynamic Launch.
+
+Static Launch
+-------------
+
+Static launch is the system launch associated with the power cycle of the CPU.
+Thus static launch refers to the classical power-on boot where the
+initialization event is the release of the CPU from reset and the system
+firmware is the software payload that brings the system up to a running state.
+Since static launch is the system launch associated with the beginning of the
+power lifecycle of a system, it is therefore a fixed, one-time system launch.
+It is because of this that static launch is referred to and thought of as being
+"static".
+
+Dynamic Launch
+--------------
+
+Modern CPUs architectures provides a mechanism to re-initialize the system to a
+"known good" state without requiring a power event. This re-initialization
+event is the event for a dynamic launch and is referred to as the Dynamic
+Launch Event (DLE). The DLE functions by accepting a software payload, referred
+to as the Dynamic Configuration Environment (DCE), that execution is handed to
+after the DLE is invoked. The DCE is responsible for bringing the system back
+to a running state. Since the dynamic launch is not tied to a power event like
+the static launch, this enables a dynamic launch to be initiated at any time
+and multiple times during a single power life cycle. This dynamism is the
+reasoning behind referring to this system launch as being dynamic.
+
+Because a dynamic launch can be conducted at any time during a single power
+life cycle, they are classified into one of two types, an early launch or a
+late launch.
+
+:Early Launch: When a dynamic launch is used as a transition from a static
+   launch chain to the final Operating System.
+
+:Late Launch: The usage of a dynamic launch by an executing Operating System to
+   transition to a “known good” state to perform one or more operations, e.g. to
+   launch into a new Operating System.
+
+System Integrity
+================
+
+A computer system can be considered a collection of mechanisms that work
+together to produce a result. The assurance that the mechanisms are functioning
+correctly and producing the expected result is the integrity of the system. To
+ensure a system's integrity there are a subset of these mechanisms, commonly
+referred to as security mechanisms, that are present to help ensure the system
+produces the expected result or at least detect the potential of an unexpected
+result may have happened. Since the security mechanisms are relied upon to
+ensue the integrity of the system, these mechanisms are trusted. Upon
+inspection these security mechanisms each have a set of properties and these
+properties can be evaluated to determine how susceptible a mechanism might be
+to failure. This assessment is referred to as the Strength of Mechanism and for
+trusted mechanism enables for the trustworthiness of that mechanism to be
+quantified.
+
+For software systems there are two system states for which the integrity is
+critical, when the software is loaded into memory and when the software is
+executing on the hardware. Ensuring that the expected software is load into
+memory is referred to as load-time integrity while ensuring that the software
+executing is the expected software is the runtime integrity of that software.
+
+Load-time Integrity
+-------------------
+
+It is critical to understand what load-time integrity establishes about a
+system and what is assumed, i.e. what is being trusted. Load-time integrity is
+when a trusted entity, i.e. an entity with an assumed integrity, takes an
+action to assess an entity being loaded into memory before it is used. A
+variety of mechanisms may be used to conduct the assessment, each with
+different properties. A particular property is whether the mechanism creates an
+evidence of the assessment. Often either cryptographic signature checking or
+hashing are the common assessment operations used.
+
+A signature checking assessment functions by requiring a representation of the
+accepted authorities and uses those representations to assess if the entity has
+been signed by an accepted authority. The benefit to this process is that
+assessment process includes an adjudication of the assessment. The drawbacks
+are that 1) the adjudication is susceptible to tampering by the Trusted
+Computing Base (TCB), 2) there is no evidence to assert that an untampered
+adjudication was completed, and 3) the system must be an active participant in
+the key management infrastructure.
+
+A cryptographic hashing assessment does not adjudicate the assessment but
+instead generates evidence of the assessment to be adjudicated independently.
+The benefits to this approach is that the assessment may be simple such that it
+is able to be implemented as an immutable mechanism, e.g. in hardware.
+Additionally it is possible for the adjudication to be conducted where it
+cannot be tampered with by the TCB. The drawback is that a compromised
+environment will be allowed to execute until an adjudication can be completed.
+
+Ultimately load-time integrity provides confidence that the correct entity was
+loaded and in the absence of a run-time integrity mechanism assumes, i.e
+trusts, that the entity will never become corrupted.
+
+Runtime Integrity
+-----------------
+
+Runtime integrity in the general sense is when a trusted entity makes an
+assessment of an entity at any point in time during the assessed entity's
+execution. A more concrete explanation is the taking of an integrity assessment
+of an active process executing on the system at any point during the process'
+execution. Often the load-time integrity of an operating system's user-space,
+i.e. the operating environment, is confused to be the runtime integrity of the
+system since it is an integrity assessment of the "runtime" software. The
+reality is that actual runtime integrity is a very difficult problem and thus
+not very many solutions are public and/or available. One example of a runtime
+integrity solution would be John Hopkins Advanced Physics Labratory's (APL)
+Linux Kernel Integrity Module (LKIM).
+
+Trust Chains
+============
+
+Bulding upon the understanding of security mechanisms to establish load-time
+integrity of an entity, it is possible to chain together load-time integrity
+assessments to establish the integrity of the whole system. This process is
+known as transitive trust and provides the concept of building a chain of
+load-time integrity assessments, commonly referred to as a trust chain. These
+assessments may be used to adjudicate the load-time integrity of the whole
+system. This trust chain is started by a trusted entity that does the first
+assessment. This first entity is referred to as the Root of Trust(RoT) with the
+entities name being derived from the mechanism used for the assessment, i.e.
+RoT for Verification (RTV) and RoT for Measurement (RTM).
+
+A trust chain is itself a mechanism, specifically a mechanism of mechanisms,
+and therefore it too has a Strength of Mechanism. The factors that contribute
+to a trust chain's strength are,
+
+  - The strength of the chain's RoT
+  - The strength of each member of the trust chain
+  - The length, i.e. the number of members, of the chain
+
+Therefore to provide the strongest trust chains, they should start with a
+strong RoT and should consist of members being of low complexity and minimizing
+the number of members participating as is possible. In a more colloquial sense,
+a trust chain is only as strong as it weakests link and more links increase
+the probability of a weak link.
+
+Dynamic Launch Components
+=========================
+
+The TCG architecture for dynamic launch is composed of a component series that
+are used to setup and then carry out the launch. These components work together
+to construct a RTM trust chain that is rooted in the dynamic launch and thus
+commonly referred to as the Dynamic Root of Trust for Measurement (DRTM) chain.
+
+What follows is a brief explanation of each component in execution order. A
+subset of these components are what establishes the dynamic launch's trust
+chain.
+
+Dynamic Configuration Environment Preamble
+------------------------------------------
+
+The Dynamic Configuration Environment (DCE) Preamble is responsible for setting
+up the system environment in preparation for a dynamic launch. The DCE Preamble
+is not a part of the DRTM trust chain.
+
+Dynamic Launch Event
+--------------------
+
+The dynamic launch event is the event, typically a CPU instruction, that triggers
+the system's dynamic launch mechanism to begin the launch. The dynamic launch
+mechanism is also the RoT for the DRTM trust chain.
+
+Dynamic Configuration Environment
+---------------------------------
+
+The dynamic launch mechanism may have resulted in a reset of a portion of the
+system. To bring the system back to an adequate state for system software the
+dynamic launch will hand over control to the DCE. Prior to handing over this
+control, the dynamic launch will measure the DCE. Once the DCE is complete it
+will proceed to measure and then execute the Dynamic Launch Measured
+Environment (DLME).
+
+Dynamic Launch Measured Environment
+-----------------------------------
+
+The DLME is the first system kernel to have control of the system but may not
+be the last. Depending on the usage and configuration, the DLME may be the
+final/target operating system or it may be a boot loader that will load the
+final/target operating system.
+
+Why DRTM
+========
+
+It is a fact that DRTM increases the load-time integrity of the system by
+providing a trust chain that has an immutable hardware RoT, uses a limited
+number of small, special purpose code to establish the trust chain that starts
+the target operating system. As mentioned in the Trust Chain section, these are
+the main three factors in driving up the strength of a trust chain. As can been
+seen by the BootHole exploit, which in fact did not effect the integrity of
+DRTM solutions, the sophistication of attacks targeting system launch is at an
+all time high. There is no reason a system should not employ every integrity
+measure hardware makes available. This is the crux of a defense-in-depth
+approach to system security. In the past the now closed SMI gap was often
+pointed to as invalidating DRTM, which in fact was nothing but a strawman
+argument. As has continued to be demonstrated, if/when SMM is corrupted it can
+always circumvent all load-time integrity, SRTM and DRTM, because it is a
+run-time integrity problem. Regardless, Intel and AMD have both deployed
+runtime integrity for SMI and SMM which is tied directly to DRTM such that this
+perceived deficiency is now non-existent and the world is moving forward with
+an expectation that DRTM must be present.
+
+Glossary
+========
+
+.. glossary::
+  integrity
+    Guarding against improper information modification or destruction, and
+    includes ensuring information non-repudiation and authenticity.
+
+    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+  mechanism
+    A process or system that is used to produce a particular result.
+
+    - NIST Special Publication 800-160 (VOLUME 1 ) - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-160v1.pdf
+
+  risk
+    A measure of the extent to which an entity is threatened by a potential
+    circumstance or event, and typically a function of: (i) the adverse impacts
+    that would arise if the circumstance or event occurs; and (ii) the
+    likelihood of occurrence.
+
+    - NIST SP 800-30 Rev. 1 - https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-30r1.pdf
+
+  security mechanism
+    A device or function designed to provide one or more security services
+    usually rated in terms of strength of service and assurance of the design.
+
+    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+  Strength of Mechanism
+    A scale for measuring the relative strength of a security mechanism
+
+    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+  transitive trust
+    Also known as "Inductive Trust", in this process a Root of Trust gives a
+    trustworthy description of a second group of functions. Based on this
+    description, an interested entity can determine the trust it is to place in
+    this second group of functions. If the interested entity determines that
+    the trust level of the second group of functions is acceptable, the trust
+    boundary is extended from the Root of Trust to include the second group of
+    functions. In this case, the process can be iterated. The second group of
+    functions can give a trustworthy description of the third group of
+    functions, etc. Transitive trust is used to provide a trustworthy
+    description of platform characteristics, and also to prove that
+    non-migratable keys are non-migratable
+
+    - TCG Glossary - https://trustedcomputinggroup.org/wp-content/uploads/TCG-Glossary-V1.1-Rev-1.0.pdf
+
+  trust
+    The confidence one element has in another that the second element will
+    behave as expected`
+
+    - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
+
+  trust anchor
+    An authoritative entity for which trust is assumed.
+
+    - NIST SP 800-57 Part 1 Rev. 5 - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf
+
+  trusted
+    An element that another element relies upon to fulfill critical
+    requirements on its behalf.
+
+    - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
+
+  trusted computing base (TCB)
+    Totality of protection mechanisms within a computer system, including
+    hardware, firmware, and software, the combination responsible for enforcing
+    a security policy.
+
+    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+  trusted computer system
+    A system that has the necessary security functions and assurance that the
+    security policy will be enforced and that can process a range of
+    information sensitivities (i.e. classified, controlled unclassified
+    information (CUI), or unclassified public information) simultaneously.
+
+    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+  trustworthiness
+    The attribute of a person or enterprise that provides confidence to others
+    of the qualifications, capabilities, and reliability of that entity to
+    perform specific tasks and fulfill assigned responsibilities.
+
+    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
diff --git a/Documentation/security/launch-integrity/secure_launch_details.rst b/Documentation/security/launch-integrity/secure_launch_details.rst
new file mode 100644
index 0000000..2e71543
--- /dev/null
+++ b/Documentation/security/launch-integrity/secure_launch_details.rst
@@ -0,0 +1,564 @@
+===================================
+Secure Launch Config and Interfaces
+===================================
+
+Configuration
+=============
+
+The settings to enable Secure Launch using Kconfig are under::
+
+  "Processor type and features" --> "Secure Launch support"
+
+A kernel with this option enabled can still be booted using other supported
+methods.
+
+To reduce the Trusted Computing Base (TCB) of the MLE [1]_, the build
+configuration should be pared down as narrowly as one's use case allows.
+The fewer drivers (less active hardware) and features reduces the attack
+surface. E.g. in the extreme, the MLE could only have local disk access
+and no other hardware support. Or only network access for remote attestation.
+
+It is also desirable if possible to embed the initrd used with the MLE kernel
+image to reduce complexity.
+
+The following are a few important configuration necessities to always consider:
+
+KASLR Configuration
+-------------------
+
+Secure Launch does not interoperate with KASLR. If possible, the MLE should be
+built with KASLR disabled::
+
+  "Processor type and features" -->
+      "Build a relocatable kernel" -->
+          "Randomize the address of the kernel image (KASLR) [ ]"
+
+This unsets the Kconfig value CONFIG_RANDOMIZE_BASE.
+
+If not possible, KASLR must be disabled on the kernel command line when doing
+a Secure Launch as follows::
+
+  nokaslr
+
+IOMMU Configuration
+-------------------
+
+When doing a Secure Launch, the IOMMU should always be enabled and the drivers
+loaded. However, IOMMU passthrough mode should never be used. This leaves the
+MLE completely exposed to DMA after the PMR's [2]_ are disabled. The current default
+mode is to use IOMMU in lazy translated mode but strict translated mode is the preferred
+IOMMU mode and this should be selected in the build configuration::
+
+  "Device Drivers" -->
+      "IOMMU Hardware Support" -->
+          "IOMMU default domain type" -->
+              "(X) Translated - Strict"
+
+In addition, the Intel IOMMU should be on by default. The following sets this as the
+default in the build configuration::
+
+  "Device Drivers" -->
+      "IOMMU Hardware Support" -->
+          "Support for Intel IOMMU using DMA Remapping Devices [*]"
+
+and::
+
+  "Device Drivers" -->
+      "IOMMU Hardware Support" -->
+          "Support for Intel IOMMU using DMA Remapping Devices [*]" -->
+              "Enable Intel DMA Remapping Devices by default  [*]"
+
+It is recommended that no other command line options should be set to override
+the defaults above.
+
+Secure Launch Resource Table
+============================
+
+The Secure Launch Resource Table (SLRT) is a platform-agnostic, standard format
+for providing information for the pre-launch environment and to pass
+information to the post-launch environment. The table is populated by one or
+more bootloaders in the boot chain and used by Secure Launch on how to setup
+the environment during post-launch. The details for the SLRT are documented
+in the TrenchBoot Secure Launch Specifcation [3]_.
+
+Intel TXT Interface
+===================
+
+The primary interfaces between the various components in TXT are the TXT MMIO
+registers and the TXT heap. The MMIO register banks are described in Appendix B
+of the TXT MLE [1]_ Development Guide.
+
+The TXT heap is described in Appendix C of the TXT MLE [1]_ Development
+Guide. Most of the TXT heap is predefined in the specification. The heap is
+initialized by firmware and the pre-launch environment and is subsequently used
+by the SINIT ACM. One section, called the OS to MLE Data Table, is reserved for
+software to define. This table is set up per the recommendation detailed in
+Appendix B of the TrenchBoot Secure Launch Specification::
+
+        /*
+         * Secure Launch defined OS/MLE TXT Heap table
+         */
+        struct txt_os_mle_data {
+                u32 version;
+                u32 boot_params_addr;
+                struct slr_table *slrt;
+                u64 txt_info;
+                u32 ap_wake_block;
+                u32 ap_wake_block_size;
+                u8 mle_scratch[64];
+        } __packed;
+
+Description of structure:
+
+=====================  ========================================================================
+Field                  Use
+=====================  ========================================================================
+version                Structure version, current value 1
+boot_params_addr       Physical base address of the Linux boot parameters
+slrt                   Physical address of the Secure Launch Resource Table
+txt_info               Pointer into the SLRT for easily locating TXT specific table
+ap_wake_block          Physical address of the block of memory for parking APs after a launch
+ap_wake_block_size     Size of the AP wake block
+mle_scratch            Scratch area used post-launch by the MLE kernel. Fields:
+ 
+                        - SL_SCRATCH_AP_EBX area to share %ebx base pointer among CPUs
+                        - SL_SCRATCH_AP_JMP_OFFSET offset to abs. ljmp fixup location for APs
+=====================  ========================================================================
+
+Error Codes
+-----------
+
+The TXT specification defines the layout for TXT 32 bit error code values.
+The bit encodings indicate where the error originated (e.g. with the CPU,
+in the SINIT ACM, in software). The error is written to a sticky TXT
+register that persists across resets called TXT.ERRORCODE (see the TXT
+MLE Development Guide). The errors defined by the Secure Launch feature are
+those generated in the MLE software. They have the format::
+
+  0xc0008XXX
+
+The low 12 bits are free for defining the following Secure Launch specific
+error codes.
+
+======  ================
+Name:   SL_ERROR_GENERIC
+Value:  0xc0008001
+======  ================
+
+Description:
+
+Generic catch all error. Currently unused.
+
+======  =================
+Name:   SL_ERROR_TPM_INIT
+Value:  0xc0008002
+======  =================
+
+Description:
+
+The Secure Launch code failed to get an access to the TPM hardware interface.
+This is most likely to due to misconfigured hardware or kernel. Ensure the
+TPM chip is enabled and the kernel TPM support is built in (it should not be
+built as a module).
+
+======  ==========================
+Name:   SL_ERROR_TPM_INVALID_LOG20
+Value:  0xc0008003
+======  ==========================
+
+Description:
+
+The Secure Launch code failed to find a valid event log descriptor for TPM
+version 2.0 or the event log descriptor is malformed. Usually this indicates
+that incompatible versions of the pre-launch environment and the MLE kernel.
+The pre-launch environment and the kernel share a structure in the TXT heap and
+if this structure (the OS-MLE table) is mismatched, this error is often seen.
+This TXT heap area is setup by the pre-launch environment so the issue may
+originate there. It could be the sign of an attempted attack.
+
+======  ===========================
+Name:   SL_ERROR_TPM_LOGGING_FAILED
+Value:  0xc0008004
+======  ===========================
+
+Description:
+
+There was a failed attempt to write a TPM event to the event log early in the
+Secure Launch process. This is likely the result of a malformed TPM event log
+buffer. Formatting of the event log buffer information is done by the
+pre-launch environment so the issue most likely originates there.
+
+======  ============================
+Name:   SL_ERROR_REGION_STRADDLE_4GB
+Value:  0xc0008005
+======  ============================
+
+Description:
+
+During early validation a buffer or region was found to straddle the 4GB
+boundary. Because of the way TXT does DMA memory protection, this is an
+unsafe configuration and is flagged as an error. This is most likely a
+configuration issue in the pre-launch environment. It could also be the sign of
+an attempted attack.
+
+======  ===================
+Name:   SL_ERROR_TPM_EXTEND
+Value:  0xc0008006
+======  ===================
+
+Description:
+
+There was a failed attempt to extend a TPM PCR in the Secure Launch platform
+module. This is most likely to due to misconfigured hardware or kernel. Ensure
+the TPM chip is enabled and the kernel TPM support is built in (it should not
+be built as a module).
+
+======  ======================
+Name:   SL_ERROR_MTRR_INV_VCNT
+Value:  0xc0008007
+======  ======================
+
+Description:
+
+During early Secure Launch validation an invalid variable MTRR count was found.
+The pre-launch environment passes a number of MSR values to the MLE to restore
+including the MTRRs. The values are restored by the Secure Launch early entry
+point code. After measuring the values supplied by the pre-launch environment,
+a discrepancy was found validating the values. It could be the sign of an
+attempted attack.
+
+======  ==========================
+Name:   SL_ERROR_MTRR_INV_DEF_TYPE
+Value:  0xc0008008
+======  ==========================
+
+Description:
+
+During early Secure Launch validation an invalid default MTRR type was found.
+See SL_ERROR_MTRR_INV_VCNT for more details.
+
+======  ======================
+Name:   SL_ERROR_MTRR_INV_BASE
+Value:  0xc0008009
+======  ======================
+
+Description:
+
+During early Secure Launch validation an invalid variable MTRR base value was
+found. See SL_ERROR_MTRR_INV_VCNT for more details.
+
+======  ======================
+Name:   SL_ERROR_MTRR_INV_MASK
+Value:  0xc000800a
+======  ======================
+
+Description:
+
+During early Secure Launch validation an invalid variable MTRR mask value was
+found. See SL_ERROR_MTRR_INV_VCNT for more details.
+
+======  ========================
+Name:   SL_ERROR_MSR_INV_MISC_EN
+Value:  0xc000800b
+======  ========================
+
+Description:
+
+During early Secure Launch validation an invalid miscellaneous enable MSR value
+was found. See SL_ERROR_MTRR_INV_VCNT for more details.
+
+======  =========================
+Name:   SL_ERROR_INV_AP_INTERRUPT
+Value:  0xc000800c
+======  =========================
+
+Description:
+
+The application processors (APs) wait to be woken up by the SMP initialization
+code. The only interrupt that they expect is an NMI; all other interrupts
+should be masked. If an AP gets some other interrupt other than an NMI it will
+cause this error. This error is very unlikely to occur.
+
+======  =========================
+Name:   SL_ERROR_INTEGER_OVERFLOW
+Value:  0xc000800d
+======  =========================
+
+Description:
+
+A buffer base and size passed to the MLE caused an integer overflow when
+added together. This is most likely a configuration issue in the pre-launch
+environment. It could also be the sign of an attempted attack.
+
+======  ==================
+Name:   SL_ERROR_HEAP_WALK
+Value:  0xc000800e
+======  ==================
+
+Description:
+
+An error occurred in TXT heap walking code. The underlying issue is a failure to
+early_memremap() portions of the heap, most likely due to a resource shortage.
+
+======  =================
+Name:   SL_ERROR_HEAP_MAP
+Value:  0xc000800f
+======  =================
+
+Description:
+
+This error is essentially the same as SL_ERROR_HEAP_WALK but occurred during the
+actual early_memremap() operation.
+
+======  =========================
+Name:   SL_ERROR_REGION_ABOVE_4GB
+Value:  0xc0008010
+======  =========================
+
+Description:
+
+A memory region used by the MLE is above 4GB. In general this is not a problem
+because memory > 4Gb can be protected from DMA. There are certain buffers that
+should never be above 4Gb though and one of these caused the violation. This is
+most likely a configuration issue in the pre-launch environment. It could also
+be the sign of an attempted attack.
+
+======  ==========================
+Name:   SL_ERROR_HEAP_INVALID_DMAR
+Value:  0xc0008011
+======  ==========================
+
+Description:
+
+The backup copy of the ACPI DMAR table which is supposed to be located in the
+TXT heap could not be found. This is due to a bug in the platform's ACM module
+or in firmware.
+
+======  =======================
+Name:   SL_ERROR_HEAP_DMAR_SIZE
+Value:  0xc0008012
+======  =======================
+
+Description:
+
+The backup copy of the ACPI DMAR table in the TXT heap is to large to be stored
+for later usage. This error is very unlikely to occur since the area reserved
+for the copy is far larger than the DMAR should be.
+
+======  ======================
+Name:   SL_ERROR_HEAP_DMAR_MAP
+Value:  0xc0008013
+======  ======================
+
+Description:
+
+The backup copy of the ACPI DMAR table in the TXT heap could not be mapped. The
+underlying issue is a failure to early_memremap() the DMAR table, most likely
+due to a resource shortage.
+
+======  ====================
+Name:   SL_ERROR_HI_PMR_BASE
+Value:  0xc0008014
+======  ====================
+
+Description:
+
+On a system with more than 4G of RAM, the high PMR [2]_ base address should be set
+to 4G. This error is due to that not being the case. This PMR value is set by
+the pre-launch environment so the issue most likely originates there. It could also
+be the sign of an attempted attack.
+
+======  ====================
+Name:   SL_ERROR_HI_PMR_SIZE
+Value:  0xc0008015
+======  ====================
+
+Description:
+
+On a system with more than 4G of RAM, the high PMR [2]_ size should be set to cover
+all RAM > 4G. This error is due to that not being the case. This PMR value is
+set by the pre-launch environment so the issue most likely originates there. It
+could also be the sign of an attempted attack.
+
+======  ====================
+Name:   SL_ERROR_LO_PMR_BASE
+Value:  0xc0008016
+======  ====================
+
+Description:
+
+The low PMR [2]_ base should always be set to address zero. This error is due to
+that not being the case. This PMR value is set by the pre-launch environment
+so the issue most likely originates there. It could also be the sign of an attempted
+attack.
+
+======  ====================
+Name:   SL_ERROR_LO_PMR_MLE
+Value:  0xc0008017
+======  ====================
+
+Description:
+
+This error indicates the MLE image is not covered by the low PMR [2]_ range. The
+PMR values are set by the pre-launch environment so the issue most likely originates
+there. It could also be the sign of an attempted attack.
+
+======  =======================
+Name:   SL_ERROR_INITRD_TOO_BIG
+Value:  0xc0008018
+======  =======================
+
+Description:
+
+The external initrd provided is larger than 4Gb. This is not a valid
+configuration for a Secure Launch due to managing DMA protection.
+
+======  =========================
+Name:   SL_ERROR_HEAP_ZERO_OFFSET
+Value:  0xc0008019
+======  =========================
+
+Description:
+
+During a TXT heap walk an invalid/zero next table offset value was found. This
+indicates the TXT heap is malformed. The TXT heap is initialized by the
+pre-launch environment so the issue most likely originates there. It could also
+be a sign of an attempted attack. In addition, ACM is also responsible for
+manipulating parts of the TXT heap so the issue could be due to a bug in the
+platform's ACM module.
+
+======  =============================
+Name:   SL_ERROR_WAKE_BLOCK_TOO_SMALL
+Value:  0xc000801a
+======  =============================
+
+Description:
+
+The AP wake block buffer passed to the MLE via the OS-MLE TXT heap table is not
+large enough. This value is set by the pre-launch environment so the issue most
+likely originates there. It also could be the sign of an attempted attack.
+
+======  ===========================
+Name:   SL_ERROR_MLE_BUFFER_OVERLAP
+Value:  0xc000801b
+======  ===========================
+
+Description:
+
+One of the buffers passed to the MLE via the OS-MLE TXT heap table overlaps
+with the MLE image in memory. This value is set by the pre-launch environment
+so the issue most likely originates there. It could also be the sign of an attempted
+attack.
+
+======  ==========================
+Name:   SL_ERROR_BUFFER_BEYOND_PMR
+Value:  0xc000801c
+======  ==========================
+
+Description:
+
+One of the buffers passed to the MLE via the OS-MLE TXT heap table is not
+protected by a PMR. This value is set by the pre-launch environment so the
+issue most likey  originates there. It could also be the sign of an attempted
+attack.
+
+======  =============================
+Name:   SL_ERROR_OS_SINIT_BAD_VERSION
+Value:  0xc000801d
+======  =============================
+
+Description:
+
+The version of the OS-SINIT TXT heap table is bad. It must be 6 or greater.
+This value is set by the pre-launch environment so the issue most likely
+originates there. It could also be the sign of an attempted attack. It is also
+possible though very unlikely that the platform is so old that the ACM being
+used requires an unsupported version.
+
+======  =====================
+Name:   SL_ERROR_EVENTLOG_MAP
+Value:  0xc000801e
+======  =====================
+
+Description:
+
+An error occurred in the Secure Launch module while mapping the TPM event log.
+The underlying issue is memremap() failure, most likely due to a resource
+shortage.
+
+======  ========================
+Name:   SL_ERROR_TPM_NUMBER_ALGS
+Value:  0xc000801f
+======  ========================
+
+Description:
+
+The TPM 2.0 event log reports an unsupported number of hashing algorithms.
+Secure launch currently only supports a maximum of two: SHA1 and SHA256.
+
+======  ===========================
+Name:   SL_ERROR_TPM_UNKNOWN_DIGEST
+Value:  0xc0008020
+======  ===========================
+
+Description:
+
+The TPM 2.0 event log reports an unsupported hashing algorithm. Secure launch
+currently only supports two algorithms: SHA1 and SHA256.
+
+======  ==========================
+Name:   SL_ERROR_TPM_INVALID_EVENT
+Value:  0xc0008021
+======  ==========================
+
+Description:
+
+An invalid/malformed event was found in the TPM event log while reading it.
+Since only trusted entities are supposed to be writing the event log, this
+would indicate either a bug or a possible attack.
+
+======  =====================
+Name:   SL_ERROR_INVALID_SLRT
+Value:  0xc0008022
+======  =====================
+
+Description:
+
+The Secure Launch Resource Table is invalid or malformed and is unusable.
+This implies the pre-launch code did not properly setup the SLRT.
+
+======  ===========================
+Name:   SL_ERROR_SLRT_MISSING_ENTRY
+Value:  0xc0008023
+======  ===========================
+
+Description:
+
+The Secure Launch Resource Table is missing a required entry within it.
+This implies the pre-launch code did not properly setup the SLRT.
+
+======  =================
+Name:   SL_ERROR_SLRT_MAP
+Value:  0xc0008024
+======  =================
+
+Description:
+
+An error occurred in the Secure Launch module while mapping the Secure Launch
+Resource table. The underlying issue is memremap() failure, most likely due to
+a resource shortage.
+
+.. [1]
+    MLE: Measured Launch Environment is the binary runtime that is measured and
+    then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
+    requirements for the MLE in detail.
+
+.. [2]
+    PMR: Intel VTd has a feature in the IOMMU called Protected Memory Registers.
+    There are two of these registers and they allow all DMA to be blocked
+    to large areas of memory. The low PMR can cover all memory below 4Gb on 2Mb
+    boundaries. The high PMR can cover all RAM on the system, again on 2Mb
+    boundaries. This feature is used during a Secure Launch by TXT.
+
+.. [3]
+    Secure Launch Specification: https://trenchboot.org/specifications/Secure_Launch/
diff --git a/Documentation/security/launch-integrity/secure_launch_overview.rst b/Documentation/security/launch-integrity/secure_launch_overview.rst
new file mode 100644
index 0000000..ba91d73
--- /dev/null
+++ b/Documentation/security/launch-integrity/secure_launch_overview.rst
@@ -0,0 +1,220 @@
+======================
+Secure Launch Overview
+======================
+
+Overview
+========
+
+Prior to the start of the TrenchBoot project, the only active Open Source
+project supporting dynamic launch was Intel's tboot project to support their
+implementation of dynamic launch known as Intel Trusted eXecution Technology
+(TXT). The approach taken by tboot was to provide an exokernel that could
+handle the launch protocol implemented by Intel's special loader, the SINIT
+Authenticated Code Module (ACM [2]_) and remained in memory to manage the SMX
+CPU mode that a dynamic launch would put a system. While it is not precluded
+from being used for doing a late launch, tboot's primary use case was to be
+used as an early launch solution. As a result the TrenchBoot project started
+the development of Secure Launch kernel feature to provide a more generalized
+approach. The focus of the effort is twofold, the first is to make the Linux
+kernel directly aware of the launch protocol used by Intel, AMD/Hygon, Arm, and
+potentially OpenPOWER. The second is to make the Linux kernel be able to
+initiate a dynamic launch. It is through this approach that the Secure Launch
+kernel feature creates a basis for the Linux kernel to be used in a variety of
+dynamic launch use cases.
+
+.. note::
+    A quick note on terminology. The larger open source project itself is
+    called TrenchBoot, which is hosted on GitHub (links below). The kernel
+    feature enabling the use of the x86 technology is referred to as "Secure
+    Launch" within the kernel code.
+
+Goals
+=====
+
+The first use case that the TrenchBoot project focused on was the ability for
+the Linux kernel to be started by a dynamic launch, in particular as part of an
+early launch sequence. In this case the dynamic launch will be initiated by any
+boot loader with associated support added to it, for example the first targeted
+boot loader in this case was GRUB2. An integral part of establishing a
+measurement-based launch integrity involves measuring everything that is
+intended to be executed (kernel image, initrd, etc) and everything that will
+configure that kernel to execute (command line, boot params, etc). Then storing
+those measurements in a protected manner. Both the Intel and AMD dynamic launch
+implementations leverage the Trusted Platform Module (TPM) to store those
+measurements. The TPM itself has been designed such that a dynamic launch
+unlocks a specific set of Platform Configuration Registers (PCR) for holding
+measurement taken during the dynamic launch.  These are referred to as the DRTM
+PCRs, PCRs 17-22. Further details on this process can be found in the
+documentation for the GETSEC instruction provided by Intel's TXT and the SKINIT
+instruction provided by AMD's AMD-V. The documentation on these technologies
+can be readily found online; see the `Resources`_ section below for references.
+
+.. note::
+    Currently only Intel TXT is supported in this first release of the Secure
+    Launch feature. AMD/Hygon SKINIT and Arm support will be added in a
+    subsequent release.
+
+To enable the kernel to be launched by GETSEC a stub, the Secure Launch stub,
+must be built into the setup section of the compressed kernel to handle the
+specific state that the dynamic launch process leaves the BSP. Also the Secure
+Launch stub must measure everything that is going to be used as early as
+possible. This stub code and subsequent code must also deal with the specific
+state that the dynamic launch leaves the APs as well.
+
+Design Decisions
+================
+
+A number of design decisions were made during the development of the Secure
+Launch feature. The two primary guiding decisions were:
+
+ - Keeping the Secure Launch code as separate from the rest of the kernel
+   as possible.
+ - Modifying the existing boot path of the kernel as little as possible.
+
+The following illustrate how the implementation followed these design
+decisions:
+
+ - All the entry point code necessary to properly configure the system post
+   launch is found in st_stub.S in the compressed kernel image. This code
+   validates the state of the system, restores necessary system operating
+   configurations and properly handles post launch CPU states.
+ - After the sl_stub.S is complete, it jumps directly to the unmodified
+   startup_32 kernel entry point.
+ - A single call is made to a function sl_main() prior to the main kernel
+   decompression step. This code performs further validation and takes the
+   needed DRTM measurements.
+ - After the call to sl_main(), the main kernel is decompressed and boots as
+   it normally would.
+ - Final setup for the Secure Launch kernel is done in a separate Secure
+   Launch module that is loaded via a late initcall. This code is responsible
+   for extending the measurements taken earlier into the TPM DRTM PCRs and
+   setting up the securityfs interface to allow access the TPM event log and
+   public TXT registers.
+ - On the reboot and kexec paths, calls are made to a function to finalize the
+   state of the Secure Launch kernel.
+
+The one place where Secure Launch code is mixed directly in with kernel code is
+in the SMP boot code. This is due to the unique state that the dynamic launch
+leaves the APs in. On Intel this involves using a method other than the
+standard INIT-SIPI sequence.
+
+A final note is that originally the extending of the PCRs was completed in the
+Secure Launch stub when the measurements were taken. An alternative solution
+had to be implemented due to the TPM maintainers objecting to the PCR
+extensions being done with a minimal interface to the TPM that was an
+independent implementation of the mainline kernel driver. Since the mainline
+driver relies heavily on kernel interfaces not available in the compressed
+kernel, it was not possible to reuse the mainline TPM driver. This resulted in
+the decision to move the extension operations to the Secure Launch module in
+the mainline kernel where the TPM driver would be available.
+
+Basic Boot Flow
+===============
+
+Outlined here is summary of the boot flow for Secure Launch. A more detailed
+review of Secure Launch process can be found in the Secure Launch
+Specification, a link is located in the `Resources`_ section.
+
+Pre-launch: *Phase where the environment is prepared and configured to initiate the
+secure launch by the boot chain.*
+
+ - The SLRT is initialized and dl_stub is placed in memory.
+ - Load the kernel, initrd and ACM [2]_ into memory.
+ - Setup the TXT heap and page tables describing the MLE [1]_ per the
+   specification.
+ - If non-UEFI platform, dl_stub is called.
+ - If UEFI platforms, SLRT registered with UEFI and efi-stub called.
+ - Upon completion, efi-stub will call EBS followed by dl_stub.
+ - The dl_stub will prepare the CPU and the TPM for the launch.
+ - The secure launch is then initiated with the GETSET[SENTER] instruction.
+
+Post-launch: *Phase where control is passed from the ACM to the MLE and the secure
+kernel begins execution.*
+
+ - Entry from the dynamic launch jumps to the SL stub.
+ - SL stub fixes up the world on the BSP.
+ - For TXT, SL stub wakes the APs, fixes up their worlds.
+ - For TXT, APs are left halted waiting for an NMI to wake them.
+ - SL stub jumps to startup_32.
+ - SL main does validation of buffers and memory locations. It sets
+   the boot parameter loadflag value SLAUNCH_FLAG to inform the main
+   kernel that a Secure Launch was done.
+ - SL main locates the TPM event log and writes the measurements of
+   configuration and module information into it.
+ - Kernel boot proceeds normally from this point.
+ - During early setup, slaunch_setup() runs to finish some validation
+   and setup tasks.
+ - The SMP bring up code is modified to wake the waiting APs. APs vector
+   to rmpiggy and start up normally from that point.
+ - SL platform module is registered as a late initcall module. It reads
+   the TPM event log and extends the measurements taken into the TPM PCRs.
+ - SL platform module initializes the securityfs interface to allow
+   access to the TPM event log and TXT public registers.
+ - Kernel boot finishes booting normally
+ - SEXIT support to leave SMX mode is present on the kexec path and
+   the various reboot paths (poweroff, reset, halt).
+
+PCR Usage
+=========
+
+The TCG DRTM architecture there are three PCRs defined for usage, PCR.Details
+(PCR17), PCR.Authorities (PCR18), and PCR.DLME_Authority (PCR19). For a deeper
+understanding of Detail and Authorities it is recommended to review the TCG
+DRTM architecture.
+
+To determine PCR usage, Linux Secure Launch follows the TrenchBoot Secure
+Launch Specification of using a measurement policy stored in the SLRT. The
+policy details what should be measured and the PCR in which to store the
+measurement. The measurement policy provides the ability to select the
+PCR.DLME_Detail (PCR20) PCR as the location for the DRTM components measured by
+the kernel, e.g. external initrd image. This can then be combined with storing
+the user authority in the PCR.DLME_Authority PCR to seal/attest to different
+variations of platform details/authorities and user details/authorities. An
+example of how this can be achieved was presented in the FOSDEM - 2021 talk
+"Secure Upgrades with DRTM".
+
+Resources
+=========
+
+The TrenchBoot project:
+
+https://trenchboot.org
+
+Secure Launch Specification:
+
+https://trenchboot.org/specifications/Secure_Launch/
+
+Trusted Computing Group's D-RTM Architecture:
+
+https://trustedcomputinggroup.org/wp-content/uploads/TCG_D-RTM_Architecture_v1-0_Published_06172013.pdf
+
+TXT documentation in the Intel TXT MLE Development Guide:
+
+https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
+
+TXT instructions documentation in the Intel SDM Instruction Set volume:
+
+https://software.intel.com/en-us/articles/intel-sdm
+
+AMD SKINIT documentation in the System Programming manual:
+
+https://www.amd.com/system/files/TechDocs/24593.pdf
+
+GRUB Secure Launch support:
+
+https://github.com/TrenchBoot/grub/tree/grub-sl-fc-38-dlstub
+
+FOSDEM 2021: Secure Upgrades with DRTM
+
+https://archive.fosdem.org/2021/schedule/event/firmware_suwd/
+
+.. [1]
+    MLE: Measured Launch Environment is the binary runtime that is measured and
+    then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
+    requirements for the MLE in detail.
+
+.. [2]
+    ACM: Intel's Authenticated Code Module. This is the 32b bit binary blob that
+    is run securely by the GETSEC[SENTER] during a measured launch. It is described
+    in the Intel documentation on TXT and versions for various chipsets are
+    signed and distributed by Intel.
-- 
1.8.3.1


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

* [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

Introduce background, overview and configuration/ABI information
for the Secure Launch kernel feature.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 Documentation/security/index.rst                   |   1 +
 Documentation/security/launch-integrity/index.rst  |  10 +
 .../security/launch-integrity/principles.rst       | 313 ++++++++++++
 .../launch-integrity/secure_launch_details.rst     | 564 +++++++++++++++++++++
 .../launch-integrity/secure_launch_overview.rst    | 220 ++++++++
 5 files changed, 1108 insertions(+)
 create mode 100644 Documentation/security/launch-integrity/index.rst
 create mode 100644 Documentation/security/launch-integrity/principles.rst
 create mode 100644 Documentation/security/launch-integrity/secure_launch_details.rst
 create mode 100644 Documentation/security/launch-integrity/secure_launch_overview.rst

diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst
index 6ed8d2f..fade37e 100644
--- a/Documentation/security/index.rst
+++ b/Documentation/security/index.rst
@@ -18,3 +18,4 @@ Security Documentation
    digsig
    landlock
    secrets/index
+   launch-integrity/index
diff --git a/Documentation/security/launch-integrity/index.rst b/Documentation/security/launch-integrity/index.rst
new file mode 100644
index 0000000..28eed91d
--- /dev/null
+++ b/Documentation/security/launch-integrity/index.rst
@@ -0,0 +1,10 @@
+=====================================
+System Launch Integrity documentation
+=====================================
+
+.. toctree::
+
+   principles
+   secure_launch_overview
+   secure_launch_details
+
diff --git a/Documentation/security/launch-integrity/principles.rst b/Documentation/security/launch-integrity/principles.rst
new file mode 100644
index 0000000..73cf063
--- /dev/null
+++ b/Documentation/security/launch-integrity/principles.rst
@@ -0,0 +1,313 @@
+=======================
+System Launch Integrity
+=======================
+
+This document serves to establish a common understanding of what is system
+launch, the integrity concern for system launch, and why using a Root of Trust
+(RoT) from a Dynamic Launch may be desired. Through out this document
+terminology from the Trusted Computing Group (TCG) and National Institue for
+Science and Technology (NIST) is used to ensure a vendor nutrual language is
+used to describe and reference security-related concepts.
+
+System Launch
+=============
+
+There is a tendency to only consider the classical power-on boot as the only
+means to launch an Operating System (OS) on a computer system, but in fact most
+modern processors support two methods to launch the system. To provide clarity a
+common definition of a system launch should be established. This definition is
+that a during a single power life cycle of a system, a System Launch consists
+of an initialization event, typically in hardware, that is followed by an
+executing software payload that takes the system from the initialized state to
+a running state. Driven by the Trusted Computing Group (TCG) architecture,
+modern processors are able to support two methods to launch a system, these two
+types of system launch are known as Static Launch and Dynamic Launch.
+
+Static Launch
+-------------
+
+Static launch is the system launch associated with the power cycle of the CPU.
+Thus static launch refers to the classical power-on boot where the
+initialization event is the release of the CPU from reset and the system
+firmware is the software payload that brings the system up to a running state.
+Since static launch is the system launch associated with the beginning of the
+power lifecycle of a system, it is therefore a fixed, one-time system launch.
+It is because of this that static launch is referred to and thought of as being
+"static".
+
+Dynamic Launch
+--------------
+
+Modern CPUs architectures provides a mechanism to re-initialize the system to a
+"known good" state without requiring a power event. This re-initialization
+event is the event for a dynamic launch and is referred to as the Dynamic
+Launch Event (DLE). The DLE functions by accepting a software payload, referred
+to as the Dynamic Configuration Environment (DCE), that execution is handed to
+after the DLE is invoked. The DCE is responsible for bringing the system back
+to a running state. Since the dynamic launch is not tied to a power event like
+the static launch, this enables a dynamic launch to be initiated at any time
+and multiple times during a single power life cycle. This dynamism is the
+reasoning behind referring to this system launch as being dynamic.
+
+Because a dynamic launch can be conducted at any time during a single power
+life cycle, they are classified into one of two types, an early launch or a
+late launch.
+
+:Early Launch: When a dynamic launch is used as a transition from a static
+   launch chain to the final Operating System.
+
+:Late Launch: The usage of a dynamic launch by an executing Operating System to
+   transition to a “known good” state to perform one or more operations, e.g. to
+   launch into a new Operating System.
+
+System Integrity
+================
+
+A computer system can be considered a collection of mechanisms that work
+together to produce a result. The assurance that the mechanisms are functioning
+correctly and producing the expected result is the integrity of the system. To
+ensure a system's integrity there are a subset of these mechanisms, commonly
+referred to as security mechanisms, that are present to help ensure the system
+produces the expected result or at least detect the potential of an unexpected
+result may have happened. Since the security mechanisms are relied upon to
+ensue the integrity of the system, these mechanisms are trusted. Upon
+inspection these security mechanisms each have a set of properties and these
+properties can be evaluated to determine how susceptible a mechanism might be
+to failure. This assessment is referred to as the Strength of Mechanism and for
+trusted mechanism enables for the trustworthiness of that mechanism to be
+quantified.
+
+For software systems there are two system states for which the integrity is
+critical, when the software is loaded into memory and when the software is
+executing on the hardware. Ensuring that the expected software is load into
+memory is referred to as load-time integrity while ensuring that the software
+executing is the expected software is the runtime integrity of that software.
+
+Load-time Integrity
+-------------------
+
+It is critical to understand what load-time integrity establishes about a
+system and what is assumed, i.e. what is being trusted. Load-time integrity is
+when a trusted entity, i.e. an entity with an assumed integrity, takes an
+action to assess an entity being loaded into memory before it is used. A
+variety of mechanisms may be used to conduct the assessment, each with
+different properties. A particular property is whether the mechanism creates an
+evidence of the assessment. Often either cryptographic signature checking or
+hashing are the common assessment operations used.
+
+A signature checking assessment functions by requiring a representation of the
+accepted authorities and uses those representations to assess if the entity has
+been signed by an accepted authority. The benefit to this process is that
+assessment process includes an adjudication of the assessment. The drawbacks
+are that 1) the adjudication is susceptible to tampering by the Trusted
+Computing Base (TCB), 2) there is no evidence to assert that an untampered
+adjudication was completed, and 3) the system must be an active participant in
+the key management infrastructure.
+
+A cryptographic hashing assessment does not adjudicate the assessment but
+instead generates evidence of the assessment to be adjudicated independently.
+The benefits to this approach is that the assessment may be simple such that it
+is able to be implemented as an immutable mechanism, e.g. in hardware.
+Additionally it is possible for the adjudication to be conducted where it
+cannot be tampered with by the TCB. The drawback is that a compromised
+environment will be allowed to execute until an adjudication can be completed.
+
+Ultimately load-time integrity provides confidence that the correct entity was
+loaded and in the absence of a run-time integrity mechanism assumes, i.e
+trusts, that the entity will never become corrupted.
+
+Runtime Integrity
+-----------------
+
+Runtime integrity in the general sense is when a trusted entity makes an
+assessment of an entity at any point in time during the assessed entity's
+execution. A more concrete explanation is the taking of an integrity assessment
+of an active process executing on the system at any point during the process'
+execution. Often the load-time integrity of an operating system's user-space,
+i.e. the operating environment, is confused to be the runtime integrity of the
+system since it is an integrity assessment of the "runtime" software. The
+reality is that actual runtime integrity is a very difficult problem and thus
+not very many solutions are public and/or available. One example of a runtime
+integrity solution would be John Hopkins Advanced Physics Labratory's (APL)
+Linux Kernel Integrity Module (LKIM).
+
+Trust Chains
+============
+
+Bulding upon the understanding of security mechanisms to establish load-time
+integrity of an entity, it is possible to chain together load-time integrity
+assessments to establish the integrity of the whole system. This process is
+known as transitive trust and provides the concept of building a chain of
+load-time integrity assessments, commonly referred to as a trust chain. These
+assessments may be used to adjudicate the load-time integrity of the whole
+system. This trust chain is started by a trusted entity that does the first
+assessment. This first entity is referred to as the Root of Trust(RoT) with the
+entities name being derived from the mechanism used for the assessment, i.e.
+RoT for Verification (RTV) and RoT for Measurement (RTM).
+
+A trust chain is itself a mechanism, specifically a mechanism of mechanisms,
+and therefore it too has a Strength of Mechanism. The factors that contribute
+to a trust chain's strength are,
+
+  - The strength of the chain's RoT
+  - The strength of each member of the trust chain
+  - The length, i.e. the number of members, of the chain
+
+Therefore to provide the strongest trust chains, they should start with a
+strong RoT and should consist of members being of low complexity and minimizing
+the number of members participating as is possible. In a more colloquial sense,
+a trust chain is only as strong as it weakests link and more links increase
+the probability of a weak link.
+
+Dynamic Launch Components
+=========================
+
+The TCG architecture for dynamic launch is composed of a component series that
+are used to setup and then carry out the launch. These components work together
+to construct a RTM trust chain that is rooted in the dynamic launch and thus
+commonly referred to as the Dynamic Root of Trust for Measurement (DRTM) chain.
+
+What follows is a brief explanation of each component in execution order. A
+subset of these components are what establishes the dynamic launch's trust
+chain.
+
+Dynamic Configuration Environment Preamble
+------------------------------------------
+
+The Dynamic Configuration Environment (DCE) Preamble is responsible for setting
+up the system environment in preparation for a dynamic launch. The DCE Preamble
+is not a part of the DRTM trust chain.
+
+Dynamic Launch Event
+--------------------
+
+The dynamic launch event is the event, typically a CPU instruction, that triggers
+the system's dynamic launch mechanism to begin the launch. The dynamic launch
+mechanism is also the RoT for the DRTM trust chain.
+
+Dynamic Configuration Environment
+---------------------------------
+
+The dynamic launch mechanism may have resulted in a reset of a portion of the
+system. To bring the system back to an adequate state for system software the
+dynamic launch will hand over control to the DCE. Prior to handing over this
+control, the dynamic launch will measure the DCE. Once the DCE is complete it
+will proceed to measure and then execute the Dynamic Launch Measured
+Environment (DLME).
+
+Dynamic Launch Measured Environment
+-----------------------------------
+
+The DLME is the first system kernel to have control of the system but may not
+be the last. Depending on the usage and configuration, the DLME may be the
+final/target operating system or it may be a boot loader that will load the
+final/target operating system.
+
+Why DRTM
+========
+
+It is a fact that DRTM increases the load-time integrity of the system by
+providing a trust chain that has an immutable hardware RoT, uses a limited
+number of small, special purpose code to establish the trust chain that starts
+the target operating system. As mentioned in the Trust Chain section, these are
+the main three factors in driving up the strength of a trust chain. As can been
+seen by the BootHole exploit, which in fact did not effect the integrity of
+DRTM solutions, the sophistication of attacks targeting system launch is at an
+all time high. There is no reason a system should not employ every integrity
+measure hardware makes available. This is the crux of a defense-in-depth
+approach to system security. In the past the now closed SMI gap was often
+pointed to as invalidating DRTM, which in fact was nothing but a strawman
+argument. As has continued to be demonstrated, if/when SMM is corrupted it can
+always circumvent all load-time integrity, SRTM and DRTM, because it is a
+run-time integrity problem. Regardless, Intel and AMD have both deployed
+runtime integrity for SMI and SMM which is tied directly to DRTM such that this
+perceived deficiency is now non-existent and the world is moving forward with
+an expectation that DRTM must be present.
+
+Glossary
+========
+
+.. glossary::
+  integrity
+    Guarding against improper information modification or destruction, and
+    includes ensuring information non-repudiation and authenticity.
+
+    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+  mechanism
+    A process or system that is used to produce a particular result.
+
+    - NIST Special Publication 800-160 (VOLUME 1 ) - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-160v1.pdf
+
+  risk
+    A measure of the extent to which an entity is threatened by a potential
+    circumstance or event, and typically a function of: (i) the adverse impacts
+    that would arise if the circumstance or event occurs; and (ii) the
+    likelihood of occurrence.
+
+    - NIST SP 800-30 Rev. 1 - https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-30r1.pdf
+
+  security mechanism
+    A device or function designed to provide one or more security services
+    usually rated in terms of strength of service and assurance of the design.
+
+    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+  Strength of Mechanism
+    A scale for measuring the relative strength of a security mechanism
+
+    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+  transitive trust
+    Also known as "Inductive Trust", in this process a Root of Trust gives a
+    trustworthy description of a second group of functions. Based on this
+    description, an interested entity can determine the trust it is to place in
+    this second group of functions. If the interested entity determines that
+    the trust level of the second group of functions is acceptable, the trust
+    boundary is extended from the Root of Trust to include the second group of
+    functions. In this case, the process can be iterated. The second group of
+    functions can give a trustworthy description of the third group of
+    functions, etc. Transitive trust is used to provide a trustworthy
+    description of platform characteristics, and also to prove that
+    non-migratable keys are non-migratable
+
+    - TCG Glossary - https://trustedcomputinggroup.org/wp-content/uploads/TCG-Glossary-V1.1-Rev-1.0.pdf
+
+  trust
+    The confidence one element has in another that the second element will
+    behave as expected`
+
+    - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
+
+  trust anchor
+    An authoritative entity for which trust is assumed.
+
+    - NIST SP 800-57 Part 1 Rev. 5 - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf
+
+  trusted
+    An element that another element relies upon to fulfill critical
+    requirements on its behalf.
+
+    - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
+
+  trusted computing base (TCB)
+    Totality of protection mechanisms within a computer system, including
+    hardware, firmware, and software, the combination responsible for enforcing
+    a security policy.
+
+    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+  trusted computer system
+    A system that has the necessary security functions and assurance that the
+    security policy will be enforced and that can process a range of
+    information sensitivities (i.e. classified, controlled unclassified
+    information (CUI), or unclassified public information) simultaneously.
+
+    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+  trustworthiness
+    The attribute of a person or enterprise that provides confidence to others
+    of the qualifications, capabilities, and reliability of that entity to
+    perform specific tasks and fulfill assigned responsibilities.
+
+    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
diff --git a/Documentation/security/launch-integrity/secure_launch_details.rst b/Documentation/security/launch-integrity/secure_launch_details.rst
new file mode 100644
index 0000000..2e71543
--- /dev/null
+++ b/Documentation/security/launch-integrity/secure_launch_details.rst
@@ -0,0 +1,564 @@
+===================================
+Secure Launch Config and Interfaces
+===================================
+
+Configuration
+=============
+
+The settings to enable Secure Launch using Kconfig are under::
+
+  "Processor type and features" --> "Secure Launch support"
+
+A kernel with this option enabled can still be booted using other supported
+methods.
+
+To reduce the Trusted Computing Base (TCB) of the MLE [1]_, the build
+configuration should be pared down as narrowly as one's use case allows.
+The fewer drivers (less active hardware) and features reduces the attack
+surface. E.g. in the extreme, the MLE could only have local disk access
+and no other hardware support. Or only network access for remote attestation.
+
+It is also desirable if possible to embed the initrd used with the MLE kernel
+image to reduce complexity.
+
+The following are a few important configuration necessities to always consider:
+
+KASLR Configuration
+-------------------
+
+Secure Launch does not interoperate with KASLR. If possible, the MLE should be
+built with KASLR disabled::
+
+  "Processor type and features" -->
+      "Build a relocatable kernel" -->
+          "Randomize the address of the kernel image (KASLR) [ ]"
+
+This unsets the Kconfig value CONFIG_RANDOMIZE_BASE.
+
+If not possible, KASLR must be disabled on the kernel command line when doing
+a Secure Launch as follows::
+
+  nokaslr
+
+IOMMU Configuration
+-------------------
+
+When doing a Secure Launch, the IOMMU should always be enabled and the drivers
+loaded. However, IOMMU passthrough mode should never be used. This leaves the
+MLE completely exposed to DMA after the PMR's [2]_ are disabled. The current default
+mode is to use IOMMU in lazy translated mode but strict translated mode is the preferred
+IOMMU mode and this should be selected in the build configuration::
+
+  "Device Drivers" -->
+      "IOMMU Hardware Support" -->
+          "IOMMU default domain type" -->
+              "(X) Translated - Strict"
+
+In addition, the Intel IOMMU should be on by default. The following sets this as the
+default in the build configuration::
+
+  "Device Drivers" -->
+      "IOMMU Hardware Support" -->
+          "Support for Intel IOMMU using DMA Remapping Devices [*]"
+
+and::
+
+  "Device Drivers" -->
+      "IOMMU Hardware Support" -->
+          "Support for Intel IOMMU using DMA Remapping Devices [*]" -->
+              "Enable Intel DMA Remapping Devices by default  [*]"
+
+It is recommended that no other command line options should be set to override
+the defaults above.
+
+Secure Launch Resource Table
+============================
+
+The Secure Launch Resource Table (SLRT) is a platform-agnostic, standard format
+for providing information for the pre-launch environment and to pass
+information to the post-launch environment. The table is populated by one or
+more bootloaders in the boot chain and used by Secure Launch on how to setup
+the environment during post-launch. The details for the SLRT are documented
+in the TrenchBoot Secure Launch Specifcation [3]_.
+
+Intel TXT Interface
+===================
+
+The primary interfaces between the various components in TXT are the TXT MMIO
+registers and the TXT heap. The MMIO register banks are described in Appendix B
+of the TXT MLE [1]_ Development Guide.
+
+The TXT heap is described in Appendix C of the TXT MLE [1]_ Development
+Guide. Most of the TXT heap is predefined in the specification. The heap is
+initialized by firmware and the pre-launch environment and is subsequently used
+by the SINIT ACM. One section, called the OS to MLE Data Table, is reserved for
+software to define. This table is set up per the recommendation detailed in
+Appendix B of the TrenchBoot Secure Launch Specification::
+
+        /*
+         * Secure Launch defined OS/MLE TXT Heap table
+         */
+        struct txt_os_mle_data {
+                u32 version;
+                u32 boot_params_addr;
+                struct slr_table *slrt;
+                u64 txt_info;
+                u32 ap_wake_block;
+                u32 ap_wake_block_size;
+                u8 mle_scratch[64];
+        } __packed;
+
+Description of structure:
+
+=====================  ========================================================================
+Field                  Use
+=====================  ========================================================================
+version                Structure version, current value 1
+boot_params_addr       Physical base address of the Linux boot parameters
+slrt                   Physical address of the Secure Launch Resource Table
+txt_info               Pointer into the SLRT for easily locating TXT specific table
+ap_wake_block          Physical address of the block of memory for parking APs after a launch
+ap_wake_block_size     Size of the AP wake block
+mle_scratch            Scratch area used post-launch by the MLE kernel. Fields:
+ 
+                        - SL_SCRATCH_AP_EBX area to share %ebx base pointer among CPUs
+                        - SL_SCRATCH_AP_JMP_OFFSET offset to abs. ljmp fixup location for APs
+=====================  ========================================================================
+
+Error Codes
+-----------
+
+The TXT specification defines the layout for TXT 32 bit error code values.
+The bit encodings indicate where the error originated (e.g. with the CPU,
+in the SINIT ACM, in software). The error is written to a sticky TXT
+register that persists across resets called TXT.ERRORCODE (see the TXT
+MLE Development Guide). The errors defined by the Secure Launch feature are
+those generated in the MLE software. They have the format::
+
+  0xc0008XXX
+
+The low 12 bits are free for defining the following Secure Launch specific
+error codes.
+
+======  ================
+Name:   SL_ERROR_GENERIC
+Value:  0xc0008001
+======  ================
+
+Description:
+
+Generic catch all error. Currently unused.
+
+======  =================
+Name:   SL_ERROR_TPM_INIT
+Value:  0xc0008002
+======  =================
+
+Description:
+
+The Secure Launch code failed to get an access to the TPM hardware interface.
+This is most likely to due to misconfigured hardware or kernel. Ensure the
+TPM chip is enabled and the kernel TPM support is built in (it should not be
+built as a module).
+
+======  ==========================
+Name:   SL_ERROR_TPM_INVALID_LOG20
+Value:  0xc0008003
+======  ==========================
+
+Description:
+
+The Secure Launch code failed to find a valid event log descriptor for TPM
+version 2.0 or the event log descriptor is malformed. Usually this indicates
+that incompatible versions of the pre-launch environment and the MLE kernel.
+The pre-launch environment and the kernel share a structure in the TXT heap and
+if this structure (the OS-MLE table) is mismatched, this error is often seen.
+This TXT heap area is setup by the pre-launch environment so the issue may
+originate there. It could be the sign of an attempted attack.
+
+======  ===========================
+Name:   SL_ERROR_TPM_LOGGING_FAILED
+Value:  0xc0008004
+======  ===========================
+
+Description:
+
+There was a failed attempt to write a TPM event to the event log early in the
+Secure Launch process. This is likely the result of a malformed TPM event log
+buffer. Formatting of the event log buffer information is done by the
+pre-launch environment so the issue most likely originates there.
+
+======  ============================
+Name:   SL_ERROR_REGION_STRADDLE_4GB
+Value:  0xc0008005
+======  ============================
+
+Description:
+
+During early validation a buffer or region was found to straddle the 4GB
+boundary. Because of the way TXT does DMA memory protection, this is an
+unsafe configuration and is flagged as an error. This is most likely a
+configuration issue in the pre-launch environment. It could also be the sign of
+an attempted attack.
+
+======  ===================
+Name:   SL_ERROR_TPM_EXTEND
+Value:  0xc0008006
+======  ===================
+
+Description:
+
+There was a failed attempt to extend a TPM PCR in the Secure Launch platform
+module. This is most likely to due to misconfigured hardware or kernel. Ensure
+the TPM chip is enabled and the kernel TPM support is built in (it should not
+be built as a module).
+
+======  ======================
+Name:   SL_ERROR_MTRR_INV_VCNT
+Value:  0xc0008007
+======  ======================
+
+Description:
+
+During early Secure Launch validation an invalid variable MTRR count was found.
+The pre-launch environment passes a number of MSR values to the MLE to restore
+including the MTRRs. The values are restored by the Secure Launch early entry
+point code. After measuring the values supplied by the pre-launch environment,
+a discrepancy was found validating the values. It could be the sign of an
+attempted attack.
+
+======  ==========================
+Name:   SL_ERROR_MTRR_INV_DEF_TYPE
+Value:  0xc0008008
+======  ==========================
+
+Description:
+
+During early Secure Launch validation an invalid default MTRR type was found.
+See SL_ERROR_MTRR_INV_VCNT for more details.
+
+======  ======================
+Name:   SL_ERROR_MTRR_INV_BASE
+Value:  0xc0008009
+======  ======================
+
+Description:
+
+During early Secure Launch validation an invalid variable MTRR base value was
+found. See SL_ERROR_MTRR_INV_VCNT for more details.
+
+======  ======================
+Name:   SL_ERROR_MTRR_INV_MASK
+Value:  0xc000800a
+======  ======================
+
+Description:
+
+During early Secure Launch validation an invalid variable MTRR mask value was
+found. See SL_ERROR_MTRR_INV_VCNT for more details.
+
+======  ========================
+Name:   SL_ERROR_MSR_INV_MISC_EN
+Value:  0xc000800b
+======  ========================
+
+Description:
+
+During early Secure Launch validation an invalid miscellaneous enable MSR value
+was found. See SL_ERROR_MTRR_INV_VCNT for more details.
+
+======  =========================
+Name:   SL_ERROR_INV_AP_INTERRUPT
+Value:  0xc000800c
+======  =========================
+
+Description:
+
+The application processors (APs) wait to be woken up by the SMP initialization
+code. The only interrupt that they expect is an NMI; all other interrupts
+should be masked. If an AP gets some other interrupt other than an NMI it will
+cause this error. This error is very unlikely to occur.
+
+======  =========================
+Name:   SL_ERROR_INTEGER_OVERFLOW
+Value:  0xc000800d
+======  =========================
+
+Description:
+
+A buffer base and size passed to the MLE caused an integer overflow when
+added together. This is most likely a configuration issue in the pre-launch
+environment. It could also be the sign of an attempted attack.
+
+======  ==================
+Name:   SL_ERROR_HEAP_WALK
+Value:  0xc000800e
+======  ==================
+
+Description:
+
+An error occurred in TXT heap walking code. The underlying issue is a failure to
+early_memremap() portions of the heap, most likely due to a resource shortage.
+
+======  =================
+Name:   SL_ERROR_HEAP_MAP
+Value:  0xc000800f
+======  =================
+
+Description:
+
+This error is essentially the same as SL_ERROR_HEAP_WALK but occurred during the
+actual early_memremap() operation.
+
+======  =========================
+Name:   SL_ERROR_REGION_ABOVE_4GB
+Value:  0xc0008010
+======  =========================
+
+Description:
+
+A memory region used by the MLE is above 4GB. In general this is not a problem
+because memory > 4Gb can be protected from DMA. There are certain buffers that
+should never be above 4Gb though and one of these caused the violation. This is
+most likely a configuration issue in the pre-launch environment. It could also
+be the sign of an attempted attack.
+
+======  ==========================
+Name:   SL_ERROR_HEAP_INVALID_DMAR
+Value:  0xc0008011
+======  ==========================
+
+Description:
+
+The backup copy of the ACPI DMAR table which is supposed to be located in the
+TXT heap could not be found. This is due to a bug in the platform's ACM module
+or in firmware.
+
+======  =======================
+Name:   SL_ERROR_HEAP_DMAR_SIZE
+Value:  0xc0008012
+======  =======================
+
+Description:
+
+The backup copy of the ACPI DMAR table in the TXT heap is to large to be stored
+for later usage. This error is very unlikely to occur since the area reserved
+for the copy is far larger than the DMAR should be.
+
+======  ======================
+Name:   SL_ERROR_HEAP_DMAR_MAP
+Value:  0xc0008013
+======  ======================
+
+Description:
+
+The backup copy of the ACPI DMAR table in the TXT heap could not be mapped. The
+underlying issue is a failure to early_memremap() the DMAR table, most likely
+due to a resource shortage.
+
+======  ====================
+Name:   SL_ERROR_HI_PMR_BASE
+Value:  0xc0008014
+======  ====================
+
+Description:
+
+On a system with more than 4G of RAM, the high PMR [2]_ base address should be set
+to 4G. This error is due to that not being the case. This PMR value is set by
+the pre-launch environment so the issue most likely originates there. It could also
+be the sign of an attempted attack.
+
+======  ====================
+Name:   SL_ERROR_HI_PMR_SIZE
+Value:  0xc0008015
+======  ====================
+
+Description:
+
+On a system with more than 4G of RAM, the high PMR [2]_ size should be set to cover
+all RAM > 4G. This error is due to that not being the case. This PMR value is
+set by the pre-launch environment so the issue most likely originates there. It
+could also be the sign of an attempted attack.
+
+======  ====================
+Name:   SL_ERROR_LO_PMR_BASE
+Value:  0xc0008016
+======  ====================
+
+Description:
+
+The low PMR [2]_ base should always be set to address zero. This error is due to
+that not being the case. This PMR value is set by the pre-launch environment
+so the issue most likely originates there. It could also be the sign of an attempted
+attack.
+
+======  ====================
+Name:   SL_ERROR_LO_PMR_MLE
+Value:  0xc0008017
+======  ====================
+
+Description:
+
+This error indicates the MLE image is not covered by the low PMR [2]_ range. The
+PMR values are set by the pre-launch environment so the issue most likely originates
+there. It could also be the sign of an attempted attack.
+
+======  =======================
+Name:   SL_ERROR_INITRD_TOO_BIG
+Value:  0xc0008018
+======  =======================
+
+Description:
+
+The external initrd provided is larger than 4Gb. This is not a valid
+configuration for a Secure Launch due to managing DMA protection.
+
+======  =========================
+Name:   SL_ERROR_HEAP_ZERO_OFFSET
+Value:  0xc0008019
+======  =========================
+
+Description:
+
+During a TXT heap walk an invalid/zero next table offset value was found. This
+indicates the TXT heap is malformed. The TXT heap is initialized by the
+pre-launch environment so the issue most likely originates there. It could also
+be a sign of an attempted attack. In addition, ACM is also responsible for
+manipulating parts of the TXT heap so the issue could be due to a bug in the
+platform's ACM module.
+
+======  =============================
+Name:   SL_ERROR_WAKE_BLOCK_TOO_SMALL
+Value:  0xc000801a
+======  =============================
+
+Description:
+
+The AP wake block buffer passed to the MLE via the OS-MLE TXT heap table is not
+large enough. This value is set by the pre-launch environment so the issue most
+likely originates there. It also could be the sign of an attempted attack.
+
+======  ===========================
+Name:   SL_ERROR_MLE_BUFFER_OVERLAP
+Value:  0xc000801b
+======  ===========================
+
+Description:
+
+One of the buffers passed to the MLE via the OS-MLE TXT heap table overlaps
+with the MLE image in memory. This value is set by the pre-launch environment
+so the issue most likely originates there. It could also be the sign of an attempted
+attack.
+
+======  ==========================
+Name:   SL_ERROR_BUFFER_BEYOND_PMR
+Value:  0xc000801c
+======  ==========================
+
+Description:
+
+One of the buffers passed to the MLE via the OS-MLE TXT heap table is not
+protected by a PMR. This value is set by the pre-launch environment so the
+issue most likey  originates there. It could also be the sign of an attempted
+attack.
+
+======  =============================
+Name:   SL_ERROR_OS_SINIT_BAD_VERSION
+Value:  0xc000801d
+======  =============================
+
+Description:
+
+The version of the OS-SINIT TXT heap table is bad. It must be 6 or greater.
+This value is set by the pre-launch environment so the issue most likely
+originates there. It could also be the sign of an attempted attack. It is also
+possible though very unlikely that the platform is so old that the ACM being
+used requires an unsupported version.
+
+======  =====================
+Name:   SL_ERROR_EVENTLOG_MAP
+Value:  0xc000801e
+======  =====================
+
+Description:
+
+An error occurred in the Secure Launch module while mapping the TPM event log.
+The underlying issue is memremap() failure, most likely due to a resource
+shortage.
+
+======  ========================
+Name:   SL_ERROR_TPM_NUMBER_ALGS
+Value:  0xc000801f
+======  ========================
+
+Description:
+
+The TPM 2.0 event log reports an unsupported number of hashing algorithms.
+Secure launch currently only supports a maximum of two: SHA1 and SHA256.
+
+======  ===========================
+Name:   SL_ERROR_TPM_UNKNOWN_DIGEST
+Value:  0xc0008020
+======  ===========================
+
+Description:
+
+The TPM 2.0 event log reports an unsupported hashing algorithm. Secure launch
+currently only supports two algorithms: SHA1 and SHA256.
+
+======  ==========================
+Name:   SL_ERROR_TPM_INVALID_EVENT
+Value:  0xc0008021
+======  ==========================
+
+Description:
+
+An invalid/malformed event was found in the TPM event log while reading it.
+Since only trusted entities are supposed to be writing the event log, this
+would indicate either a bug or a possible attack.
+
+======  =====================
+Name:   SL_ERROR_INVALID_SLRT
+Value:  0xc0008022
+======  =====================
+
+Description:
+
+The Secure Launch Resource Table is invalid or malformed and is unusable.
+This implies the pre-launch code did not properly setup the SLRT.
+
+======  ===========================
+Name:   SL_ERROR_SLRT_MISSING_ENTRY
+Value:  0xc0008023
+======  ===========================
+
+Description:
+
+The Secure Launch Resource Table is missing a required entry within it.
+This implies the pre-launch code did not properly setup the SLRT.
+
+======  =================
+Name:   SL_ERROR_SLRT_MAP
+Value:  0xc0008024
+======  =================
+
+Description:
+
+An error occurred in the Secure Launch module while mapping the Secure Launch
+Resource table. The underlying issue is memremap() failure, most likely due to
+a resource shortage.
+
+.. [1]
+    MLE: Measured Launch Environment is the binary runtime that is measured and
+    then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
+    requirements for the MLE in detail.
+
+.. [2]
+    PMR: Intel VTd has a feature in the IOMMU called Protected Memory Registers.
+    There are two of these registers and they allow all DMA to be blocked
+    to large areas of memory. The low PMR can cover all memory below 4Gb on 2Mb
+    boundaries. The high PMR can cover all RAM on the system, again on 2Mb
+    boundaries. This feature is used during a Secure Launch by TXT.
+
+.. [3]
+    Secure Launch Specification: https://trenchboot.org/specifications/Secure_Launch/
diff --git a/Documentation/security/launch-integrity/secure_launch_overview.rst b/Documentation/security/launch-integrity/secure_launch_overview.rst
new file mode 100644
index 0000000..ba91d73
--- /dev/null
+++ b/Documentation/security/launch-integrity/secure_launch_overview.rst
@@ -0,0 +1,220 @@
+======================
+Secure Launch Overview
+======================
+
+Overview
+========
+
+Prior to the start of the TrenchBoot project, the only active Open Source
+project supporting dynamic launch was Intel's tboot project to support their
+implementation of dynamic launch known as Intel Trusted eXecution Technology
+(TXT). The approach taken by tboot was to provide an exokernel that could
+handle the launch protocol implemented by Intel's special loader, the SINIT
+Authenticated Code Module (ACM [2]_) and remained in memory to manage the SMX
+CPU mode that a dynamic launch would put a system. While it is not precluded
+from being used for doing a late launch, tboot's primary use case was to be
+used as an early launch solution. As a result the TrenchBoot project started
+the development of Secure Launch kernel feature to provide a more generalized
+approach. The focus of the effort is twofold, the first is to make the Linux
+kernel directly aware of the launch protocol used by Intel, AMD/Hygon, Arm, and
+potentially OpenPOWER. The second is to make the Linux kernel be able to
+initiate a dynamic launch. It is through this approach that the Secure Launch
+kernel feature creates a basis for the Linux kernel to be used in a variety of
+dynamic launch use cases.
+
+.. note::
+    A quick note on terminology. The larger open source project itself is
+    called TrenchBoot, which is hosted on GitHub (links below). The kernel
+    feature enabling the use of the x86 technology is referred to as "Secure
+    Launch" within the kernel code.
+
+Goals
+=====
+
+The first use case that the TrenchBoot project focused on was the ability for
+the Linux kernel to be started by a dynamic launch, in particular as part of an
+early launch sequence. In this case the dynamic launch will be initiated by any
+boot loader with associated support added to it, for example the first targeted
+boot loader in this case was GRUB2. An integral part of establishing a
+measurement-based launch integrity involves measuring everything that is
+intended to be executed (kernel image, initrd, etc) and everything that will
+configure that kernel to execute (command line, boot params, etc). Then storing
+those measurements in a protected manner. Both the Intel and AMD dynamic launch
+implementations leverage the Trusted Platform Module (TPM) to store those
+measurements. The TPM itself has been designed such that a dynamic launch
+unlocks a specific set of Platform Configuration Registers (PCR) for holding
+measurement taken during the dynamic launch.  These are referred to as the DRTM
+PCRs, PCRs 17-22. Further details on this process can be found in the
+documentation for the GETSEC instruction provided by Intel's TXT and the SKINIT
+instruction provided by AMD's AMD-V. The documentation on these technologies
+can be readily found online; see the `Resources`_ section below for references.
+
+.. note::
+    Currently only Intel TXT is supported in this first release of the Secure
+    Launch feature. AMD/Hygon SKINIT and Arm support will be added in a
+    subsequent release.
+
+To enable the kernel to be launched by GETSEC a stub, the Secure Launch stub,
+must be built into the setup section of the compressed kernel to handle the
+specific state that the dynamic launch process leaves the BSP. Also the Secure
+Launch stub must measure everything that is going to be used as early as
+possible. This stub code and subsequent code must also deal with the specific
+state that the dynamic launch leaves the APs as well.
+
+Design Decisions
+================
+
+A number of design decisions were made during the development of the Secure
+Launch feature. The two primary guiding decisions were:
+
+ - Keeping the Secure Launch code as separate from the rest of the kernel
+   as possible.
+ - Modifying the existing boot path of the kernel as little as possible.
+
+The following illustrate how the implementation followed these design
+decisions:
+
+ - All the entry point code necessary to properly configure the system post
+   launch is found in st_stub.S in the compressed kernel image. This code
+   validates the state of the system, restores necessary system operating
+   configurations and properly handles post launch CPU states.
+ - After the sl_stub.S is complete, it jumps directly to the unmodified
+   startup_32 kernel entry point.
+ - A single call is made to a function sl_main() prior to the main kernel
+   decompression step. This code performs further validation and takes the
+   needed DRTM measurements.
+ - After the call to sl_main(), the main kernel is decompressed and boots as
+   it normally would.
+ - Final setup for the Secure Launch kernel is done in a separate Secure
+   Launch module that is loaded via a late initcall. This code is responsible
+   for extending the measurements taken earlier into the TPM DRTM PCRs and
+   setting up the securityfs interface to allow access the TPM event log and
+   public TXT registers.
+ - On the reboot and kexec paths, calls are made to a function to finalize the
+   state of the Secure Launch kernel.
+
+The one place where Secure Launch code is mixed directly in with kernel code is
+in the SMP boot code. This is due to the unique state that the dynamic launch
+leaves the APs in. On Intel this involves using a method other than the
+standard INIT-SIPI sequence.
+
+A final note is that originally the extending of the PCRs was completed in the
+Secure Launch stub when the measurements were taken. An alternative solution
+had to be implemented due to the TPM maintainers objecting to the PCR
+extensions being done with a minimal interface to the TPM that was an
+independent implementation of the mainline kernel driver. Since the mainline
+driver relies heavily on kernel interfaces not available in the compressed
+kernel, it was not possible to reuse the mainline TPM driver. This resulted in
+the decision to move the extension operations to the Secure Launch module in
+the mainline kernel where the TPM driver would be available.
+
+Basic Boot Flow
+===============
+
+Outlined here is summary of the boot flow for Secure Launch. A more detailed
+review of Secure Launch process can be found in the Secure Launch
+Specification, a link is located in the `Resources`_ section.
+
+Pre-launch: *Phase where the environment is prepared and configured to initiate the
+secure launch by the boot chain.*
+
+ - The SLRT is initialized and dl_stub is placed in memory.
+ - Load the kernel, initrd and ACM [2]_ into memory.
+ - Setup the TXT heap and page tables describing the MLE [1]_ per the
+   specification.
+ - If non-UEFI platform, dl_stub is called.
+ - If UEFI platforms, SLRT registered with UEFI and efi-stub called.
+ - Upon completion, efi-stub will call EBS followed by dl_stub.
+ - The dl_stub will prepare the CPU and the TPM for the launch.
+ - The secure launch is then initiated with the GETSET[SENTER] instruction.
+
+Post-launch: *Phase where control is passed from the ACM to the MLE and the secure
+kernel begins execution.*
+
+ - Entry from the dynamic launch jumps to the SL stub.
+ - SL stub fixes up the world on the BSP.
+ - For TXT, SL stub wakes the APs, fixes up their worlds.
+ - For TXT, APs are left halted waiting for an NMI to wake them.
+ - SL stub jumps to startup_32.
+ - SL main does validation of buffers and memory locations. It sets
+   the boot parameter loadflag value SLAUNCH_FLAG to inform the main
+   kernel that a Secure Launch was done.
+ - SL main locates the TPM event log and writes the measurements of
+   configuration and module information into it.
+ - Kernel boot proceeds normally from this point.
+ - During early setup, slaunch_setup() runs to finish some validation
+   and setup tasks.
+ - The SMP bring up code is modified to wake the waiting APs. APs vector
+   to rmpiggy and start up normally from that point.
+ - SL platform module is registered as a late initcall module. It reads
+   the TPM event log and extends the measurements taken into the TPM PCRs.
+ - SL platform module initializes the securityfs interface to allow
+   access to the TPM event log and TXT public registers.
+ - Kernel boot finishes booting normally
+ - SEXIT support to leave SMX mode is present on the kexec path and
+   the various reboot paths (poweroff, reset, halt).
+
+PCR Usage
+=========
+
+The TCG DRTM architecture there are three PCRs defined for usage, PCR.Details
+(PCR17), PCR.Authorities (PCR18), and PCR.DLME_Authority (PCR19). For a deeper
+understanding of Detail and Authorities it is recommended to review the TCG
+DRTM architecture.
+
+To determine PCR usage, Linux Secure Launch follows the TrenchBoot Secure
+Launch Specification of using a measurement policy stored in the SLRT. The
+policy details what should be measured and the PCR in which to store the
+measurement. The measurement policy provides the ability to select the
+PCR.DLME_Detail (PCR20) PCR as the location for the DRTM components measured by
+the kernel, e.g. external initrd image. This can then be combined with storing
+the user authority in the PCR.DLME_Authority PCR to seal/attest to different
+variations of platform details/authorities and user details/authorities. An
+example of how this can be achieved was presented in the FOSDEM - 2021 talk
+"Secure Upgrades with DRTM".
+
+Resources
+=========
+
+The TrenchBoot project:
+
+https://trenchboot.org
+
+Secure Launch Specification:
+
+https://trenchboot.org/specifications/Secure_Launch/
+
+Trusted Computing Group's D-RTM Architecture:
+
+https://trustedcomputinggroup.org/wp-content/uploads/TCG_D-RTM_Architecture_v1-0_Published_06172013.pdf
+
+TXT documentation in the Intel TXT MLE Development Guide:
+
+https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
+
+TXT instructions documentation in the Intel SDM Instruction Set volume:
+
+https://software.intel.com/en-us/articles/intel-sdm
+
+AMD SKINIT documentation in the System Programming manual:
+
+https://www.amd.com/system/files/TechDocs/24593.pdf
+
+GRUB Secure Launch support:
+
+https://github.com/TrenchBoot/grub/tree/grub-sl-fc-38-dlstub
+
+FOSDEM 2021: Secure Upgrades with DRTM
+
+https://archive.fosdem.org/2021/schedule/event/firmware_suwd/
+
+.. [1]
+    MLE: Measured Launch Environment is the binary runtime that is measured and
+    then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
+    requirements for the MLE in detail.
+
+.. [2]
+    ACM: Intel's Authenticated Code Module. This is the 32b bit binary blob that
+    is run securely by the GETSEC[SENTER] during a measured launch. It is described
+    in the Intel documentation on TXT and versions for various chipsets are
+    signed and distributed by Intel.
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 03/14] x86: Secure Launch Kconfig
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

Initial bits to bring in Secure Launch functionality. Add Kconfig
options for compiling in/out the Secure Launch code.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/Kconfig | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 53bab12..85ecf3f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2041,6 +2041,18 @@ config EFI_RUNTIME_MAP
 
 	  See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
 
+config SECURE_LAUNCH
+	bool "Secure Launch support"
+	default n
+	depends on X86_64 && X86_X2APIC
+	help
+	   The Secure Launch feature allows a kernel to be loaded
+	   directly through an Intel TXT measured launch. Intel TXT
+	   establishes a Dynamic Root of Trust for Measurement (DRTM)
+	   where the CPU measures the kernel image. This feature then
+	   continues the measurement chain over kernel configuration
+	   information and init images.
+
 source "kernel/Kconfig.hz"
 
 config KEXEC
-- 
1.8.3.1


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

* [PATCH v6 03/14] x86: Secure Launch Kconfig
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

Initial bits to bring in Secure Launch functionality. Add Kconfig
options for compiling in/out the Secure Launch code.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/Kconfig | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 53bab12..85ecf3f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2041,6 +2041,18 @@ config EFI_RUNTIME_MAP
 
 	  See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
 
+config SECURE_LAUNCH
+	bool "Secure Launch support"
+	default n
+	depends on X86_64 && X86_X2APIC
+	help
+	   The Secure Launch feature allows a kernel to be loaded
+	   directly through an Intel TXT measured launch. Intel TXT
+	   establishes a Dynamic Root of Trust for Measurement (DRTM)
+	   where the CPU measures the kernel image. This feature then
+	   continues the measurement chain over kernel configuration
+	   information and init images.
+
 source "kernel/Kconfig.hz"
 
 config KEXEC
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

Introduce the Secure Launch Resource Table which forms the formal
interface between the pre and post launch code.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 include/linux/slr_table.h | 270 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 270 insertions(+)
 create mode 100644 include/linux/slr_table.h

diff --git a/include/linux/slr_table.h b/include/linux/slr_table.h
new file mode 100644
index 0000000..d4b76e5
--- /dev/null
+++ b/include/linux/slr_table.h
@@ -0,0 +1,270 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Secure Launch Resource Table
+ *
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ */
+
+#ifndef _LINUX_SLR_TABLE_H
+#define _LINUX_SLR_TABLE_H
+
+/* Put this in efi.h if it becomes a standard */
+#define SLR_TABLE_GUID				EFI_GUID(0x877a9b2a, 0x0385, 0x45d1, 0xa0, 0x34, 0x9d, 0xac, 0x9c, 0x9e, 0x56, 0x5f)
+
+/* SLR table header values */
+#define SLR_TABLE_MAGIC		0x4452544d
+#define SLR_TABLE_REVISION	1
+
+/* Current revisions for the policy and UEFI config */
+#define SLR_POLICY_REVISION		1
+#define SLR_UEFI_CONFIG_REVISION	1
+
+/* SLR defined architectures */
+#define SLR_INTEL_TXT		1
+#define SLR_AMD_SKINIT		2
+
+/* SLR defined bootloaders */
+#define SLR_BOOTLOADER_INVALID	0
+#define SLR_BOOTLOADER_GRUB	1
+
+/* Log formats */
+#define SLR_DRTM_TPM12_LOG	1
+#define SLR_DRTM_TPM20_LOG	2
+
+/* DRTM Policy Entry Flags */
+#define SLR_POLICY_FLAG_MEASURED	0x1
+#define SLR_POLICY_IMPLICIT_SIZE	0x2
+
+/* Array Lengths */
+#define TPM_EVENT_INFO_LENGTH		32
+#define TXT_VARIABLE_MTRRS_LENGTH	32
+
+/* Tags */
+#define SLR_ENTRY_INVALID	0x0000
+#define SLR_ENTRY_DL_INFO	0x0001
+#define SLR_ENTRY_LOG_INFO	0x0002
+#define SLR_ENTRY_ENTRY_POLICY	0x0003
+#define SLR_ENTRY_INTEL_INFO	0x0004
+#define SLR_ENTRY_AMD_INFO	0x0005
+#define SLR_ENTRY_ARM_INFO	0x0006
+#define SLR_ENTRY_UEFI_INFO	0x0007
+#define SLR_ENTRY_UEFI_CONFIG	0x0008
+#define SLR_ENTRY_END		0xffff
+
+/* Entity Types */
+#define SLR_ET_UNSPECIFIED	0x0000
+#define SLR_ET_SLRT		0x0001
+#define SLR_ET_BOOT_PARAMS	0x0002
+#define SLR_ET_SETUP_DATA	0x0003
+#define SLR_ET_CMDLINE		0x0004
+#define SLR_ET_UEFI_MEMMAP	0x0005
+#define SLR_ET_RAMDISK		0x0006
+#define SLR_ET_TXT_OS2MLE	0x0010
+#define SLR_ET_UNUSED		0xffff
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Primary SLR Table Header
+ */
+struct slr_table {
+	u32 magic;
+	u16 revision;
+	u16 architecture;
+	u32 size;
+	u32 max_size;
+	/* entries[] */
+} __packed;
+
+/*
+ * Common SLRT Table Header
+ */
+struct slr_entry_hdr {
+	u16 tag;
+	u16 size;
+} __packed;
+
+/*
+ * Boot loader context
+ */
+struct slr_bl_context {
+	u16 bootloader;
+	u16 reserved;
+	u64 context;
+} __packed;
+
+/*
+ * DRTM Dynamic Launch Configuration
+ */
+struct slr_entry_dl_info {
+	struct slr_entry_hdr hdr;
+	struct slr_bl_context bl_context;
+	u64 dl_handler;
+	u64 dce_base;
+	u32 dce_size;
+	u64 dlme_entry;
+} __packed;
+
+/*
+ * TPM Log Information
+ */
+struct slr_entry_log_info {
+	struct slr_entry_hdr hdr;
+	u16 format;
+	u16 reserved;
+	u64 addr;
+	u32 size;
+} __packed;
+
+/*
+ * DRTM Measurement Policy
+ */
+struct slr_entry_policy {
+	struct slr_entry_hdr hdr;
+	u16 revision;
+	u16 nr_entries;
+	/* policy_entries[] */
+} __packed;
+
+/*
+ * DRTM Measurement Entry
+ */
+struct slr_policy_entry {
+	u16 pcr;
+	u16 entity_type;
+	u16 flags;
+	u16 reserved;
+	u64 entity;
+	u64 size;
+	char evt_info[TPM_EVENT_INFO_LENGTH];
+} __packed;
+
+/*
+ * Secure Launch defined MTRR saving structures
+ */
+struct slr_txt_mtrr_pair {
+	u64 mtrr_physbase;
+	u64 mtrr_physmask;
+} __packed;
+
+struct slr_txt_mtrr_state {
+	u64 default_mem_type;
+	u64 mtrr_vcnt;
+	struct slr_txt_mtrr_pair mtrr_pair[TXT_VARIABLE_MTRRS_LENGTH];
+} __packed;
+
+/*
+ * Intel TXT Info table
+ */
+struct slr_entry_intel_info {
+	struct slr_entry_hdr hdr;
+	u64 saved_misc_enable_msr;
+	struct slr_txt_mtrr_state saved_bsp_mtrrs;
+} __packed;
+
+/*
+ * AMD SKINIT Info table
+ */
+struct slr_entry_amd_info {
+	struct slr_entry_hdr hdr;
+} __packed;
+
+/*
+ * ARM DRTM Info table
+ */
+struct slr_entry_arm_info {
+	struct slr_entry_hdr hdr;
+} __packed;
+
+struct slr_entry_uefi_config {
+	struct slr_entry_hdr hdr;
+	u16 revision;
+	u16 nr_entries;
+	/* uefi_cfg_entries[] */
+} __packed;
+
+struct slr_uefi_cfg_entry {
+	u16 pcr;
+	u16 reserved;
+	u64 cfg; /* address or value */
+	u32 size;
+	char evt_info[TPM_EVENT_INFO_LENGTH];
+} __packed;
+
+static inline void *slr_end_of_entrys(struct slr_table *table)
+{
+	return (((void *)table) + table->size);
+}
+
+static inline struct slr_entry_hdr *
+slr_next_entry(struct slr_table *table,
+		struct slr_entry_hdr *curr)
+{
+	struct slr_entry_hdr *next = (struct slr_entry_hdr *)
+				((u8 *)curr + curr->size);
+
+	if ((void *)next >= slr_end_of_entrys(table))
+		return NULL;
+	if (next->tag == SLR_ENTRY_END)
+		return NULL;
+
+	return next;
+}
+
+static inline struct slr_entry_hdr *
+slr_next_entry_by_tag(struct slr_table *table,
+		      struct slr_entry_hdr *entry,
+		      u16 tag)
+{
+	if (!entry) /* Start from the beginning */
+		entry = (struct slr_entry_hdr *)(((u8 *)table) + sizeof(*table));
+
+	for ( ; ; ) {
+		if (entry->tag == tag)
+			return entry;
+
+		entry = slr_next_entry(table, entry);
+		if (!entry)
+			return NULL;
+	}
+
+	return NULL;
+}
+
+static inline int
+slr_add_entry(struct slr_table *table,
+	      struct slr_entry_hdr *entry)
+{
+	struct slr_entry_hdr *end;
+
+	if ((table->size + entry->size) > table->max_size)
+		return -1;
+
+	memcpy((u8 *)table + table->size - sizeof(*end), entry, entry->size);
+	table->size += entry->size;
+
+	end  = (struct slr_entry_hdr *)((u8 *)table + table->size - sizeof(*end));
+	end->tag = SLR_ENTRY_END;
+	end->size = sizeof(*end);
+
+	return 0;
+}
+
+static inline void
+slr_init_table(struct slr_table *slrt, u16 architecture, u32 max_size)
+{
+	struct slr_entry_hdr *end;
+
+	slrt->magic = SLR_TABLE_MAGIC;
+	slrt->revision = SLR_TABLE_REVISION;
+	slrt->architecture = architecture;
+	slrt->size = sizeof(*slrt) + sizeof(*end);
+	slrt->max_size = max_size;
+	end = (struct slr_entry_hdr *)((u8 *)slrt + sizeof(*slrt));
+	end->tag = SLR_ENTRY_END;
+	end->size = sizeof(*end);
+}
+
+#endif /* !__ASSEMBLY */
+
+#endif /* _LINUX_SLR_TABLE_H */
-- 
1.8.3.1


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

* [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

Introduce the Secure Launch Resource Table which forms the formal
interface between the pre and post launch code.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 include/linux/slr_table.h | 270 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 270 insertions(+)
 create mode 100644 include/linux/slr_table.h

diff --git a/include/linux/slr_table.h b/include/linux/slr_table.h
new file mode 100644
index 0000000..d4b76e5
--- /dev/null
+++ b/include/linux/slr_table.h
@@ -0,0 +1,270 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Secure Launch Resource Table
+ *
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ */
+
+#ifndef _LINUX_SLR_TABLE_H
+#define _LINUX_SLR_TABLE_H
+
+/* Put this in efi.h if it becomes a standard */
+#define SLR_TABLE_GUID				EFI_GUID(0x877a9b2a, 0x0385, 0x45d1, 0xa0, 0x34, 0x9d, 0xac, 0x9c, 0x9e, 0x56, 0x5f)
+
+/* SLR table header values */
+#define SLR_TABLE_MAGIC		0x4452544d
+#define SLR_TABLE_REVISION	1
+
+/* Current revisions for the policy and UEFI config */
+#define SLR_POLICY_REVISION		1
+#define SLR_UEFI_CONFIG_REVISION	1
+
+/* SLR defined architectures */
+#define SLR_INTEL_TXT		1
+#define SLR_AMD_SKINIT		2
+
+/* SLR defined bootloaders */
+#define SLR_BOOTLOADER_INVALID	0
+#define SLR_BOOTLOADER_GRUB	1
+
+/* Log formats */
+#define SLR_DRTM_TPM12_LOG	1
+#define SLR_DRTM_TPM20_LOG	2
+
+/* DRTM Policy Entry Flags */
+#define SLR_POLICY_FLAG_MEASURED	0x1
+#define SLR_POLICY_IMPLICIT_SIZE	0x2
+
+/* Array Lengths */
+#define TPM_EVENT_INFO_LENGTH		32
+#define TXT_VARIABLE_MTRRS_LENGTH	32
+
+/* Tags */
+#define SLR_ENTRY_INVALID	0x0000
+#define SLR_ENTRY_DL_INFO	0x0001
+#define SLR_ENTRY_LOG_INFO	0x0002
+#define SLR_ENTRY_ENTRY_POLICY	0x0003
+#define SLR_ENTRY_INTEL_INFO	0x0004
+#define SLR_ENTRY_AMD_INFO	0x0005
+#define SLR_ENTRY_ARM_INFO	0x0006
+#define SLR_ENTRY_UEFI_INFO	0x0007
+#define SLR_ENTRY_UEFI_CONFIG	0x0008
+#define SLR_ENTRY_END		0xffff
+
+/* Entity Types */
+#define SLR_ET_UNSPECIFIED	0x0000
+#define SLR_ET_SLRT		0x0001
+#define SLR_ET_BOOT_PARAMS	0x0002
+#define SLR_ET_SETUP_DATA	0x0003
+#define SLR_ET_CMDLINE		0x0004
+#define SLR_ET_UEFI_MEMMAP	0x0005
+#define SLR_ET_RAMDISK		0x0006
+#define SLR_ET_TXT_OS2MLE	0x0010
+#define SLR_ET_UNUSED		0xffff
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Primary SLR Table Header
+ */
+struct slr_table {
+	u32 magic;
+	u16 revision;
+	u16 architecture;
+	u32 size;
+	u32 max_size;
+	/* entries[] */
+} __packed;
+
+/*
+ * Common SLRT Table Header
+ */
+struct slr_entry_hdr {
+	u16 tag;
+	u16 size;
+} __packed;
+
+/*
+ * Boot loader context
+ */
+struct slr_bl_context {
+	u16 bootloader;
+	u16 reserved;
+	u64 context;
+} __packed;
+
+/*
+ * DRTM Dynamic Launch Configuration
+ */
+struct slr_entry_dl_info {
+	struct slr_entry_hdr hdr;
+	struct slr_bl_context bl_context;
+	u64 dl_handler;
+	u64 dce_base;
+	u32 dce_size;
+	u64 dlme_entry;
+} __packed;
+
+/*
+ * TPM Log Information
+ */
+struct slr_entry_log_info {
+	struct slr_entry_hdr hdr;
+	u16 format;
+	u16 reserved;
+	u64 addr;
+	u32 size;
+} __packed;
+
+/*
+ * DRTM Measurement Policy
+ */
+struct slr_entry_policy {
+	struct slr_entry_hdr hdr;
+	u16 revision;
+	u16 nr_entries;
+	/* policy_entries[] */
+} __packed;
+
+/*
+ * DRTM Measurement Entry
+ */
+struct slr_policy_entry {
+	u16 pcr;
+	u16 entity_type;
+	u16 flags;
+	u16 reserved;
+	u64 entity;
+	u64 size;
+	char evt_info[TPM_EVENT_INFO_LENGTH];
+} __packed;
+
+/*
+ * Secure Launch defined MTRR saving structures
+ */
+struct slr_txt_mtrr_pair {
+	u64 mtrr_physbase;
+	u64 mtrr_physmask;
+} __packed;
+
+struct slr_txt_mtrr_state {
+	u64 default_mem_type;
+	u64 mtrr_vcnt;
+	struct slr_txt_mtrr_pair mtrr_pair[TXT_VARIABLE_MTRRS_LENGTH];
+} __packed;
+
+/*
+ * Intel TXT Info table
+ */
+struct slr_entry_intel_info {
+	struct slr_entry_hdr hdr;
+	u64 saved_misc_enable_msr;
+	struct slr_txt_mtrr_state saved_bsp_mtrrs;
+} __packed;
+
+/*
+ * AMD SKINIT Info table
+ */
+struct slr_entry_amd_info {
+	struct slr_entry_hdr hdr;
+} __packed;
+
+/*
+ * ARM DRTM Info table
+ */
+struct slr_entry_arm_info {
+	struct slr_entry_hdr hdr;
+} __packed;
+
+struct slr_entry_uefi_config {
+	struct slr_entry_hdr hdr;
+	u16 revision;
+	u16 nr_entries;
+	/* uefi_cfg_entries[] */
+} __packed;
+
+struct slr_uefi_cfg_entry {
+	u16 pcr;
+	u16 reserved;
+	u64 cfg; /* address or value */
+	u32 size;
+	char evt_info[TPM_EVENT_INFO_LENGTH];
+} __packed;
+
+static inline void *slr_end_of_entrys(struct slr_table *table)
+{
+	return (((void *)table) + table->size);
+}
+
+static inline struct slr_entry_hdr *
+slr_next_entry(struct slr_table *table,
+		struct slr_entry_hdr *curr)
+{
+	struct slr_entry_hdr *next = (struct slr_entry_hdr *)
+				((u8 *)curr + curr->size);
+
+	if ((void *)next >= slr_end_of_entrys(table))
+		return NULL;
+	if (next->tag == SLR_ENTRY_END)
+		return NULL;
+
+	return next;
+}
+
+static inline struct slr_entry_hdr *
+slr_next_entry_by_tag(struct slr_table *table,
+		      struct slr_entry_hdr *entry,
+		      u16 tag)
+{
+	if (!entry) /* Start from the beginning */
+		entry = (struct slr_entry_hdr *)(((u8 *)table) + sizeof(*table));
+
+	for ( ; ; ) {
+		if (entry->tag == tag)
+			return entry;
+
+		entry = slr_next_entry(table, entry);
+		if (!entry)
+			return NULL;
+	}
+
+	return NULL;
+}
+
+static inline int
+slr_add_entry(struct slr_table *table,
+	      struct slr_entry_hdr *entry)
+{
+	struct slr_entry_hdr *end;
+
+	if ((table->size + entry->size) > table->max_size)
+		return -1;
+
+	memcpy((u8 *)table + table->size - sizeof(*end), entry, entry->size);
+	table->size += entry->size;
+
+	end  = (struct slr_entry_hdr *)((u8 *)table + table->size - sizeof(*end));
+	end->tag = SLR_ENTRY_END;
+	end->size = sizeof(*end);
+
+	return 0;
+}
+
+static inline void
+slr_init_table(struct slr_table *slrt, u16 architecture, u32 max_size)
+{
+	struct slr_entry_hdr *end;
+
+	slrt->magic = SLR_TABLE_MAGIC;
+	slrt->revision = SLR_TABLE_REVISION;
+	slrt->architecture = architecture;
+	slrt->size = sizeof(*slrt) + sizeof(*end);
+	slrt->max_size = max_size;
+	end = (struct slr_entry_hdr *)((u8 *)slrt + sizeof(*slrt));
+	end->tag = SLR_ENTRY_END;
+	end->size = sizeof(*end);
+}
+
+#endif /* !__ASSEMBLY */
+
+#endif /* _LINUX_SLR_TABLE_H */
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 05/14] x86: Secure Launch main header file
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

Introduce the main Secure Launch header file used in the early SL stub
and the early setup code.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 include/linux/slaunch.h | 513 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 513 insertions(+)
 create mode 100644 include/linux/slaunch.h

diff --git a/include/linux/slaunch.h b/include/linux/slaunch.h
new file mode 100644
index 0000000..a1c3172
--- /dev/null
+++ b/include/linux/slaunch.h
@@ -0,0 +1,513 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Main Secure Launch header file.
+ *
+ * Copyright (c) 2022, Oracle and/or its affiliates.
+ */
+
+#ifndef _LINUX_SLAUNCH_H
+#define _LINUX_SLAUNCH_H
+
+/*
+ * Secure Launch Defined State Flags
+ */
+#define SL_FLAG_ACTIVE		0x00000001
+#define SL_FLAG_ARCH_SKINIT	0x00000002
+#define SL_FLAG_ARCH_TXT	0x00000004
+
+/*
+ * Secure Launch CPU Type
+ */
+#define SL_CPU_AMD	1
+#define SL_CPU_INTEL	2
+
+#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
+
+#define __SL32_CS	0x0008
+#define __SL32_DS	0x0010
+
+/*
+ * Intel Safer Mode Extensions (SMX)
+ *
+ * Intel SMX provides a programming interface to establish a Measured Launched
+ * Environment (MLE). The measurement and protection mechanisms supported by the
+ * capabilities of an Intel Trusted Execution Technology (TXT) platform. SMX is
+ * the processor’s programming interface in an Intel TXT platform.
+ *
+ * See Intel SDM Volume 2 - 6.1 "Safer Mode Extensions Reference"
+ */
+
+/*
+ * SMX GETSEC Leaf Functions
+ */
+#define SMX_X86_GETSEC_SEXIT	5
+#define SMX_X86_GETSEC_SMCTRL	7
+#define SMX_X86_GETSEC_WAKEUP	8
+
+/*
+ * Intel Trusted Execution Technology MMIO Registers Banks
+ */
+#define TXT_PUB_CONFIG_REGS_BASE	0xfed30000
+#define TXT_PRIV_CONFIG_REGS_BASE	0xfed20000
+#define TXT_NR_CONFIG_PAGES     ((TXT_PUB_CONFIG_REGS_BASE - \
+				  TXT_PRIV_CONFIG_REGS_BASE) >> PAGE_SHIFT)
+
+/*
+ * Intel Trusted Execution Technology (TXT) Registers
+ */
+#define TXT_CR_STS			0x0000
+#define TXT_CR_ESTS			0x0008
+#define TXT_CR_ERRORCODE		0x0030
+#define TXT_CR_CMD_RESET		0x0038
+#define TXT_CR_CMD_CLOSE_PRIVATE	0x0048
+#define TXT_CR_DIDVID			0x0110
+#define TXT_CR_VER_EMIF			0x0200
+#define TXT_CR_CMD_UNLOCK_MEM_CONFIG	0x0218
+#define TXT_CR_SINIT_BASE		0x0270
+#define TXT_CR_SINIT_SIZE		0x0278
+#define TXT_CR_MLE_JOIN			0x0290
+#define TXT_CR_HEAP_BASE		0x0300
+#define TXT_CR_HEAP_SIZE		0x0308
+#define TXT_CR_SCRATCHPAD		0x0378
+#define TXT_CR_CMD_OPEN_LOCALITY1	0x0380
+#define TXT_CR_CMD_CLOSE_LOCALITY1	0x0388
+#define TXT_CR_CMD_OPEN_LOCALITY2	0x0390
+#define TXT_CR_CMD_CLOSE_LOCALITY2	0x0398
+#define TXT_CR_CMD_SECRETS		0x08e0
+#define TXT_CR_CMD_NO_SECRETS		0x08e8
+#define TXT_CR_E2STS			0x08f0
+
+/* TXT default register value */
+#define TXT_REGVALUE_ONE		0x1ULL
+
+/* TXTCR_STS status bits */
+#define TXT_SENTER_DONE_STS		(1<<0)
+#define TXT_SEXIT_DONE_STS		(1<<1)
+
+/*
+ * SINIT/MLE Capabilities Field Bit Definitions
+ */
+#define TXT_SINIT_MLE_CAP_WAKE_GETSEC	0
+#define TXT_SINIT_MLE_CAP_WAKE_MONITOR	1
+
+/*
+ * OS/MLE Secure Launch Specific Definitions
+ */
+#define TXT_OS_MLE_STRUCT_VERSION	1
+#define TXT_OS_MLE_MAX_VARIABLE_MTRRS	32
+
+/*
+ * TXT Heap Table Enumeration
+ */
+#define TXT_BIOS_DATA_TABLE		1
+#define TXT_OS_MLE_DATA_TABLE		2
+#define TXT_OS_SINIT_DATA_TABLE		3
+#define TXT_SINIT_MLE_DATA_TABLE	4
+#define TXT_SINIT_TABLE_MAX		TXT_SINIT_MLE_DATA_TABLE
+
+/*
+ * Secure Launch Defined Error Codes used in MLE-initiated TXT resets.
+ *
+ * TXT Specification
+ * Appendix I ACM Error Codes
+ */
+#define SL_ERROR_GENERIC		0xc0008001
+#define SL_ERROR_TPM_INIT		0xc0008002
+#define SL_ERROR_TPM_INVALID_LOG20	0xc0008003
+#define SL_ERROR_TPM_LOGGING_FAILED	0xc0008004
+#define SL_ERROR_REGION_STRADDLE_4GB	0xc0008005
+#define SL_ERROR_TPM_EXTEND		0xc0008006
+#define SL_ERROR_MTRR_INV_VCNT		0xc0008007
+#define SL_ERROR_MTRR_INV_DEF_TYPE	0xc0008008
+#define SL_ERROR_MTRR_INV_BASE		0xc0008009
+#define SL_ERROR_MTRR_INV_MASK		0xc000800a
+#define SL_ERROR_MSR_INV_MISC_EN	0xc000800b
+#define SL_ERROR_INV_AP_INTERRUPT	0xc000800c
+#define SL_ERROR_INTEGER_OVERFLOW	0xc000800d
+#define SL_ERROR_HEAP_WALK		0xc000800e
+#define SL_ERROR_HEAP_MAP		0xc000800f
+#define SL_ERROR_REGION_ABOVE_4GB	0xc0008010
+#define SL_ERROR_HEAP_INVALID_DMAR	0xc0008011
+#define SL_ERROR_HEAP_DMAR_SIZE		0xc0008012
+#define SL_ERROR_HEAP_DMAR_MAP		0xc0008013
+#define SL_ERROR_HI_PMR_BASE		0xc0008014
+#define SL_ERROR_HI_PMR_SIZE		0xc0008015
+#define SL_ERROR_LO_PMR_BASE		0xc0008016
+#define SL_ERROR_LO_PMR_MLE		0xc0008017
+#define SL_ERROR_INITRD_TOO_BIG		0xc0008018
+#define SL_ERROR_HEAP_ZERO_OFFSET	0xc0008019
+#define SL_ERROR_WAKE_BLOCK_TOO_SMALL	0xc000801a
+#define SL_ERROR_MLE_BUFFER_OVERLAP	0xc000801b
+#define SL_ERROR_BUFFER_BEYOND_PMR	0xc000801c
+#define SL_ERROR_OS_SINIT_BAD_VERSION	0xc000801d
+#define SL_ERROR_EVENTLOG_MAP		0xc000801e
+#define SL_ERROR_TPM_NUMBER_ALGS	0xc000801f
+#define SL_ERROR_TPM_UNKNOWN_DIGEST	0xc0008020
+#define SL_ERROR_TPM_INVALID_EVENT	0xc0008021
+#define SL_ERROR_INVALID_SLRT		0xc0008022
+#define SL_ERROR_SLRT_MISSING_ENTRY	0xc0008023
+#define SL_ERROR_SLRT_MAP		0xc0008024
+
+/*
+ * Secure Launch Defined Limits
+ */
+#define TXT_MAX_CPUS		512
+#define TXT_BOOT_STACK_SIZE	24
+
+/*
+ * Secure Launch event log entry type. The TXT specification defines the
+ * base event value as 0x400 for DRTM values.
+ */
+#define TXT_EVTYPE_BASE			0x400
+#define TXT_EVTYPE_SLAUNCH		(TXT_EVTYPE_BASE + 0x102)
+#define TXT_EVTYPE_SLAUNCH_START	(TXT_EVTYPE_BASE + 0x103)
+#define TXT_EVTYPE_SLAUNCH_END		(TXT_EVTYPE_BASE + 0x104)
+
+/*
+ * Measured Launch PCRs
+ */
+#define SL_DEF_DLME_DETAIL_PCR17	17
+#define SL_DEF_DLME_AUTHORITY_PCR18	18
+#define SL_ALT_DLME_AUTHORITY_PCR19	19
+#define SL_ALT_DLME_DETAIL_PCR20	20
+
+/*
+ * MLE scratch area offsets
+ */
+#define SL_SCRATCH_AP_EBX		0
+#define SL_SCRATCH_AP_JMP_OFFSET	4
+#define SL_SCRATCH_AP_PAUSE		8
+
+#ifndef __ASSEMBLY__
+
+#include <linux/io.h>
+#include <linux/tpm.h>
+#include <linux/tpm_eventlog.h>
+
+/*
+ * Secure Launch AP wakeup information fetched in SMP boot code.
+ */
+struct sl_ap_wake_info {
+	u32 ap_wake_block;
+	u32 ap_wake_block_size;
+	u32 ap_jmp_offset;
+};
+
+/*
+ * TXT heap extended data elements.
+ */
+struct txt_heap_ext_data_element {
+	u32 type;
+	u32 size;
+	/* Data */
+} __packed;
+
+#define TXT_HEAP_EXTDATA_TYPE_END			0
+
+struct txt_heap_end_element {
+	u32 type;
+	u32 size;
+} __packed;
+
+#define TXT_HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR		5
+
+struct txt_heap_event_log_element {
+	u64 event_log_phys_addr;
+} __packed;
+
+#define TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1	8
+
+struct txt_heap_event_log_pointer2_1_element {
+	u64 phys_addr;
+	u32 allocated_event_container_size;
+	u32 first_record_offset;
+	u32 next_record_offset;
+} __packed;
+
+/*
+ * Secure Launch defined OS/MLE TXT Heap table
+ */
+struct txt_os_mle_data {
+	u32 version;
+	u32 boot_params_addr;
+	u64 slrt;
+	u64 txt_info;
+	u32 ap_wake_block;
+	u32 ap_wake_block_size;
+	u8 mle_scratch[64];
+} __packed;
+
+/*
+ * TXT specification defined BIOS data TXT Heap table
+ */
+struct txt_bios_data {
+	u32 version; /* Currently 5 for TPM 1.2 and 6 for TPM 2.0 */
+	u32 bios_sinit_size;
+	u64 reserved1;
+	u64 reserved2;
+	u32 num_logical_procs;
+	/* Versions >= 5 with updates in version 6 */
+	u32 sinit_flags;
+	u32 mle_flags;
+	/* Versions >= 4 */
+	/* Ext Data Elements */
+} __packed;
+
+/*
+ * TXT specification defined OS/SINIT TXT Heap table
+ */
+struct txt_os_sinit_data {
+	u32 version; /* Currently 6 for TPM 1.2 and 7 for TPM 2.0 */
+	u32 flags;
+	u64 mle_ptab;
+	u64 mle_size;
+	u64 mle_hdr_base;
+	u64 vtd_pmr_lo_base;
+	u64 vtd_pmr_lo_size;
+	u64 vtd_pmr_hi_base;
+	u64 vtd_pmr_hi_size;
+	u64 lcp_po_base;
+	u64 lcp_po_size;
+	u32 capabilities;
+	/* Version = 5 */
+	u64 efi_rsdt_ptr;
+	/* Versions >= 6 */
+	/* Ext Data Elements */
+} __packed;
+
+/*
+ * TXT specification defined SINIT/MLE TXT Heap table
+ */
+struct txt_sinit_mle_data {
+	u32 version;             /* Current values are 6 through 9 */
+	/* Versions <= 8 */
+	u8 bios_acm_id[20];
+	u32 edx_senter_flags;
+	u64 mseg_valid;
+	u8 sinit_hash[20];
+	u8 mle_hash[20];
+	u8 stm_hash[20];
+	u8 lcp_policy_hash[20];
+	u32 lcp_policy_control;
+	/* Versions >= 7 */
+	u32 rlp_wakeup_addr;
+	u32 reserved;
+	u32 num_of_sinit_mdrs;
+	u32 sinit_mdrs_table_offset;
+	u32 sinit_vtd_dmar_table_size;
+	u32 sinit_vtd_dmar_table_offset;
+	/* Versions >= 8 */
+	u32 processor_scrtm_status;
+	/* Versions >= 9 */
+	/* Ext Data Elements */
+} __packed;
+
+/*
+ * TXT data reporting structure for memory types
+ */
+struct txt_sinit_memory_descriptor_record {
+	u64 address;
+	u64 length;
+	u8 type;
+	u8 reserved[7];
+} __packed;
+
+/*
+ * TXT data structure used by a responsive local processor (RLP) to start
+ * execution in response to a GETSEC[WAKEUP].
+ */
+struct smx_rlp_mle_join {
+	u32 rlp_gdt_limit;
+	u32 rlp_gdt_base;
+	u32 rlp_seg_sel;     /* cs (ds, es, ss are seg_sel+8) */
+	u32 rlp_entry_point; /* phys addr */
+} __packed;
+
+/*
+ * TPM event log structures defined in both the TXT specification and
+ * the TCG documentation.
+ */
+#define TPM12_EVTLOG_SIGNATURE "TXT Event Container"
+
+struct tpm12_event_log_header {
+	char signature[20];
+	char reserved[12];
+	u8 container_ver_major;
+	u8 container_ver_minor;
+	u8 pcr_event_ver_major;
+	u8 pcr_event_ver_minor;
+	u32 container_size;
+	u32 pcr_events_offset;
+	u32 next_event_offset;
+	/* PCREvents[] */
+} __packed;
+
+/*
+ * Functions to extract data from the Intel TXT Heap Memory. The layout
+ * of the heap is as follows:
+ *  +----------------------------+
+ *  | Size Bios Data table (u64) |
+ *  +----------------------------+
+ *  | Bios Data table            |
+ *  +----------------------------+
+ *  | Size OS MLE table (u64)    |
+ *  +----------------------------+
+ *  | OS MLE table               |
+ *  +--------------------------- +
+ *  | Size OS SINIT table (u64)  |
+ *  +----------------------------+
+ *  | OS SINIT table             |
+ *  +----------------------------+
+ *  | Size SINIT MLE table (u64) |
+ *  +----------------------------+
+ *  | SINIT MLE table            |
+ *  +----------------------------+
+ *
+ *  NOTE: the table size fields include the 8 byte size field itself.
+ */
+static inline u64 txt_bios_data_size(void *heap)
+{
+	return *((u64 *)heap);
+}
+
+static inline void *txt_bios_data_start(void *heap)
+{
+	return heap + sizeof(u64);
+}
+
+static inline u64 txt_os_mle_data_size(void *heap)
+{
+	return *((u64 *)(heap + txt_bios_data_size(heap)));
+}
+
+static inline void *txt_os_mle_data_start(void *heap)
+{
+	return heap + txt_bios_data_size(heap) + sizeof(u64);
+}
+
+static inline u64 txt_os_sinit_data_size(void *heap)
+{
+	return *((u64 *)(heap + txt_bios_data_size(heap) +
+			txt_os_mle_data_size(heap)));
+}
+
+static inline void *txt_os_sinit_data_start(void *heap)
+{
+	return heap + txt_bios_data_size(heap) +
+		txt_os_mle_data_size(heap) + sizeof(u64);
+}
+
+static inline u64 txt_sinit_mle_data_size(void *heap)
+{
+	return *((u64 *)(heap + txt_bios_data_size(heap) +
+			txt_os_mle_data_size(heap) +
+			txt_os_sinit_data_size(heap)));
+}
+
+static inline void *txt_sinit_mle_data_start(void *heap)
+{
+	return heap + txt_bios_data_size(heap) +
+		txt_os_mle_data_size(heap) +
+		txt_os_sinit_data_size(heap) + sizeof(u64);
+}
+
+/*
+ * TPM event logging functions.
+ */
+static inline struct txt_heap_event_log_pointer2_1_element*
+tpm20_find_log2_1_element(struct txt_os_sinit_data *os_sinit_data)
+{
+	struct txt_heap_ext_data_element *ext_elem;
+
+	/* The extended element array as at the end of this table */
+	ext_elem = (struct txt_heap_ext_data_element *)
+		((u8 *)os_sinit_data + sizeof(struct txt_os_sinit_data));
+
+	while (ext_elem->type != TXT_HEAP_EXTDATA_TYPE_END) {
+		if (ext_elem->type ==
+		    TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1) {
+			return (struct txt_heap_event_log_pointer2_1_element *)
+				((u8 *)ext_elem +
+					sizeof(struct txt_heap_ext_data_element));
+		}
+		ext_elem =
+			(struct txt_heap_ext_data_element *)
+			((u8 *)ext_elem + ext_elem->size);
+	}
+
+	return NULL;
+}
+
+static inline int tpm12_log_event(void *evtlog_base, u32 evtlog_size,
+				  u32 event_size, void *event)
+{
+	struct tpm12_event_log_header *evtlog =
+		(struct tpm12_event_log_header *)evtlog_base;
+
+	if (memcmp(evtlog->signature, TPM12_EVTLOG_SIGNATURE,
+		   sizeof(TPM12_EVTLOG_SIGNATURE)))
+		return -EINVAL;
+
+	if (evtlog->container_size > evtlog_size)
+		return -EINVAL;
+
+	if (evtlog->next_event_offset + event_size > evtlog->container_size)
+		return -E2BIG;
+
+	memcpy(evtlog_base + evtlog->next_event_offset, event, event_size);
+	evtlog->next_event_offset += event_size;
+
+	return 0;
+}
+
+static inline int tpm20_log_event(struct txt_heap_event_log_pointer2_1_element *elem,
+				  void *evtlog_base, u32 evtlog_size,
+				  u32 event_size, void *event)
+{
+	struct tcg_pcr_event *header =
+		(struct tcg_pcr_event *)evtlog_base;
+
+	/* Has to be at least big enough for the signature */
+	if (header->event_size < sizeof(TCG_SPECID_SIG))
+		return -EINVAL;
+
+	if (memcmp((u8 *)header + sizeof(struct tcg_pcr_event),
+		   TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
+		return -EINVAL;
+
+	if (elem->allocated_event_container_size > evtlog_size)
+		return -EINVAL;
+
+	if (elem->next_record_offset + event_size >
+	    elem->allocated_event_container_size)
+		return -E2BIG;
+
+	memcpy(evtlog_base + elem->next_record_offset, event, event_size);
+	elem->next_record_offset += event_size;
+
+	return 0;
+}
+
+/*
+ * External functions avalailable in mainline kernel.
+ */
+extern void slaunch_setup_txt(void);
+extern u32 slaunch_get_flags(void);
+extern struct sl_ap_wake_info *slaunch_get_ap_wake_info(void);
+extern struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar);
+extern void __noreturn slaunch_txt_reset(void __iomem *txt,
+					 const char *msg, u64 error);
+extern void slaunch_finalize(int do_sexit);
+
+#endif /* !__ASSEMBLY */
+
+#else
+
+#define slaunch_setup_txt()		do { } while (0)
+#define slaunch_get_flags()		0
+#define slaunch_get_dmar_table(d)	(d)
+#define slaunch_finalize(d)		do { } while (0)
+
+#endif /* !IS_ENABLED(CONFIG_SECURE_LAUNCH) */
+
+#endif /* _LINUX_SLAUNCH_H */
-- 
1.8.3.1


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

* [PATCH v6 05/14] x86: Secure Launch main header file
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

Introduce the main Secure Launch header file used in the early SL stub
and the early setup code.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 include/linux/slaunch.h | 513 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 513 insertions(+)
 create mode 100644 include/linux/slaunch.h

diff --git a/include/linux/slaunch.h b/include/linux/slaunch.h
new file mode 100644
index 0000000..a1c3172
--- /dev/null
+++ b/include/linux/slaunch.h
@@ -0,0 +1,513 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Main Secure Launch header file.
+ *
+ * Copyright (c) 2022, Oracle and/or its affiliates.
+ */
+
+#ifndef _LINUX_SLAUNCH_H
+#define _LINUX_SLAUNCH_H
+
+/*
+ * Secure Launch Defined State Flags
+ */
+#define SL_FLAG_ACTIVE		0x00000001
+#define SL_FLAG_ARCH_SKINIT	0x00000002
+#define SL_FLAG_ARCH_TXT	0x00000004
+
+/*
+ * Secure Launch CPU Type
+ */
+#define SL_CPU_AMD	1
+#define SL_CPU_INTEL	2
+
+#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
+
+#define __SL32_CS	0x0008
+#define __SL32_DS	0x0010
+
+/*
+ * Intel Safer Mode Extensions (SMX)
+ *
+ * Intel SMX provides a programming interface to establish a Measured Launched
+ * Environment (MLE). The measurement and protection mechanisms supported by the
+ * capabilities of an Intel Trusted Execution Technology (TXT) platform. SMX is
+ * the processor’s programming interface in an Intel TXT platform.
+ *
+ * See Intel SDM Volume 2 - 6.1 "Safer Mode Extensions Reference"
+ */
+
+/*
+ * SMX GETSEC Leaf Functions
+ */
+#define SMX_X86_GETSEC_SEXIT	5
+#define SMX_X86_GETSEC_SMCTRL	7
+#define SMX_X86_GETSEC_WAKEUP	8
+
+/*
+ * Intel Trusted Execution Technology MMIO Registers Banks
+ */
+#define TXT_PUB_CONFIG_REGS_BASE	0xfed30000
+#define TXT_PRIV_CONFIG_REGS_BASE	0xfed20000
+#define TXT_NR_CONFIG_PAGES     ((TXT_PUB_CONFIG_REGS_BASE - \
+				  TXT_PRIV_CONFIG_REGS_BASE) >> PAGE_SHIFT)
+
+/*
+ * Intel Trusted Execution Technology (TXT) Registers
+ */
+#define TXT_CR_STS			0x0000
+#define TXT_CR_ESTS			0x0008
+#define TXT_CR_ERRORCODE		0x0030
+#define TXT_CR_CMD_RESET		0x0038
+#define TXT_CR_CMD_CLOSE_PRIVATE	0x0048
+#define TXT_CR_DIDVID			0x0110
+#define TXT_CR_VER_EMIF			0x0200
+#define TXT_CR_CMD_UNLOCK_MEM_CONFIG	0x0218
+#define TXT_CR_SINIT_BASE		0x0270
+#define TXT_CR_SINIT_SIZE		0x0278
+#define TXT_CR_MLE_JOIN			0x0290
+#define TXT_CR_HEAP_BASE		0x0300
+#define TXT_CR_HEAP_SIZE		0x0308
+#define TXT_CR_SCRATCHPAD		0x0378
+#define TXT_CR_CMD_OPEN_LOCALITY1	0x0380
+#define TXT_CR_CMD_CLOSE_LOCALITY1	0x0388
+#define TXT_CR_CMD_OPEN_LOCALITY2	0x0390
+#define TXT_CR_CMD_CLOSE_LOCALITY2	0x0398
+#define TXT_CR_CMD_SECRETS		0x08e0
+#define TXT_CR_CMD_NO_SECRETS		0x08e8
+#define TXT_CR_E2STS			0x08f0
+
+/* TXT default register value */
+#define TXT_REGVALUE_ONE		0x1ULL
+
+/* TXTCR_STS status bits */
+#define TXT_SENTER_DONE_STS		(1<<0)
+#define TXT_SEXIT_DONE_STS		(1<<1)
+
+/*
+ * SINIT/MLE Capabilities Field Bit Definitions
+ */
+#define TXT_SINIT_MLE_CAP_WAKE_GETSEC	0
+#define TXT_SINIT_MLE_CAP_WAKE_MONITOR	1
+
+/*
+ * OS/MLE Secure Launch Specific Definitions
+ */
+#define TXT_OS_MLE_STRUCT_VERSION	1
+#define TXT_OS_MLE_MAX_VARIABLE_MTRRS	32
+
+/*
+ * TXT Heap Table Enumeration
+ */
+#define TXT_BIOS_DATA_TABLE		1
+#define TXT_OS_MLE_DATA_TABLE		2
+#define TXT_OS_SINIT_DATA_TABLE		3
+#define TXT_SINIT_MLE_DATA_TABLE	4
+#define TXT_SINIT_TABLE_MAX		TXT_SINIT_MLE_DATA_TABLE
+
+/*
+ * Secure Launch Defined Error Codes used in MLE-initiated TXT resets.
+ *
+ * TXT Specification
+ * Appendix I ACM Error Codes
+ */
+#define SL_ERROR_GENERIC		0xc0008001
+#define SL_ERROR_TPM_INIT		0xc0008002
+#define SL_ERROR_TPM_INVALID_LOG20	0xc0008003
+#define SL_ERROR_TPM_LOGGING_FAILED	0xc0008004
+#define SL_ERROR_REGION_STRADDLE_4GB	0xc0008005
+#define SL_ERROR_TPM_EXTEND		0xc0008006
+#define SL_ERROR_MTRR_INV_VCNT		0xc0008007
+#define SL_ERROR_MTRR_INV_DEF_TYPE	0xc0008008
+#define SL_ERROR_MTRR_INV_BASE		0xc0008009
+#define SL_ERROR_MTRR_INV_MASK		0xc000800a
+#define SL_ERROR_MSR_INV_MISC_EN	0xc000800b
+#define SL_ERROR_INV_AP_INTERRUPT	0xc000800c
+#define SL_ERROR_INTEGER_OVERFLOW	0xc000800d
+#define SL_ERROR_HEAP_WALK		0xc000800e
+#define SL_ERROR_HEAP_MAP		0xc000800f
+#define SL_ERROR_REGION_ABOVE_4GB	0xc0008010
+#define SL_ERROR_HEAP_INVALID_DMAR	0xc0008011
+#define SL_ERROR_HEAP_DMAR_SIZE		0xc0008012
+#define SL_ERROR_HEAP_DMAR_MAP		0xc0008013
+#define SL_ERROR_HI_PMR_BASE		0xc0008014
+#define SL_ERROR_HI_PMR_SIZE		0xc0008015
+#define SL_ERROR_LO_PMR_BASE		0xc0008016
+#define SL_ERROR_LO_PMR_MLE		0xc0008017
+#define SL_ERROR_INITRD_TOO_BIG		0xc0008018
+#define SL_ERROR_HEAP_ZERO_OFFSET	0xc0008019
+#define SL_ERROR_WAKE_BLOCK_TOO_SMALL	0xc000801a
+#define SL_ERROR_MLE_BUFFER_OVERLAP	0xc000801b
+#define SL_ERROR_BUFFER_BEYOND_PMR	0xc000801c
+#define SL_ERROR_OS_SINIT_BAD_VERSION	0xc000801d
+#define SL_ERROR_EVENTLOG_MAP		0xc000801e
+#define SL_ERROR_TPM_NUMBER_ALGS	0xc000801f
+#define SL_ERROR_TPM_UNKNOWN_DIGEST	0xc0008020
+#define SL_ERROR_TPM_INVALID_EVENT	0xc0008021
+#define SL_ERROR_INVALID_SLRT		0xc0008022
+#define SL_ERROR_SLRT_MISSING_ENTRY	0xc0008023
+#define SL_ERROR_SLRT_MAP		0xc0008024
+
+/*
+ * Secure Launch Defined Limits
+ */
+#define TXT_MAX_CPUS		512
+#define TXT_BOOT_STACK_SIZE	24
+
+/*
+ * Secure Launch event log entry type. The TXT specification defines the
+ * base event value as 0x400 for DRTM values.
+ */
+#define TXT_EVTYPE_BASE			0x400
+#define TXT_EVTYPE_SLAUNCH		(TXT_EVTYPE_BASE + 0x102)
+#define TXT_EVTYPE_SLAUNCH_START	(TXT_EVTYPE_BASE + 0x103)
+#define TXT_EVTYPE_SLAUNCH_END		(TXT_EVTYPE_BASE + 0x104)
+
+/*
+ * Measured Launch PCRs
+ */
+#define SL_DEF_DLME_DETAIL_PCR17	17
+#define SL_DEF_DLME_AUTHORITY_PCR18	18
+#define SL_ALT_DLME_AUTHORITY_PCR19	19
+#define SL_ALT_DLME_DETAIL_PCR20	20
+
+/*
+ * MLE scratch area offsets
+ */
+#define SL_SCRATCH_AP_EBX		0
+#define SL_SCRATCH_AP_JMP_OFFSET	4
+#define SL_SCRATCH_AP_PAUSE		8
+
+#ifndef __ASSEMBLY__
+
+#include <linux/io.h>
+#include <linux/tpm.h>
+#include <linux/tpm_eventlog.h>
+
+/*
+ * Secure Launch AP wakeup information fetched in SMP boot code.
+ */
+struct sl_ap_wake_info {
+	u32 ap_wake_block;
+	u32 ap_wake_block_size;
+	u32 ap_jmp_offset;
+};
+
+/*
+ * TXT heap extended data elements.
+ */
+struct txt_heap_ext_data_element {
+	u32 type;
+	u32 size;
+	/* Data */
+} __packed;
+
+#define TXT_HEAP_EXTDATA_TYPE_END			0
+
+struct txt_heap_end_element {
+	u32 type;
+	u32 size;
+} __packed;
+
+#define TXT_HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR		5
+
+struct txt_heap_event_log_element {
+	u64 event_log_phys_addr;
+} __packed;
+
+#define TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1	8
+
+struct txt_heap_event_log_pointer2_1_element {
+	u64 phys_addr;
+	u32 allocated_event_container_size;
+	u32 first_record_offset;
+	u32 next_record_offset;
+} __packed;
+
+/*
+ * Secure Launch defined OS/MLE TXT Heap table
+ */
+struct txt_os_mle_data {
+	u32 version;
+	u32 boot_params_addr;
+	u64 slrt;
+	u64 txt_info;
+	u32 ap_wake_block;
+	u32 ap_wake_block_size;
+	u8 mle_scratch[64];
+} __packed;
+
+/*
+ * TXT specification defined BIOS data TXT Heap table
+ */
+struct txt_bios_data {
+	u32 version; /* Currently 5 for TPM 1.2 and 6 for TPM 2.0 */
+	u32 bios_sinit_size;
+	u64 reserved1;
+	u64 reserved2;
+	u32 num_logical_procs;
+	/* Versions >= 5 with updates in version 6 */
+	u32 sinit_flags;
+	u32 mle_flags;
+	/* Versions >= 4 */
+	/* Ext Data Elements */
+} __packed;
+
+/*
+ * TXT specification defined OS/SINIT TXT Heap table
+ */
+struct txt_os_sinit_data {
+	u32 version; /* Currently 6 for TPM 1.2 and 7 for TPM 2.0 */
+	u32 flags;
+	u64 mle_ptab;
+	u64 mle_size;
+	u64 mle_hdr_base;
+	u64 vtd_pmr_lo_base;
+	u64 vtd_pmr_lo_size;
+	u64 vtd_pmr_hi_base;
+	u64 vtd_pmr_hi_size;
+	u64 lcp_po_base;
+	u64 lcp_po_size;
+	u32 capabilities;
+	/* Version = 5 */
+	u64 efi_rsdt_ptr;
+	/* Versions >= 6 */
+	/* Ext Data Elements */
+} __packed;
+
+/*
+ * TXT specification defined SINIT/MLE TXT Heap table
+ */
+struct txt_sinit_mle_data {
+	u32 version;             /* Current values are 6 through 9 */
+	/* Versions <= 8 */
+	u8 bios_acm_id[20];
+	u32 edx_senter_flags;
+	u64 mseg_valid;
+	u8 sinit_hash[20];
+	u8 mle_hash[20];
+	u8 stm_hash[20];
+	u8 lcp_policy_hash[20];
+	u32 lcp_policy_control;
+	/* Versions >= 7 */
+	u32 rlp_wakeup_addr;
+	u32 reserved;
+	u32 num_of_sinit_mdrs;
+	u32 sinit_mdrs_table_offset;
+	u32 sinit_vtd_dmar_table_size;
+	u32 sinit_vtd_dmar_table_offset;
+	/* Versions >= 8 */
+	u32 processor_scrtm_status;
+	/* Versions >= 9 */
+	/* Ext Data Elements */
+} __packed;
+
+/*
+ * TXT data reporting structure for memory types
+ */
+struct txt_sinit_memory_descriptor_record {
+	u64 address;
+	u64 length;
+	u8 type;
+	u8 reserved[7];
+} __packed;
+
+/*
+ * TXT data structure used by a responsive local processor (RLP) to start
+ * execution in response to a GETSEC[WAKEUP].
+ */
+struct smx_rlp_mle_join {
+	u32 rlp_gdt_limit;
+	u32 rlp_gdt_base;
+	u32 rlp_seg_sel;     /* cs (ds, es, ss are seg_sel+8) */
+	u32 rlp_entry_point; /* phys addr */
+} __packed;
+
+/*
+ * TPM event log structures defined in both the TXT specification and
+ * the TCG documentation.
+ */
+#define TPM12_EVTLOG_SIGNATURE "TXT Event Container"
+
+struct tpm12_event_log_header {
+	char signature[20];
+	char reserved[12];
+	u8 container_ver_major;
+	u8 container_ver_minor;
+	u8 pcr_event_ver_major;
+	u8 pcr_event_ver_minor;
+	u32 container_size;
+	u32 pcr_events_offset;
+	u32 next_event_offset;
+	/* PCREvents[] */
+} __packed;
+
+/*
+ * Functions to extract data from the Intel TXT Heap Memory. The layout
+ * of the heap is as follows:
+ *  +----------------------------+
+ *  | Size Bios Data table (u64) |
+ *  +----------------------------+
+ *  | Bios Data table            |
+ *  +----------------------------+
+ *  | Size OS MLE table (u64)    |
+ *  +----------------------------+
+ *  | OS MLE table               |
+ *  +--------------------------- +
+ *  | Size OS SINIT table (u64)  |
+ *  +----------------------------+
+ *  | OS SINIT table             |
+ *  +----------------------------+
+ *  | Size SINIT MLE table (u64) |
+ *  +----------------------------+
+ *  | SINIT MLE table            |
+ *  +----------------------------+
+ *
+ *  NOTE: the table size fields include the 8 byte size field itself.
+ */
+static inline u64 txt_bios_data_size(void *heap)
+{
+	return *((u64 *)heap);
+}
+
+static inline void *txt_bios_data_start(void *heap)
+{
+	return heap + sizeof(u64);
+}
+
+static inline u64 txt_os_mle_data_size(void *heap)
+{
+	return *((u64 *)(heap + txt_bios_data_size(heap)));
+}
+
+static inline void *txt_os_mle_data_start(void *heap)
+{
+	return heap + txt_bios_data_size(heap) + sizeof(u64);
+}
+
+static inline u64 txt_os_sinit_data_size(void *heap)
+{
+	return *((u64 *)(heap + txt_bios_data_size(heap) +
+			txt_os_mle_data_size(heap)));
+}
+
+static inline void *txt_os_sinit_data_start(void *heap)
+{
+	return heap + txt_bios_data_size(heap) +
+		txt_os_mle_data_size(heap) + sizeof(u64);
+}
+
+static inline u64 txt_sinit_mle_data_size(void *heap)
+{
+	return *((u64 *)(heap + txt_bios_data_size(heap) +
+			txt_os_mle_data_size(heap) +
+			txt_os_sinit_data_size(heap)));
+}
+
+static inline void *txt_sinit_mle_data_start(void *heap)
+{
+	return heap + txt_bios_data_size(heap) +
+		txt_os_mle_data_size(heap) +
+		txt_os_sinit_data_size(heap) + sizeof(u64);
+}
+
+/*
+ * TPM event logging functions.
+ */
+static inline struct txt_heap_event_log_pointer2_1_element*
+tpm20_find_log2_1_element(struct txt_os_sinit_data *os_sinit_data)
+{
+	struct txt_heap_ext_data_element *ext_elem;
+
+	/* The extended element array as at the end of this table */
+	ext_elem = (struct txt_heap_ext_data_element *)
+		((u8 *)os_sinit_data + sizeof(struct txt_os_sinit_data));
+
+	while (ext_elem->type != TXT_HEAP_EXTDATA_TYPE_END) {
+		if (ext_elem->type ==
+		    TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1) {
+			return (struct txt_heap_event_log_pointer2_1_element *)
+				((u8 *)ext_elem +
+					sizeof(struct txt_heap_ext_data_element));
+		}
+		ext_elem =
+			(struct txt_heap_ext_data_element *)
+			((u8 *)ext_elem + ext_elem->size);
+	}
+
+	return NULL;
+}
+
+static inline int tpm12_log_event(void *evtlog_base, u32 evtlog_size,
+				  u32 event_size, void *event)
+{
+	struct tpm12_event_log_header *evtlog =
+		(struct tpm12_event_log_header *)evtlog_base;
+
+	if (memcmp(evtlog->signature, TPM12_EVTLOG_SIGNATURE,
+		   sizeof(TPM12_EVTLOG_SIGNATURE)))
+		return -EINVAL;
+
+	if (evtlog->container_size > evtlog_size)
+		return -EINVAL;
+
+	if (evtlog->next_event_offset + event_size > evtlog->container_size)
+		return -E2BIG;
+
+	memcpy(evtlog_base + evtlog->next_event_offset, event, event_size);
+	evtlog->next_event_offset += event_size;
+
+	return 0;
+}
+
+static inline int tpm20_log_event(struct txt_heap_event_log_pointer2_1_element *elem,
+				  void *evtlog_base, u32 evtlog_size,
+				  u32 event_size, void *event)
+{
+	struct tcg_pcr_event *header =
+		(struct tcg_pcr_event *)evtlog_base;
+
+	/* Has to be at least big enough for the signature */
+	if (header->event_size < sizeof(TCG_SPECID_SIG))
+		return -EINVAL;
+
+	if (memcmp((u8 *)header + sizeof(struct tcg_pcr_event),
+		   TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
+		return -EINVAL;
+
+	if (elem->allocated_event_container_size > evtlog_size)
+		return -EINVAL;
+
+	if (elem->next_record_offset + event_size >
+	    elem->allocated_event_container_size)
+		return -E2BIG;
+
+	memcpy(evtlog_base + elem->next_record_offset, event, event_size);
+	elem->next_record_offset += event_size;
+
+	return 0;
+}
+
+/*
+ * External functions avalailable in mainline kernel.
+ */
+extern void slaunch_setup_txt(void);
+extern u32 slaunch_get_flags(void);
+extern struct sl_ap_wake_info *slaunch_get_ap_wake_info(void);
+extern struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar);
+extern void __noreturn slaunch_txt_reset(void __iomem *txt,
+					 const char *msg, u64 error);
+extern void slaunch_finalize(int do_sexit);
+
+#endif /* !__ASSEMBLY */
+
+#else
+
+#define slaunch_setup_txt()		do { } while (0)
+#define slaunch_get_flags()		0
+#define slaunch_get_dmar_table(d)	(d)
+#define slaunch_finalize(d)		do { } while (0)
+
+#endif /* !IS_ENABLED(CONFIG_SECURE_LAUNCH) */
+
+#endif /* _LINUX_SLAUNCH_H */
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

From: "Daniel P. Smith" <dpsmith@apertussolutions.com>

The SHA algorithms are necessary to measure configuration information into
the TPM as early as possible before using the values. This implementation
uses the established approach of #including the SHA libraries directly in
the code since the compressed kernel is not uncompressed at this point.

The SHA code here has its origins in the code from the main kernel:

commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")

That code could not be pulled directly into the setup portion of the
compressed kernel because of other dependencies it pulls in. The result
is this is a modified copy of that code that still leverages the core
SHA algorithms.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/boot/compressed/Makefile       |  2 +
 arch/x86/boot/compressed/early_sha1.c   | 97 +++++++++++++++++++++++++++++++++
 arch/x86/boot/compressed/early_sha1.h   | 17 ++++++
 arch/x86/boot/compressed/early_sha256.c |  7 +++
 lib/crypto/sha1.c                       |  4 ++
 lib/crypto/sha256.c                     |  8 +++
 6 files changed, 135 insertions(+)
 create mode 100644 arch/x86/boot/compressed/early_sha1.c
 create mode 100644 arch/x86/boot/compressed/early_sha1.h
 create mode 100644 arch/x86/boot/compressed/early_sha256.c

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 6b6cfe6..1d327d4 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -112,6 +112,8 @@ vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
 vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
 vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
 
+vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/early_sha1.o $(obj)/early_sha256.o
+
 $(obj)/vmlinux: $(vmlinux-objs-y) FORCE
 	$(call if_changed,ld)
 
diff --git a/arch/x86/boot/compressed/early_sha1.c b/arch/x86/boot/compressed/early_sha1.c
new file mode 100644
index 0000000..524ec23
--- /dev/null
+++ b/arch/x86/boot/compressed/early_sha1.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Apertus Solutions, LLC.
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/string.h>
+#include <asm/boot.h>
+#include <asm/unaligned.h>
+
+#include "early_sha1.h"
+
+#define SHA1_DISABLE_EXPORT
+#include "../../../../lib/crypto/sha1.c"
+
+/* The SHA1 implementation in lib/sha1.c was written to get the workspace
+ * buffer as a parameter. This wrapper function provides a container
+ * around a temporary workspace that is cleared after the transform completes.
+ */
+static void __sha_transform(u32 *digest, const char *data)
+{
+	u32 ws[SHA1_WORKSPACE_WORDS];
+
+	sha1_transform(digest, data, ws);
+
+	memzero_explicit(ws, sizeof(ws));
+}
+
+void early_sha1_init(struct sha1_state *sctx)
+{
+	sha1_init(sctx->state);
+	sctx->count = 0;
+}
+
+void early_sha1_update(struct sha1_state *sctx,
+		       const u8 *data,
+		       unsigned int len)
+{
+	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+
+	sctx->count += len;
+
+	if (likely((partial + len) >= SHA1_BLOCK_SIZE)) {
+		int blocks;
+
+		if (partial) {
+			int p = SHA1_BLOCK_SIZE - partial;
+
+			memcpy(sctx->buffer + partial, data, p);
+			data += p;
+			len -= p;
+
+			__sha_transform(sctx->state, sctx->buffer);
+		}
+
+		blocks = len / SHA1_BLOCK_SIZE;
+		len %= SHA1_BLOCK_SIZE;
+
+		if (blocks) {
+			while (blocks--) {
+				__sha_transform(sctx->state, data);
+				data += SHA1_BLOCK_SIZE;
+			}
+		}
+		partial = 0;
+	}
+
+	if (len)
+		memcpy(sctx->buffer + partial, data, len);
+}
+
+void early_sha1_final(struct sha1_state *sctx, u8 *out)
+{
+	const int bit_offset = SHA1_BLOCK_SIZE - sizeof(__be64);
+	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+	__be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
+	__be32 *digest = (__be32 *)out;
+	int i;
+
+	sctx->buffer[partial++] = 0x80;
+	if (partial > bit_offset) {
+		memset(sctx->buffer + partial, 0x0, SHA1_BLOCK_SIZE - partial);
+		partial = 0;
+
+		__sha_transform(sctx->state, sctx->buffer);
+	}
+
+	memset(sctx->buffer + partial, 0x0, bit_offset - partial);
+	*bits = cpu_to_be64(sctx->count << 3);
+	__sha_transform(sctx->state, sctx->buffer);
+
+	for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
+		put_unaligned_be32(sctx->state[i], digest++);
+
+	*sctx = (struct sha1_state){};
+}
diff --git a/arch/x86/boot/compressed/early_sha1.h b/arch/x86/boot/compressed/early_sha1.h
new file mode 100644
index 0000000..adcc4a9
--- /dev/null
+++ b/arch/x86/boot/compressed/early_sha1.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2022 Apertus Solutions, LLC
+ */
+
+#ifndef BOOT_COMPRESSED_EARLY_SHA1_H
+#define BOOT_COMPRESSED_EARLY_SHA1_H
+
+#include <crypto/sha1.h>
+
+void early_sha1_init(struct sha1_state *sctx);
+void early_sha1_update(struct sha1_state *sctx,
+		       const u8 *data,
+		       unsigned int len);
+void early_sha1_final(struct sha1_state *sctx, u8 *out);
+
+#endif /* BOOT_COMPRESSED_EARLY_SHA1_H */
diff --git a/arch/x86/boot/compressed/early_sha256.c b/arch/x86/boot/compressed/early_sha256.c
new file mode 100644
index 0000000..28a8e32
--- /dev/null
+++ b/arch/x86/boot/compressed/early_sha256.c
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Apertus Solutions, LLC
+ */
+
+#define SHA256_DISABLE_EXPORT
+#include "../../../../lib/crypto/sha256.c"
diff --git a/lib/crypto/sha1.c b/lib/crypto/sha1.c
index 1aebe7b..771ff90 100644
--- a/lib/crypto/sha1.c
+++ b/lib/crypto/sha1.c
@@ -121,7 +121,9 @@ void sha1_transform(__u32 *digest, const char *data, __u32 *array)
 	digest[3] += D;
 	digest[4] += E;
 }
+#ifndef SHA1_DISABLE_EXPORT
 EXPORT_SYMBOL(sha1_transform);
+#endif
 
 /**
  * sha1_init - initialize the vectors for a SHA1 digest
@@ -135,6 +137,8 @@ void sha1_init(__u32 *buf)
 	buf[3] = 0x10325476;
 	buf[4] = 0xc3d2e1f0;
 }
+#ifndef SHA1_DISABLE_EXPORT
 EXPORT_SYMBOL(sha1_init);
+#endif
 
 MODULE_LICENSE("GPL");
diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
index 72a4b0b..e532220 100644
--- a/lib/crypto/sha256.c
+++ b/lib/crypto/sha256.c
@@ -149,13 +149,17 @@ void sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len)
 	}
 	memcpy(sctx->buf + partial, src, len - done);
 }
+#ifndef SHA256_DISABLE_EXPORT
 EXPORT_SYMBOL(sha256_update);
+#endif
 
 void sha224_update(struct sha256_state *sctx, const u8 *data, unsigned int len)
 {
 	sha256_update(sctx, data, len);
 }
+#ifndef SHA256_DISABLE_EXPORT
 EXPORT_SYMBOL(sha224_update);
+#endif
 
 static void __sha256_final(struct sha256_state *sctx, u8 *out, int digest_words)
 {
@@ -188,13 +192,17 @@ void sha256_final(struct sha256_state *sctx, u8 *out)
 {
 	__sha256_final(sctx, out, 8);
 }
+#ifndef SHA256_DISABLE_EXPORT
 EXPORT_SYMBOL(sha256_final);
+#endif
 
 void sha224_final(struct sha256_state *sctx, u8 *out)
 {
 	__sha256_final(sctx, out, 7);
 }
+#ifndef SHA256_DISABLE_EXPORT
 EXPORT_SYMBOL(sha224_final);
+#endif
 
 void sha256(const u8 *data, unsigned int len, u8 *out)
 {
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

From: "Daniel P. Smith" <dpsmith@apertussolutions.com>

The SHA algorithms are necessary to measure configuration information into
the TPM as early as possible before using the values. This implementation
uses the established approach of #including the SHA libraries directly in
the code since the compressed kernel is not uncompressed at this point.

The SHA code here has its origins in the code from the main kernel:

commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")

That code could not be pulled directly into the setup portion of the
compressed kernel because of other dependencies it pulls in. The result
is this is a modified copy of that code that still leverages the core
SHA algorithms.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/boot/compressed/Makefile       |  2 +
 arch/x86/boot/compressed/early_sha1.c   | 97 +++++++++++++++++++++++++++++++++
 arch/x86/boot/compressed/early_sha1.h   | 17 ++++++
 arch/x86/boot/compressed/early_sha256.c |  7 +++
 lib/crypto/sha1.c                       |  4 ++
 lib/crypto/sha256.c                     |  8 +++
 6 files changed, 135 insertions(+)
 create mode 100644 arch/x86/boot/compressed/early_sha1.c
 create mode 100644 arch/x86/boot/compressed/early_sha1.h
 create mode 100644 arch/x86/boot/compressed/early_sha256.c

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 6b6cfe6..1d327d4 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -112,6 +112,8 @@ vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
 vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
 vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
 
+vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/early_sha1.o $(obj)/early_sha256.o
+
 $(obj)/vmlinux: $(vmlinux-objs-y) FORCE
 	$(call if_changed,ld)
 
diff --git a/arch/x86/boot/compressed/early_sha1.c b/arch/x86/boot/compressed/early_sha1.c
new file mode 100644
index 0000000..524ec23
--- /dev/null
+++ b/arch/x86/boot/compressed/early_sha1.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Apertus Solutions, LLC.
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/string.h>
+#include <asm/boot.h>
+#include <asm/unaligned.h>
+
+#include "early_sha1.h"
+
+#define SHA1_DISABLE_EXPORT
+#include "../../../../lib/crypto/sha1.c"
+
+/* The SHA1 implementation in lib/sha1.c was written to get the workspace
+ * buffer as a parameter. This wrapper function provides a container
+ * around a temporary workspace that is cleared after the transform completes.
+ */
+static void __sha_transform(u32 *digest, const char *data)
+{
+	u32 ws[SHA1_WORKSPACE_WORDS];
+
+	sha1_transform(digest, data, ws);
+
+	memzero_explicit(ws, sizeof(ws));
+}
+
+void early_sha1_init(struct sha1_state *sctx)
+{
+	sha1_init(sctx->state);
+	sctx->count = 0;
+}
+
+void early_sha1_update(struct sha1_state *sctx,
+		       const u8 *data,
+		       unsigned int len)
+{
+	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+
+	sctx->count += len;
+
+	if (likely((partial + len) >= SHA1_BLOCK_SIZE)) {
+		int blocks;
+
+		if (partial) {
+			int p = SHA1_BLOCK_SIZE - partial;
+
+			memcpy(sctx->buffer + partial, data, p);
+			data += p;
+			len -= p;
+
+			__sha_transform(sctx->state, sctx->buffer);
+		}
+
+		blocks = len / SHA1_BLOCK_SIZE;
+		len %= SHA1_BLOCK_SIZE;
+
+		if (blocks) {
+			while (blocks--) {
+				__sha_transform(sctx->state, data);
+				data += SHA1_BLOCK_SIZE;
+			}
+		}
+		partial = 0;
+	}
+
+	if (len)
+		memcpy(sctx->buffer + partial, data, len);
+}
+
+void early_sha1_final(struct sha1_state *sctx, u8 *out)
+{
+	const int bit_offset = SHA1_BLOCK_SIZE - sizeof(__be64);
+	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+	__be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
+	__be32 *digest = (__be32 *)out;
+	int i;
+
+	sctx->buffer[partial++] = 0x80;
+	if (partial > bit_offset) {
+		memset(sctx->buffer + partial, 0x0, SHA1_BLOCK_SIZE - partial);
+		partial = 0;
+
+		__sha_transform(sctx->state, sctx->buffer);
+	}
+
+	memset(sctx->buffer + partial, 0x0, bit_offset - partial);
+	*bits = cpu_to_be64(sctx->count << 3);
+	__sha_transform(sctx->state, sctx->buffer);
+
+	for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
+		put_unaligned_be32(sctx->state[i], digest++);
+
+	*sctx = (struct sha1_state){};
+}
diff --git a/arch/x86/boot/compressed/early_sha1.h b/arch/x86/boot/compressed/early_sha1.h
new file mode 100644
index 0000000..adcc4a9
--- /dev/null
+++ b/arch/x86/boot/compressed/early_sha1.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2022 Apertus Solutions, LLC
+ */
+
+#ifndef BOOT_COMPRESSED_EARLY_SHA1_H
+#define BOOT_COMPRESSED_EARLY_SHA1_H
+
+#include <crypto/sha1.h>
+
+void early_sha1_init(struct sha1_state *sctx);
+void early_sha1_update(struct sha1_state *sctx,
+		       const u8 *data,
+		       unsigned int len);
+void early_sha1_final(struct sha1_state *sctx, u8 *out);
+
+#endif /* BOOT_COMPRESSED_EARLY_SHA1_H */
diff --git a/arch/x86/boot/compressed/early_sha256.c b/arch/x86/boot/compressed/early_sha256.c
new file mode 100644
index 0000000..28a8e32
--- /dev/null
+++ b/arch/x86/boot/compressed/early_sha256.c
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Apertus Solutions, LLC
+ */
+
+#define SHA256_DISABLE_EXPORT
+#include "../../../../lib/crypto/sha256.c"
diff --git a/lib/crypto/sha1.c b/lib/crypto/sha1.c
index 1aebe7b..771ff90 100644
--- a/lib/crypto/sha1.c
+++ b/lib/crypto/sha1.c
@@ -121,7 +121,9 @@ void sha1_transform(__u32 *digest, const char *data, __u32 *array)
 	digest[3] += D;
 	digest[4] += E;
 }
+#ifndef SHA1_DISABLE_EXPORT
 EXPORT_SYMBOL(sha1_transform);
+#endif
 
 /**
  * sha1_init - initialize the vectors for a SHA1 digest
@@ -135,6 +137,8 @@ void sha1_init(__u32 *buf)
 	buf[3] = 0x10325476;
 	buf[4] = 0xc3d2e1f0;
 }
+#ifndef SHA1_DISABLE_EXPORT
 EXPORT_SYMBOL(sha1_init);
+#endif
 
 MODULE_LICENSE("GPL");
diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
index 72a4b0b..e532220 100644
--- a/lib/crypto/sha256.c
+++ b/lib/crypto/sha256.c
@@ -149,13 +149,17 @@ void sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len)
 	}
 	memcpy(sctx->buf + partial, src, len - done);
 }
+#ifndef SHA256_DISABLE_EXPORT
 EXPORT_SYMBOL(sha256_update);
+#endif
 
 void sha224_update(struct sha256_state *sctx, const u8 *data, unsigned int len)
 {
 	sha256_update(sctx, data, len);
 }
+#ifndef SHA256_DISABLE_EXPORT
 EXPORT_SYMBOL(sha224_update);
+#endif
 
 static void __sha256_final(struct sha256_state *sctx, u8 *out, int digest_words)
 {
@@ -188,13 +192,17 @@ void sha256_final(struct sha256_state *sctx, u8 *out)
 {
 	__sha256_final(sctx, out, 8);
 }
+#ifndef SHA256_DISABLE_EXPORT
 EXPORT_SYMBOL(sha256_final);
+#endif
 
 void sha224_final(struct sha256_state *sctx, u8 *out)
 {
 	__sha256_final(sctx, out, 7);
 }
+#ifndef SHA256_DISABLE_EXPORT
 EXPORT_SYMBOL(sha224_final);
+#endif
 
 void sha256(const u8 *data, unsigned int len, u8 *out)
 {
-- 
1.8.3.1


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

* [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

The Secure Launch (SL) stub provides the entry point for Intel TXT (and
later AMD SKINIT) to vector to during the late launch. The symbol
sl_stub_entry is that entry point and its offset into the kernel is
conveyed to the launching code using the MLE (Measured Launch
Environment) header in the structure named mle_header. The offset of the
MLE header is set in the kernel_info. The routine sl_stub contains the
very early late launch setup code responsible for setting up the basic
environment to allow the normal kernel startup_32 code to proceed. It is
also responsible for properly waking and handling the APs on Intel
platforms. The routine sl_main which runs after entering 64b mode is
responsible for measuring configuration and module information before
it is used like the boot params, the kernel command line, the TXT heap,
an external initramfs, etc.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 Documentation/arch/x86/boot.rst        |  21 +
 arch/x86/boot/compressed/Makefile      |   3 +-
 arch/x86/boot/compressed/head_64.S     |  37 ++
 arch/x86/boot/compressed/kernel_info.S |  34 ++
 arch/x86/boot/compressed/sl_main.c     | 599 ++++++++++++++++++++++++++++
 arch/x86/boot/compressed/sl_stub.S     | 690 +++++++++++++++++++++++++++++++++
 arch/x86/include/uapi/asm/bootparam.h  |   1 +
 arch/x86/kernel/asm-offsets.c          |  20 +
 8 files changed, 1404 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/boot/compressed/sl_main.c
 create mode 100644 arch/x86/boot/compressed/sl_stub.S

diff --git a/Documentation/arch/x86/boot.rst b/Documentation/arch/x86/boot.rst
index 33520ec..90552f7 100644
--- a/Documentation/arch/x86/boot.rst
+++ b/Documentation/arch/x86/boot.rst
@@ -482,6 +482,14 @@ Protocol:	2.00+
 	    - If 1, KASLR enabled.
 	    - If 0, KASLR disabled.
 
+  Bit 2 (kernel internal): SLAUNCH_FLAG
+
+	- Used internally by the compressed kernel to communicate
+	  Secure Launch status to kernel proper.
+
+	    - If 1, Secure Launch enabled.
+	    - If 0, Secure Launch disabled.
+
   Bit 5 (write): QUIET_FLAG
 
 	- If 0, print early messages.
@@ -1027,6 +1035,19 @@ Offset/size:	0x000c/4
 
   This field contains maximal allowed type for setup_data and setup_indirect structs.
 
+============	=================
+Field name:	mle_header_offset
+Offset/size:	0x0010/4
+============	=================
+
+  This field contains the offset to the Secure Launch Measured Launch Environment
+  (MLE) header. This offset is used to locate information needed during a secure
+  late launch using Intel TXT. If the offset is zero, the kernel does not have
+  Secure Launch capabilities. The MLE entry point is called from TXT on the BSP
+  following a success measured launch. The specific state of the processors is
+  outlined in the TXT Software Development Guide, the latest can be found here:
+  https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
+
 
 The Image Checksum
 ==================
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 1d327d4..7f31473 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -112,7 +112,8 @@ vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
 vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
 vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
 
-vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/early_sha1.o $(obj)/early_sha256.o
+vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/early_sha1.o $(obj)/early_sha256.o \
+	$(obj)/sl_main.o $(obj)/sl_stub.o
 
 $(obj)/vmlinux: $(vmlinux-objs-y) FORCE
 	$(call if_changed,ld)
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 03c4328..d079d8d 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -492,6 +492,17 @@ trampoline_return:
 	pushq	$0
 	popfq
 
+#ifdef CONFIG_SECURE_LAUNCH
+	pushq	%rsi
+
+	/* Ensure the relocation region coverd by a PMR */
+	movq	%rbx, %rdi
+	movl	$(_bss - startup_32), %esi
+	callq	sl_check_region
+
+	popq	%rsi
+#endif
+
 /*
  * Copy the compressed kernel to the end of our buffer
  * where decompression in place becomes safe.
@@ -551,6 +562,32 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
 	shrq	$3, %rcx
 	rep	stosq
 
+#ifdef CONFIG_SECURE_LAUNCH
+	/*
+	 * Have to do the final early sl stub work in 64b area.
+	 *
+	 * *********** NOTE ***********
+	 *
+	 * Several boot params get used before we get a chance to measure
+	 * them in this call. This is a known issue and we currently don't
+	 * have a solution. The scratch field doesn't matter. There is no
+	 * obvious way to do anything about the use of kernel_alignment or
+	 * init_size though these seem low risk with all the PMR and overlap
+	 * checks in place.
+	 */
+	pushq	%rsi
+
+	movq	%rsi, %rdi
+	callq	sl_main
+
+	/* Ensure the decompression location is coverd by a PMR */
+	movq	%rbp, %rdi
+	movq	output_len(%rip), %rsi
+	callq	sl_check_region
+
+	popq	%rsi
+#endif
+
 	pushq	%rsi
 	call	load_stage2_idt
 
diff --git a/arch/x86/boot/compressed/kernel_info.S b/arch/x86/boot/compressed/kernel_info.S
index c18f071..e199b87 100644
--- a/arch/x86/boot/compressed/kernel_info.S
+++ b/arch/x86/boot/compressed/kernel_info.S
@@ -28,6 +28,40 @@ SYM_DATA_START(kernel_info)
 	/* Maximal allowed type for setup_data and setup_indirect structs. */
 	.long	SETUP_TYPE_MAX
 
+	/* Offset to the MLE header structure */
+#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
+	.long	rva(mle_header)
+#else
+	.long	0
+#endif
+
 kernel_info_var_len_data:
 	/* Empty for time being... */
 SYM_DATA_END_LABEL(kernel_info, SYM_L_LOCAL, kernel_info_end)
+
+#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
+	/*
+	 * The MLE Header per the TXT Specification, section 2.1
+	 * MLE capabilities, see table 4. Capabilities set:
+	 * bit 0: Support for GETSEC[WAKEUP] for RLP wakeup
+	 * bit 1: Support for RLP wakeup using MONITOR address
+	 * bit 2: The ECX register will contain the pointer to the MLE page table
+	 * bit 5: TPM 1.2 family: Details/authorities PCR usage support
+	 * bit 9: Supported format of TPM 2.0 event log - TCG compliant
+	 */
+SYM_DATA_START(mle_header)
+	.long	0x9082ac5a  /* UUID0 */
+	.long	0x74a7476f  /* UUID1 */
+	.long	0xa2555c0f  /* UUID2 */
+	.long	0x42b651cb  /* UUID3 */
+	.long	0x00000034  /* MLE header size */
+	.long	0x00020002  /* MLE version 2.2 */
+	.long	rva(sl_stub_entry) /* Linear entry point of MLE (virt. address) */
+	.long	0x00000000  /* First valid page of MLE */
+	.long	0x00000000  /* Offset within binary of first byte of MLE */
+	.long	rva(_edata) /* Offset within binary of last byte + 1 of MLE */
+	.long	0x00000227  /* Bit vector of MLE-supported capabilities */
+	.long	0x00000000  /* Starting linear address of command line (unused) */
+	.long	0x00000000  /* Ending linear address of command line (unused) */
+SYM_DATA_END(mle_header)
+#endif
diff --git a/arch/x86/boot/compressed/sl_main.c b/arch/x86/boot/compressed/sl_main.c
new file mode 100644
index 0000000..23d7722
--- /dev/null
+++ b/arch/x86/boot/compressed/sl_main.c
@@ -0,0 +1,599 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Secure Launch early measurement and validation routines.
+ *
+ * Copyright (c) 2022, Oracle and/or its affiliates.
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/boot.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/processor-flags.h>
+#include <asm/asm-offsets.h>
+#include <asm/bootparam.h>
+#include <asm/bootparam_utils.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
+#include <crypto/sha1.h>
+#include <crypto/sha2.h>
+
+#include "early_sha1.h"
+
+#define CAPS_VARIABLE_MTRR_COUNT_MASK	0xff
+
+#define SL_TPM12_LOG		1
+#define SL_TPM20_LOG		2
+
+#define SL_TPM20_MAX_ALGS	2
+
+#define SL_MAX_EVENT_DATA	64
+#define SL_TPM12_LOG_SIZE	(sizeof(struct tcg_pcr_event) + \
+				SL_MAX_EVENT_DATA)
+#define SL_TPM20_LOG_SIZE	(sizeof(struct tcg_pcr_event2_head) + \
+				SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + \
+				sizeof(struct tcg_event_field) + \
+				SL_MAX_EVENT_DATA)
+
+static void *evtlog_base;
+static u32 evtlog_size;
+static struct txt_heap_event_log_pointer2_1_element *log20_elem;
+static u32 tpm_log_ver = SL_TPM12_LOG;
+struct tcg_efi_specid_event_algs tpm_algs[SL_TPM20_MAX_ALGS] = {0};
+
+extern u32 sl_cpu_type;
+extern u32 sl_mle_start;
+extern struct boot_params *boot_params;
+
+static u64 sl_txt_read(u32 reg)
+{
+	return readq((void *)(u64)(TXT_PRIV_CONFIG_REGS_BASE + reg));
+}
+
+static void sl_txt_write(u32 reg, u64 val)
+{
+	writeq(val, (void *)(u64)(TXT_PRIV_CONFIG_REGS_BASE + reg));
+}
+
+static void __noreturn sl_txt_reset(u64 error)
+{
+	/* Reading the E2STS register acts as a barrier for TXT registers */
+	sl_txt_write(TXT_CR_ERRORCODE, error);
+	sl_txt_read(TXT_CR_E2STS);
+	sl_txt_write(TXT_CR_CMD_UNLOCK_MEM_CONFIG, 1);
+	sl_txt_read(TXT_CR_E2STS);
+	sl_txt_write(TXT_CR_CMD_RESET, 1);
+
+	for ( ; ; )
+		asm volatile ("hlt");
+
+	unreachable();
+}
+
+static u64 sl_rdmsr(u32 reg)
+{
+	u64 lo, hi;
+
+	asm volatile ("rdmsr" : "=a" (lo), "=d" (hi) : "c" (reg));
+
+	return (hi << 32) | lo;
+}
+
+static struct slr_table *sl_locate_and_validate_slrt(void)
+{
+	struct txt_os_mle_data *os_mle_data;
+	struct slr_table *slrt;
+	void *txt_heap;
+
+	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+	os_mle_data = txt_os_mle_data_start(txt_heap);
+
+	if (!os_mle_data->slrt)
+		sl_txt_reset(SL_ERROR_INVALID_SLRT);
+
+	slrt = (struct slr_table *)os_mle_data->slrt;
+
+	if (slrt->magic != SLR_TABLE_MAGIC)
+		sl_txt_reset(SL_ERROR_INVALID_SLRT);
+
+	if (slrt->architecture != SLR_INTEL_TXT)
+		sl_txt_reset(SL_ERROR_INVALID_SLRT);
+
+	return slrt;
+}
+
+static void sl_check_pmr_coverage(void *base, u32 size, bool allow_hi)
+{
+	struct txt_os_sinit_data *os_sinit_data;
+	void *end = base + size;
+	void *txt_heap;
+
+	if (!(sl_cpu_type & SL_CPU_INTEL))
+		return;
+
+	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+	os_sinit_data = txt_os_sinit_data_start(txt_heap);
+
+	if ((end >= (void *)0x100000000ULL) &&
+	    (base < (void *)0x100000000ULL))
+		sl_txt_reset(SL_ERROR_REGION_STRADDLE_4GB);
+
+	/*
+	 * Note that the late stub code validates that the hi PMR covers
+	 * all memory above 4G. At this point the code can only check that
+	 * regions are within the hi PMR but that is sufficient.
+	 */
+	if ((end > (void *)0x100000000ULL) &&
+	    (base >= (void *)0x100000000ULL)) {
+		if (allow_hi) {
+			if (end >= (void *)(os_sinit_data->vtd_pmr_hi_base +
+					   os_sinit_data->vtd_pmr_hi_size))
+				sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
+		} else
+			sl_txt_reset(SL_ERROR_REGION_ABOVE_4GB);
+	}
+
+	if (end >= (void *)os_sinit_data->vtd_pmr_lo_size)
+		sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
+}
+
+/*
+ * Some MSRs are modified by the pre-launch code including the MTRRs.
+ * The early MLE code has to restore these values. This code validates
+ * the values after they are measured.
+ */
+static void sl_txt_validate_msrs(struct txt_os_mle_data *os_mle_data)
+{
+	struct slr_txt_mtrr_state *saved_bsp_mtrrs;
+	u64 mtrr_caps, mtrr_def_type, mtrr_var;
+	struct slr_entry_intel_info *txt_info;
+	u64 misc_en_msr;
+	u32 vcnt, i;
+
+	txt_info = (struct slr_entry_intel_info *)os_mle_data->txt_info;
+	saved_bsp_mtrrs = &(txt_info->saved_bsp_mtrrs);
+
+	mtrr_caps = sl_rdmsr(MSR_MTRRcap);
+	vcnt = (u32)(mtrr_caps & CAPS_VARIABLE_MTRR_COUNT_MASK);
+
+	if (saved_bsp_mtrrs->mtrr_vcnt > vcnt)
+		sl_txt_reset(SL_ERROR_MTRR_INV_VCNT);
+	if (saved_bsp_mtrrs->mtrr_vcnt > TXT_OS_MLE_MAX_VARIABLE_MTRRS)
+		sl_txt_reset(SL_ERROR_MTRR_INV_VCNT);
+
+	mtrr_def_type = sl_rdmsr(MSR_MTRRdefType);
+	if (saved_bsp_mtrrs->default_mem_type != mtrr_def_type)
+		sl_txt_reset(SL_ERROR_MTRR_INV_DEF_TYPE);
+
+	for (i = 0; i < saved_bsp_mtrrs->mtrr_vcnt; i++) {
+		mtrr_var = sl_rdmsr(MTRRphysBase_MSR(i));
+		if (saved_bsp_mtrrs->mtrr_pair[i].mtrr_physbase != mtrr_var)
+			sl_txt_reset(SL_ERROR_MTRR_INV_BASE);
+		mtrr_var = sl_rdmsr(MTRRphysMask_MSR(i));
+		if (saved_bsp_mtrrs->mtrr_pair[i].mtrr_physmask != mtrr_var)
+			sl_txt_reset(SL_ERROR_MTRR_INV_MASK);
+	}
+
+	misc_en_msr = sl_rdmsr(MSR_IA32_MISC_ENABLE);
+	if (txt_info->saved_misc_enable_msr != misc_en_msr)
+		sl_txt_reset(SL_ERROR_MSR_INV_MISC_EN);
+}
+
+static void sl_find_event_log(struct slr_table *slrt)
+{
+	struct txt_os_sinit_data *os_sinit_data;
+	struct slr_entry_log_info *log_info;
+	void *txt_heap;
+
+	log_info = (struct slr_entry_log_info *)
+			slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
+	if (!log_info)
+		sl_txt_reset(SL_ERROR_SLRT_MISSING_ENTRY);
+
+	evtlog_base = (void *)log_info->addr;
+	evtlog_size = log_info->size;
+
+	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+
+	/*
+	 * For TPM 2.0, the event log 2.1 extended data structure has to also
+	 * be located and fixed up.
+	 */
+	os_sinit_data = txt_os_sinit_data_start(txt_heap);
+
+	/*
+	 * Only support version 6 and later that properly handle the
+	 * list of ExtDataElements in the OS-SINIT structure.
+	 */
+	if (os_sinit_data->version < 6)
+		sl_txt_reset(SL_ERROR_OS_SINIT_BAD_VERSION);
+
+	/* Find the TPM2.0 logging extended heap element */
+	log20_elem = tpm20_find_log2_1_element(os_sinit_data);
+
+	/* If found, this implies TPM20 log and family */
+	if (log20_elem)
+		tpm_log_ver = SL_TPM20_LOG;
+}
+
+static void sl_validate_event_log_buffer(void)
+{
+	struct txt_os_sinit_data *os_sinit_data;
+	void *txt_heap, *txt_end;
+	void *mle_base, *mle_end;
+	void *evtlog_end;
+
+	if ((u64)evtlog_size > (LLONG_MAX - (u64)evtlog_base))
+		sl_txt_reset(SL_ERROR_INTEGER_OVERFLOW);
+	evtlog_end = evtlog_base + evtlog_size;
+
+	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+	txt_end = txt_heap + sl_txt_read(TXT_CR_HEAP_SIZE);
+	os_sinit_data = txt_os_sinit_data_start(txt_heap);
+
+	mle_base = (void *)(u64)sl_mle_start;
+	mle_end = mle_base + os_sinit_data->mle_size;
+
+	/*
+	 * This check is to ensure the event log buffer does not overlap with
+	 * the MLE image.
+	 */
+	if ((evtlog_base >= mle_end) &&
+	    (evtlog_end > mle_end))
+		goto pmr_check; /* above */
+
+	if ((evtlog_end <= mle_base) &&
+	    (evtlog_base < mle_base))
+		goto pmr_check; /* below */
+
+	sl_txt_reset(SL_ERROR_MLE_BUFFER_OVERLAP);
+
+pmr_check:
+	/*
+	 * The TXT heap is protected by the DPR. If the TPM event log is
+	 * inside the TXT heap, there is no need for a PMR check.
+	 */
+	if ((evtlog_base > txt_heap) &&
+	    (evtlog_end < txt_end))
+		return;
+
+	sl_check_pmr_coverage(evtlog_base, evtlog_size, true);
+}
+
+static void sl_find_event_log_algorithms(void)
+{
+	struct tcg_efi_specid_event_head *efi_head =
+		(struct tcg_efi_specid_event_head *)(evtlog_base +
+					log20_elem->first_record_offset +
+					sizeof(struct tcg_pcr_event));
+
+	if (efi_head->num_algs == 0 || efi_head->num_algs > 2)
+		sl_txt_reset(SL_ERROR_TPM_NUMBER_ALGS);
+
+	memcpy(&tpm_algs[0], &efi_head->digest_sizes[0],
+	       sizeof(struct tcg_efi_specid_event_algs) * efi_head->num_algs);
+}
+
+static void sl_tpm12_log_event(u32 pcr, u32 event_type,
+			       const u8 *data, u32 length,
+			       const u8 *event_data, u32 event_size)
+{
+	u8 sha1_hash[SHA1_DIGEST_SIZE] = {0};
+	u8 log_buf[SL_TPM12_LOG_SIZE] = {0};
+	struct tcg_pcr_event *pcr_event;
+	struct sha1_state sctx = {0};
+	u32 total_size;
+
+	pcr_event = (struct tcg_pcr_event *)log_buf;
+	pcr_event->pcr_idx = pcr;
+	pcr_event->event_type = event_type;
+	if (length > 0) {
+		early_sha1_init(&sctx);
+		early_sha1_update(&sctx, data, length);
+		early_sha1_final(&sctx, &sha1_hash[0]);
+		memcpy(&pcr_event->digest[0], &sha1_hash[0], SHA1_DIGEST_SIZE);
+	}
+	pcr_event->event_size = event_size;
+	if (event_size > 0)
+		memcpy((u8 *)pcr_event + sizeof(struct tcg_pcr_event),
+		       event_data, event_size);
+
+	total_size = sizeof(struct tcg_pcr_event) + event_size;
+
+	if (tpm12_log_event(evtlog_base, evtlog_size, total_size, pcr_event))
+		sl_txt_reset(SL_ERROR_TPM_LOGGING_FAILED);
+}
+
+static void sl_tpm20_log_event(u32 pcr, u32 event_type,
+			       const u8 *data, u32 length,
+			       const u8 *event_data, u32 event_size)
+{
+	u8 sha256_hash[SHA256_DIGEST_SIZE] = {0};
+	u8 sha1_hash[SHA1_DIGEST_SIZE] = {0};
+	u8 log_buf[SL_TPM20_LOG_SIZE] = {0};
+	struct sha256_state sctx256 = {0};
+	struct tcg_pcr_event2_head *head;
+	struct tcg_event_field *event;
+	struct sha1_state sctx1 = {0};
+	u32 total_size;
+	u16 *alg_ptr;
+	u8 *dgst_ptr;
+
+	head = (struct tcg_pcr_event2_head *)log_buf;
+	head->pcr_idx = pcr;
+	head->event_type = event_type;
+	total_size = sizeof(struct tcg_pcr_event2_head);
+	alg_ptr = (u16 *)(log_buf + sizeof(struct tcg_pcr_event2_head));
+
+	for ( ; head->count < 2; head->count++) {
+		if (!tpm_algs[head->count].alg_id)
+			break;
+
+		*alg_ptr = tpm_algs[head->count].alg_id;
+		dgst_ptr = (u8 *)alg_ptr + sizeof(u16);
+
+		if (tpm_algs[head->count].alg_id == TPM_ALG_SHA256 &&
+		    length) {
+			sha256_init(&sctx256);
+			sha256_update(&sctx256, data, length);
+			sha256_final(&sctx256, &sha256_hash[0]);
+		} else if (tpm_algs[head->count].alg_id == TPM_ALG_SHA1 &&
+			   length) {
+			early_sha1_init(&sctx1);
+			early_sha1_update(&sctx1, data, length);
+			early_sha1_final(&sctx1, &sha1_hash[0]);
+		}
+
+		if (tpm_algs[head->count].alg_id == TPM_ALG_SHA256) {
+			memcpy(dgst_ptr, &sha256_hash[0], SHA256_DIGEST_SIZE);
+			total_size += SHA256_DIGEST_SIZE + sizeof(u16);
+			alg_ptr = (u16 *)((u8 *)alg_ptr + SHA256_DIGEST_SIZE + sizeof(u16));
+		} else if (tpm_algs[head->count].alg_id == TPM_ALG_SHA1) {
+			memcpy(dgst_ptr, &sha1_hash[0], SHA1_DIGEST_SIZE);
+			total_size += SHA1_DIGEST_SIZE + sizeof(u16);
+			alg_ptr = (u16 *)((u8 *)alg_ptr + SHA1_DIGEST_SIZE + sizeof(u16));
+		} else
+			sl_txt_reset(SL_ERROR_TPM_UNKNOWN_DIGEST);
+	}
+
+	event = (struct tcg_event_field *)(log_buf + total_size);
+	event->event_size = event_size;
+	if (event_size > 0)
+		memcpy((u8 *)event + sizeof(struct tcg_event_field),
+		       event_data, event_size);
+	total_size += sizeof(struct tcg_event_field) + event_size;
+
+	if (tpm20_log_event(log20_elem, evtlog_base, evtlog_size,
+	    total_size, &log_buf[0]))
+		sl_txt_reset(SL_ERROR_TPM_LOGGING_FAILED);
+}
+
+static void sl_tpm_extend_evtlog(u32 pcr, u32 type,
+				 const u8 *data, u32 length, const char *desc)
+{
+	if (tpm_log_ver == SL_TPM20_LOG)
+		sl_tpm20_log_event(pcr, type, data, length,
+				   (const u8 *)desc, strlen(desc));
+	else
+		sl_tpm12_log_event(pcr, type, data, length,
+				   (const u8 *)desc, strlen(desc));
+}
+
+static struct setup_data *sl_handle_setup_data(struct setup_data *curr,
+					       struct slr_policy_entry *entry)
+{
+	struct setup_indirect *ind;
+	struct setup_data *next;
+
+	if (!curr)
+		return NULL;
+
+	next = (struct setup_data *)(unsigned long)curr->next;
+
+	/* SETUP_INDIRECT instances have to be handled differently */
+	if (curr->type == SETUP_INDIRECT) {
+		ind = (struct setup_indirect *)
+			((u8 *)curr + offsetof(struct setup_data, data));
+
+		sl_check_pmr_coverage((void *)ind->addr, ind->len, true);
+
+		sl_tpm_extend_evtlog(entry->pcr, TXT_EVTYPE_SLAUNCH,
+				     (void *)ind->addr, ind->len,
+				     entry->evt_info);
+
+		return next;
+	}
+
+	sl_check_pmr_coverage(((u8 *)curr) + sizeof(struct setup_data),
+			      curr->len, true);
+
+	sl_tpm_extend_evtlog(entry->pcr, TXT_EVTYPE_SLAUNCH,
+			     ((u8 *)curr) + sizeof(struct setup_data),
+			     curr->len,
+			     entry->evt_info);
+
+	return next;
+}
+
+static void sl_extend_setup_data(struct slr_policy_entry *entry)
+{
+	struct setup_data *data;
+
+	/*
+	 * Measuring the boot params measured the fixed e820 memory map.
+	 * Measure any setup_data entries including e820 extended entries.
+	 */
+	data = (struct setup_data *)(unsigned long)entry->entity;
+	while (data)
+		data = sl_handle_setup_data(data, entry);
+}
+
+static void sl_extend_slrt(struct slr_policy_entry *entry)
+{
+	struct slr_table *slrt = (struct slr_table *)entry->entity;
+	struct slr_entry_intel_info *intel_info;
+
+	/*
+	 * In revision one of the SLRT, the only table that needs to be
+	 * measured is the Intel info table. Everything else is meta-data,
+	 * addresses and sizes.
+	 */
+	if (slrt->revision == 1) {
+		intel_info = (struct slr_entry_intel_info *)
+				slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO);
+		if (!intel_info)
+			sl_txt_reset(SL_ERROR_SLRT_MISSING_ENTRY);
+
+		sl_tpm_extend_evtlog(entry->pcr, TXT_EVTYPE_SLAUNCH,
+				     (void *)entry->entity, entry->size,
+				     entry->evt_info);
+	}
+}
+
+static void sl_extend_txt_os2mle(struct slr_policy_entry *entry)
+{
+	struct txt_os_mle_data *os_mle_data;
+	void *txt_heap;
+
+	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+	os_mle_data = txt_os_mle_data_start(txt_heap);
+
+	/*
+	 * Version 1 of the OS-MLE heap structure has no fields to measure. It just
+	 * has addresses and sizes and a scratch buffer.
+	 */
+	if (os_mle_data->version == 1)
+		return;
+}
+
+static void sl_process_extend_policy(struct slr_table *slrt)
+{
+	struct slr_entry_policy *policy;
+	struct slr_policy_entry *entry;
+	u16 i = 0;
+
+	policy =(struct slr_entry_policy *)
+		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_ENTRY_POLICY);
+	if (!policy)
+		sl_txt_reset(SL_ERROR_SLRT_MISSING_ENTRY);
+
+	entry = (struct slr_policy_entry *)((u8 *)policy + sizeof(*policy));
+
+	for ( ; i < policy->nr_entries; i++, entry++) {
+		switch (entry->entity_type) {
+		case SLR_ET_SETUP_DATA:
+			sl_extend_setup_data(entry);
+			break;
+		case SLR_ET_SLRT:
+			sl_extend_slrt(entry);
+			break;
+		case SLR_ET_TXT_OS2MLE:
+			sl_extend_txt_os2mle(entry);
+			break;
+		case SLR_ET_UNUSED:
+			continue;
+		default:
+			sl_tpm_extend_evtlog(entry->pcr, TXT_EVTYPE_SLAUNCH,
+					     (void *)entry->entity, entry->size,
+					     entry->evt_info);
+		}
+	}
+}
+
+static void sl_process_extend_uefi_config(struct slr_table *slrt)
+{
+	struct slr_entry_uefi_config *uefi_config;
+	struct slr_uefi_cfg_entry *uefi_entry;
+	u64 i;
+
+	uefi_config =(struct slr_entry_uefi_config *)
+		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_UEFI_CONFIG);
+
+	/* Optionally here depending on how SL kernel was booted */
+	if (!uefi_config)
+		return;
+
+	uefi_entry = (struct slr_uefi_cfg_entry *)((u8 *)uefi_config + sizeof(*uefi_config));
+
+	for ( ; i < uefi_config->nr_entries; i++, uefi_entry++) {
+		sl_tpm_extend_evtlog(uefi_entry->pcr, TXT_EVTYPE_SLAUNCH,
+				     (void *)uefi_entry->cfg, uefi_entry->size,
+				     uefi_entry->evt_info);
+	}
+}
+
+asmlinkage __visible void sl_check_region(void *base, u32 size)
+{
+	sl_check_pmr_coverage(base, size, false);
+}
+
+asmlinkage __visible void sl_main(void *bootparams)
+{
+	struct boot_params *bp  = (struct boot_params *)bootparams;
+	struct txt_os_mle_data *os_mle_data;
+	struct slr_table *slrt;
+	void *txt_heap;
+
+	/*
+	 * Ensure loadflags do not indicate a secure launch was done
+	 * unless it really was.
+	 */
+	bp->hdr.loadflags &= ~SLAUNCH_FLAG;
+
+	/*
+	 * Currently only Intel TXT is supported for Secure Launch. Testing
+	 * this value also indicates that the kernel was booted successfully
+	 * through the Secure Launch entry point and is in SMX mode.
+	 */
+	if (!(sl_cpu_type & SL_CPU_INTEL))
+		return;
+
+	slrt = sl_locate_and_validate_slrt();
+
+	/* Locate the TPM event log. */
+	sl_find_event_log(slrt);
+
+	/* Validate the location of the event log buffer before using it */
+	sl_validate_event_log_buffer();
+
+	/*
+	 * Find the TPM hash algorithms used by the ACM and recorded in the
+	 * event log.
+	 */
+	if (tpm_log_ver == SL_TPM20_LOG)
+		sl_find_event_log_algorithms();
+
+	/*
+	 * Sanitize them before measuring. Set the SLAUNCH_FLAG early since if
+	 * anything fails, the system will reset anyway.
+	 */
+	boot_params = (struct boot_params *)bootparams;
+	sanitize_boot_params(boot_params);
+	bp->hdr.loadflags |= SLAUNCH_FLAG;
+
+	sl_check_pmr_coverage(bootparams, PAGE_SIZE, false);
+
+	/* Place event log SL specific tags before and after measurements */
+	sl_tpm_extend_evtlog(17, TXT_EVTYPE_SLAUNCH_START, NULL, 0, "");
+
+	/* Process all policy entries and extend the measurements to the evtlog */
+	sl_process_extend_policy(slrt);
+
+	/* Process all EFI config entries and extend the measurements to the evtlog */
+	sl_process_extend_uefi_config(slrt);
+
+	sl_tpm_extend_evtlog(17, TXT_EVTYPE_SLAUNCH_END, NULL, 0, "");
+
+	/* No PMR check is needed, the TXT heap is covered by the DPR */
+	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+	os_mle_data = txt_os_mle_data_start(txt_heap);
+
+	/*
+	 * Now that the OS-MLE data is measured, ensure the MTRR and
+	 * misc enable MSRs are what we expect.
+	 */
+	sl_txt_validate_msrs(os_mle_data);
+}
diff --git a/arch/x86/boot/compressed/sl_stub.S b/arch/x86/boot/compressed/sl_stub.S
new file mode 100644
index 0000000..2d8aa3a
--- /dev/null
+++ b/arch/x86/boot/compressed/sl_stub.S
@@ -0,0 +1,690 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Secure Launch protected mode entry point.
+ *
+ * Copyright (c) 2022, Oracle and/or its affiliates.
+ */
+	.code32
+	.text
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/msr.h>
+#include <asm/processor-flags.h>
+#include <asm/asm-offsets.h>
+#include <asm/bootparam.h>
+#include <asm/page_types.h>
+#include <asm/irq_vectors.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
+
+/* CPUID: leaf 1, ECX, SMX feature bit */
+#define X86_FEATURE_BIT_SMX	(1 << 6)
+
+/* Can't include apiddef.h in asm */
+#define XAPIC_ENABLE	(1 << 11)
+#define X2APIC_ENABLE	(1 << 10)
+
+/* Can't include traps.h in asm */
+#define X86_TRAP_NMI	2
+
+/* Can't include mtrr.h in asm */
+#define MTRRphysBase0	0x200
+
+#define IDT_VECTOR_LO_BITS	0
+#define IDT_VECTOR_HI_BITS	6
+
+/*
+ * See the comment in head_64.S for detailed informatoin on what this macro
+ * is used for.
+ */
+#define rva(X) ((X) - sl_stub_entry)
+
+/*
+ * The GETSEC op code is open coded because older versions of
+ * GCC do not support the getsec mnemonic.
+ */
+.macro GETSEC leaf
+	pushl	%ebx
+	xorl	%ebx, %ebx	/* Must be zero for SMCTRL */
+	movl	\leaf, %eax	/* Leaf function */
+	.byte 	0x0f, 0x37	/* GETSEC opcode */
+	popl	%ebx
+.endm
+
+.macro TXT_RESET error
+	/*
+	 * Set a sticky error value and reset. Note the movs to %eax act as
+	 * TXT register barriers.
+	 */
+	movl	\error, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_ERRORCODE)
+	movl	(TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_E2STS), %eax
+	movl	$1, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_CMD_NO_SECRETS)
+	movl	(TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_E2STS), %eax
+	movl	$1, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_CMD_UNLOCK_MEM_CONFIG)
+	movl	(TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_E2STS), %eax
+	movl	$1, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_CMD_RESET)
+1:
+	hlt
+	jmp	1b
+.endm
+
+	.code32
+SYM_FUNC_START(sl_stub_entry)
+	cli
+	cld
+
+	/*
+	 * On entry, %ebx has the entry abs offset to sl_stub_entry. This
+	 * will be correctly scaled using the rva macro and avoid causing
+	 * relocations. Only %cs and %ds segments are known good.
+	 */
+
+	/* Load GDT, set segment regs and lret to __SL32_CS */
+	leal	rva(sl_gdt_desc)(%ebx), %eax
+	addl	%eax, 2(%eax)
+	lgdt	(%eax)
+
+	movl	$(__SL32_DS), %eax
+	movw	%ax, %ds
+	movw	%ax, %es
+	movw	%ax, %fs
+	movw	%ax, %gs
+	movw	%ax, %ss
+
+	/*
+	 * Now that %ss is known good, take the first stack for the BSP. The
+	 * AP stacks are only used on Intel.
+	 */
+	leal	rva(sl_stacks_end)(%ebx), %esp
+
+	leal	rva(.Lsl_cs)(%ebx), %eax
+	pushl	$(__SL32_CS)
+	pushl	%eax
+	lret
+
+.Lsl_cs:
+	/* Save our base pointer reg and page table for MLE */
+	pushl	%ebx
+	pushl	%ecx
+
+	/* See if SMX feature is supported. */
+	movl	$1, %eax
+	cpuid
+	testl	$(X86_FEATURE_BIT_SMX), %ecx
+	jz	.Ldo_unknown_cpu
+
+	popl	%ecx
+	popl	%ebx
+
+	/* Know it is Intel */
+	movl	$(SL_CPU_INTEL), rva(sl_cpu_type)(%ebx)
+
+	/* Locate the base of the MLE using the page tables in %ecx */
+	call	sl_find_mle_base
+
+	/* Increment CPU count for BSP */
+	incl	rva(sl_txt_cpu_count)(%ebx)
+
+	/*
+	 * Enable SMI with GETSEC[SMCTRL] which were disabled by SENTER.
+	 * NMIs were also disabled by SENTER. Since there is no IDT for the BSP,
+	 * allow the mainline kernel re-enable them in the normal course of
+	 * booting.
+	 */
+	GETSEC	$(SMX_X86_GETSEC_SMCTRL)
+
+	/* Clear the TXT error registers for a clean start of day */
+	movl	$0, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_ERRORCODE)
+	movl	$0xffffffff, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_ESTS)
+
+	/* On Intel, the zero page address is passed in the TXT heap */
+	/* Read physical base of heap into EAX */
+	movl	(TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_HEAP_BASE), %eax
+	/* Read the size of the BIOS data into ECX (first 8 bytes) */
+	movl	(%eax), %ecx
+	/* Skip over BIOS data and size of OS to MLE data section */
+	leal	8(%eax, %ecx), %eax
+
+	/* Need to verify the values in the OS-MLE struct passed in */
+	call	sl_txt_verify_os_mle_struct
+
+	/*
+	 * Get the boot params address from the heap. Note %esi and %ebx MUST
+	 * be preserved across calls and operations.
+	 */
+	movl	SL_boot_params_addr(%eax), %esi
+
+	/* Save %ebx so the APs can find their way home */
+	movl	%ebx, (SL_mle_scratch + SL_SCRATCH_AP_EBX)(%eax)
+
+	/* Fetch the AP wake code block address from the heap */
+	movl	SL_ap_wake_block(%eax), %edi
+	movl	%edi, rva(sl_txt_ap_wake_block)(%ebx)
+
+	/* Store the offset in the AP wake block to the jmp address */
+	movl	$(sl_ap_jmp_offset - sl_txt_ap_wake_begin), \
+		(SL_mle_scratch + SL_SCRATCH_AP_JMP_OFFSET)(%eax)
+
+	/* %eax still is the base of the OS-MLE block, save it */
+	pushl	%eax
+
+	/* Relocate the AP wake code to the safe block */
+	call	sl_txt_reloc_ap_wake
+
+	/*
+	 * Wake up all APs that are blocked in the ACM and wait for them to
+	 * halt. This should be done before restoring the MTRRs so the ACM is
+	 * still properly in WB memory.
+	 */
+	call	sl_txt_wake_aps
+
+	/* Restore OS-MLE in %eax */
+	popl	%eax
+
+	/*
+	 * %edi is used by this routine to find the MTRRs which are in the SLRT
+	 * in the Intel info.
+	 */
+	movl	SL_txt_info(%eax), %edi
+	call	sl_txt_load_regs
+
+	jmp	.Lcpu_setup_done
+
+.Ldo_unknown_cpu:
+	/* Non-Intel CPUs are not yet supported */
+	ud2
+
+.Lcpu_setup_done:
+	/*
+	 * Don't enable MCE at this point. The kernel will enable
+	 * it on the BSP later when it is ready.
+	 */
+
+	/* Done, jump to normal 32b pm entry */
+	jmp	startup_32
+SYM_FUNC_END(sl_stub_entry)
+
+SYM_FUNC_START(sl_find_mle_base)
+	/* %ecx has PDPT, get first PD */
+	movl	(%ecx), %eax
+	andl	$(PAGE_MASK), %eax
+	/* Get first PT from first PDE */
+	movl	(%eax), %eax
+	andl	$(PAGE_MASK), %eax
+	/* Get MLE base from first PTE */
+	movl	(%eax), %eax
+	andl	$(PAGE_MASK), %eax
+
+	movl	%eax, rva(sl_mle_start)(%ebx)
+	ret
+SYM_FUNC_END(sl_find_mle_base)
+
+SYM_FUNC_START(sl_check_buffer_mle_overlap)
+	/* %ecx: buffer begin %edx: buffer end */
+	/* %ebx: MLE begin %edi: MLE end */
+
+	cmpl	%edi, %ecx
+	jb	.Lnext_check
+	cmpl	%edi, %edx
+	jbe	.Lnext_check
+	jmp	.Lvalid /* Buffer above MLE */
+
+.Lnext_check:
+	cmpl	%ebx, %edx
+	ja	.Linvalid
+	cmpl	%ebx, %ecx
+	jae	.Linvalid
+	jmp	.Lvalid /* Buffer below MLE */
+
+.Linvalid:
+	TXT_RESET $(SL_ERROR_MLE_BUFFER_OVERLAP)
+
+.Lvalid:
+	ret
+SYM_FUNC_END(sl_check_buffer_mle_overlap)
+
+SYM_FUNC_START(sl_txt_verify_os_mle_struct)
+	pushl	%ebx
+	/*
+	 * %eax points to the base of the OS-MLE struct. Need to also
+	 * read some values from the OS-SINIT struct too.
+	 */
+	movl	-8(%eax), %ecx
+	/* Skip over OS to MLE data section and size of OS-SINIT structure */
+	leal	(%eax, %ecx), %edx
+
+	/* Load MLE image base absolute offset */
+	movl	rva(sl_mle_start)(%ebx), %ebx
+
+	/* Verify the value of the low PMR base. It should always be 0. */
+	movl	SL_vtd_pmr_lo_base(%edx), %esi
+	cmpl	$0, %esi
+	jz	.Lvalid_pmr_base
+	TXT_RESET $(SL_ERROR_LO_PMR_BASE)
+
+.Lvalid_pmr_base:
+	/* Grab some values from OS-SINIT structure */
+	movl	SL_mle_size(%edx), %edi
+	addl	%ebx, %edi
+	jc	.Loverflow_detected
+	movl	SL_vtd_pmr_lo_size(%edx), %esi
+
+	/* Check the AP wake block */
+	movl	SL_ap_wake_block(%eax), %ecx
+	movl	SL_ap_wake_block_size(%eax), %edx
+	addl	%ecx, %edx
+	jc	.Loverflow_detected
+	call	sl_check_buffer_mle_overlap
+	cmpl	%esi, %edx
+	ja	.Lbuffer_beyond_pmr
+
+	/* Check the boot params */
+	movl	SL_boot_params_addr(%eax), %ecx
+	movl	$(PAGE_SIZE), %edx
+	addl	%ecx, %edx
+	jc	.Loverflow_detected
+	call	sl_check_buffer_mle_overlap
+	cmpl	%esi, %edx
+	ja	.Lbuffer_beyond_pmr
+
+	/* Check that the AP wake block is big enough */
+	cmpl	$(sl_txt_ap_wake_end - sl_txt_ap_wake_begin), \
+		SL_ap_wake_block_size(%eax)
+	jae	.Lwake_block_ok
+	TXT_RESET $(SL_ERROR_WAKE_BLOCK_TOO_SMALL)
+
+.Lwake_block_ok:
+	popl	%ebx
+	ret
+
+.Loverflow_detected:
+	TXT_RESET $(SL_ERROR_INTEGER_OVERFLOW)
+
+.Lbuffer_beyond_pmr:
+	TXT_RESET $(SL_ERROR_BUFFER_BEYOND_PMR)
+SYM_FUNC_END(sl_txt_verify_os_mle_struct)
+
+SYM_FUNC_START(sl_txt_ap_entry)
+	cli
+	cld
+	/*
+	 * The %cs and %ds segments are known good after waking the AP.
+	 * First order of business is to find where we are and
+	 * save it in %ebx.
+	 */
+
+	/* Read physical base of heap into EAX */
+	movl	(TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_HEAP_BASE), %eax
+	/* Read the size of the BIOS data into ECX (first 8 bytes) */
+	movl	(%eax), %ecx
+	/* Skip over BIOS data and size of OS to MLE data section */
+	leal	8(%eax, %ecx), %eax
+
+	/* Saved %ebx from the BSP and stash OS-MLE pointer */
+	movl	(SL_mle_scratch + SL_SCRATCH_AP_EBX)(%eax), %ebx
+
+	/* Save TXT info ptr in %edi for call to sl_txt_load_regs */
+	movl	SL_txt_info(%eax), %edi
+
+	/* Lock and get our stack index */
+	movl	$1, %ecx
+.Lspin:
+	xorl	%eax, %eax
+	lock cmpxchgl	%ecx, rva(sl_txt_spin_lock)(%ebx)
+	pause
+	jnz	.Lspin
+
+	/* Increment the stack index and use the next value inside lock */
+	incl	rva(sl_txt_stack_index)(%ebx)
+	movl	rva(sl_txt_stack_index)(%ebx), %eax
+
+	/* Unlock */
+	movl	$0, rva(sl_txt_spin_lock)(%ebx)
+
+	/* Location of the relocated AP wake block */
+	movl	rva(sl_txt_ap_wake_block)(%ebx), %ecx
+
+	/* Load reloc GDT, set segment regs and lret to __SL32_CS */
+	lgdt	(sl_ap_gdt_desc - sl_txt_ap_wake_begin)(%ecx)
+
+	movl	$(__SL32_DS), %edx
+	movw	%dx, %ds
+	movw	%dx, %es
+	movw	%dx, %fs
+	movw	%dx, %gs
+	movw	%dx, %ss
+
+	/* Load our reloc AP stack */
+	movl	$(TXT_BOOT_STACK_SIZE), %edx
+	mull	%edx
+	leal	(sl_stacks_end - sl_txt_ap_wake_begin)(%ecx), %esp
+	subl	%eax, %esp
+
+	/* Switch to AP code segment */
+	leal	rva(.Lsl_ap_cs)(%ebx), %eax
+	pushl	$(__SL32_CS)
+	pushl	%eax
+	lret
+
+.Lsl_ap_cs:
+	/* Load the relocated AP IDT */
+	lidt	(sl_ap_idt_desc - sl_txt_ap_wake_begin)(%ecx)
+
+	/* Fixup MTRRs and misc enable MSR on APs too */
+	call	sl_txt_load_regs
+
+	/* Enable SMI with GETSEC[SMCTRL] */
+	GETSEC $(SMX_X86_GETSEC_SMCTRL)
+
+	/* IRET-to-self can be used to enable NMIs which SENTER disabled */
+	leal	rva(.Lnmi_enabled_ap)(%ebx), %eax
+	pushfl
+	pushl	$(__SL32_CS)
+	pushl	%eax
+	iret
+
+.Lnmi_enabled_ap:
+	/* Put APs in X2APIC mode like the BSP */
+	movl	$(MSR_IA32_APICBASE), %ecx
+	rdmsr
+	orl	$(XAPIC_ENABLE | X2APIC_ENABLE), %eax
+	wrmsr
+
+	/*
+	 * Basically done, increment the CPU count and jump off to the AP
+	 * wake block to wait.
+	 */
+	lock incl	rva(sl_txt_cpu_count)(%ebx)
+
+	movl	rva(sl_txt_ap_wake_block)(%ebx), %eax
+	jmp	*%eax
+SYM_FUNC_END(sl_txt_ap_entry)
+
+SYM_FUNC_START(sl_txt_reloc_ap_wake)
+	/* Save boot params register */
+	pushl	%esi
+
+	movl	rva(sl_txt_ap_wake_block)(%ebx), %edi
+
+	/* Fixup AP IDT and GDT descriptor before relocating */
+	leal	rva(sl_ap_idt_desc)(%ebx), %eax
+	addl	%edi, 2(%eax)
+	leal	rva(sl_ap_gdt_desc)(%ebx), %eax
+	addl	%edi, 2(%eax)
+
+	/*
+	 * Copy the AP wake code and AP GDT/IDT to the protected wake block
+	 * provided by the loader. Destination already in %edi.
+	 */
+	movl	$(sl_txt_ap_wake_end - sl_txt_ap_wake_begin), %ecx
+	leal	rva(sl_txt_ap_wake_begin)(%ebx), %esi
+	rep movsb
+
+	/* Setup the IDT for the APs to use in the relocation block */
+	movl	rva(sl_txt_ap_wake_block)(%ebx), %ecx
+	addl	$(sl_ap_idt - sl_txt_ap_wake_begin), %ecx
+	xorl	%edx, %edx
+
+	/* Form the default reset vector relocation address */
+	movl	rva(sl_txt_ap_wake_block)(%ebx), %esi
+	addl	$(sl_txt_int_reset - sl_txt_ap_wake_begin), %esi
+
+1:
+	cmpw	$(NR_VECTORS), %dx
+	jz	.Lap_idt_done
+
+	cmpw	$(X86_TRAP_NMI), %dx
+	jz	2f
+
+	/* Load all other fixed vectors with reset handler */
+	movl	%esi, %eax
+	movw	%ax, (IDT_VECTOR_LO_BITS)(%ecx)
+	shrl	$16, %eax
+	movw	%ax, (IDT_VECTOR_HI_BITS)(%ecx)
+	jmp	3f
+
+2:
+	/* Load single wake NMI IPI vector at the relocation address */
+	movl	rva(sl_txt_ap_wake_block)(%ebx), %eax
+	addl	$(sl_txt_int_ipi_wake - sl_txt_ap_wake_begin), %eax
+	movw	%ax, (IDT_VECTOR_LO_BITS)(%ecx)
+	shrl	$16, %eax
+	movw	%ax, (IDT_VECTOR_HI_BITS)(%ecx)
+
+3:
+	incw	%dx
+	addl	$8, %ecx
+	jmp	1b
+
+.Lap_idt_done:
+	popl	%esi
+	ret
+SYM_FUNC_END(sl_txt_reloc_ap_wake)
+
+SYM_FUNC_START(sl_txt_load_regs)
+	/* Save base pointer register */
+	pushl	%ebx
+
+	/*
+	 * On Intel, the original variable MTRRs and Misc Enable MSR are
+	 * restored on the BSP at early boot. Each AP will also restore
+	 * its MTRRs and Misc Enable MSR.
+	 */
+	pushl	%edi
+	addl	$(SL_saved_bsp_mtrrs), %edi
+	movl	(%edi), %ebx
+	pushl	%ebx /* default_mem_type lo */
+	addl	$4, %edi
+	movl	(%edi), %ebx
+	pushl	%ebx /* default_mem_type hi */
+	addl	$4, %edi
+	movl	(%edi), %ebx /* mtrr_vcnt lo, don't care about hi part */
+	addl	$8, %edi /* now at MTRR pair array */
+	/* Write the variable MTRRs */
+	movl	$(MTRRphysBase0), %ecx
+1:
+	cmpl	$0, %ebx
+	jz	2f
+
+	movl	(%edi), %eax /* MTRRphysBaseX lo */
+	addl	$4, %edi
+	movl	(%edi), %edx /* MTRRphysBaseX hi */
+	wrmsr
+	addl	$4, %edi
+	incl	%ecx
+	movl	(%edi), %eax /* MTRRphysMaskX lo */
+	addl	$4, %edi
+	movl	(%edi), %edx /* MTRRphysMaskX hi */
+	wrmsr
+	addl	$4, %edi
+	incl	%ecx
+
+	decl	%ebx
+	jmp	1b
+2:
+	/* Write the default MTRR register */
+	popl	%edx
+	popl	%eax
+	movl	$(MSR_MTRRdefType), %ecx
+	wrmsr
+
+	/* Return to beginning and write the misc enable msr */
+	popl	%edi
+	addl	$(SL_saved_misc_enable_msr), %edi
+	movl	(%edi), %eax /* saved_misc_enable_msr lo */
+	addl	$4, %edi
+	movl	(%edi), %edx /* saved_misc_enable_msr hi */
+	movl	$(MSR_IA32_MISC_ENABLE), %ecx
+	wrmsr
+
+	popl	%ebx
+	ret
+SYM_FUNC_END(sl_txt_load_regs)
+
+SYM_FUNC_START(sl_txt_wake_aps)
+	/* Save boot params register */
+	pushl	%esi
+
+	/* First setup the MLE join structure and load it into TXT reg */
+	leal	rva(sl_gdt)(%ebx), %eax
+	leal	rva(sl_txt_ap_entry)(%ebx), %ecx
+	leal	rva(sl_smx_rlp_mle_join)(%ebx), %edx
+	movl	%eax, SL_rlp_gdt_base(%edx)
+	movl	%ecx, SL_rlp_entry_point(%edx)
+	movl	%edx, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_MLE_JOIN)
+
+	/* Another TXT heap walk to find various values needed to wake APs */
+	movl	(TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_HEAP_BASE), %eax
+	/* At BIOS data size, find the number of logical processors */
+	movl	(SL_num_logical_procs + 8)(%eax), %edx
+	/* Skip over BIOS data */
+	movl	(%eax), %ecx
+	addl	%ecx, %eax
+	/* Skip over OS to MLE */
+	movl	(%eax), %ecx
+	addl	%ecx, %eax
+	/* At OS-SNIT size, get capabilities to know how to wake up the APs */
+	movl	(SL_capabilities + 8)(%eax), %esi
+	/* Skip over OS to SNIT */
+	movl	(%eax), %ecx
+	addl	%ecx, %eax
+	/* At SINIT-MLE size, get the AP wake MONITOR address */
+	movl	(SL_rlp_wakeup_addr + 8)(%eax), %edi
+
+	/* Determine how to wake up the APs */
+	testl	$(1 << TXT_SINIT_MLE_CAP_WAKE_MONITOR), %esi
+	jz	.Lwake_getsec
+
+	/* Wake using MWAIT MONITOR */
+	movl	$1, (%edi)
+	jmp	.Laps_awake
+
+.Lwake_getsec:
+	/* Wake using GETSEC(WAKEUP) */
+	GETSEC	$(SMX_X86_GETSEC_WAKEUP)
+
+.Laps_awake:
+	/*
+	 * All of the APs are woken up and rendesvous in the relocated wake
+	 * block starting at sl_txt_ap_wake_begin. Wait for all of them to
+	 * halt.
+	 */
+	pause
+	cmpl	rva(sl_txt_cpu_count)(%ebx), %edx
+	jne	.Laps_awake
+
+	popl	%esi
+	ret
+SYM_FUNC_END(sl_txt_wake_aps)
+
+/* This is the beginning of the relocated AP wake code block */
+	.global sl_txt_ap_wake_begin
+sl_txt_ap_wake_begin:
+
+	/*
+	 * Wait for NMI IPI in the relocated AP wake block which was provided
+	 * and protected in the memory map by the prelaunch code. Leave all
+	 * other interrupts masked since we do not expect anything but an NMI.
+	 */
+	xorl	%edx, %edx
+
+1:
+	hlt
+	testl	%edx, %edx
+	jz	1b
+
+	/*
+	 * This is the long absolute jump to the 32b Secure Launch protected
+	 * mode stub code in the rmpiggy. The jump address will be fixed in
+	 * the SMP boot code when the first AP is brought up. This whole area
+	 * is provided and protected in the memory map by the prelaunch code.
+	 */
+	.byte	0xea
+sl_ap_jmp_offset:
+	.long	0x00000000
+	.word	__SL32_CS
+
+SYM_FUNC_START(sl_txt_int_ipi_wake)
+	movl	$1, %edx
+
+	/* NMI context, just IRET */
+	iret
+SYM_FUNC_END(sl_txt_int_ipi_wake)
+
+SYM_FUNC_START(sl_txt_int_reset)
+	TXT_RESET $(SL_ERROR_INV_AP_INTERRUPT)
+SYM_FUNC_END(sl_txt_int_reset)
+
+	.balign 8
+SYM_DATA_START_LOCAL(sl_ap_idt_desc)
+	.word	sl_ap_idt_end - sl_ap_idt - 1		/* Limit */
+	.long	sl_ap_idt - sl_txt_ap_wake_begin	/* Base */
+SYM_DATA_END_LABEL(sl_ap_idt_desc, SYM_L_LOCAL, sl_ap_idt_desc_end)
+
+	.balign 8
+SYM_DATA_START_LOCAL(sl_ap_idt)
+	.rept	NR_VECTORS
+	.word	0x0000		/* Offset 15 to 0 */
+	.word	__SL32_CS	/* Segment selector */
+	.word	0x8e00		/* Present, DPL=0, 32b Vector, Interrupt */
+	.word	0x0000		/* Offset 31 to 16 */
+	.endr
+SYM_DATA_END_LABEL(sl_ap_idt, SYM_L_LOCAL, sl_ap_idt_end)
+
+	.balign 8
+SYM_DATA_START_LOCAL(sl_ap_gdt_desc)
+	.word	sl_ap_gdt_end - sl_ap_gdt - 1
+	.long	sl_ap_gdt - sl_txt_ap_wake_begin
+SYM_DATA_END_LABEL(sl_ap_gdt_desc, SYM_L_LOCAL, sl_ap_gdt_desc_end)
+
+	.balign	8
+SYM_DATA_START_LOCAL(sl_ap_gdt)
+	.quad	0x0000000000000000	/* NULL */
+	.quad	0x00cf9a000000ffff	/* __SL32_CS */
+	.quad	0x00cf92000000ffff	/* __SL32_DS */
+SYM_DATA_END_LABEL(sl_ap_gdt, SYM_L_LOCAL, sl_ap_gdt_end)
+
+	/* Small stacks for BSP and APs to work with */
+	.balign 4
+SYM_DATA_START_LOCAL(sl_stacks)
+	.fill (TXT_MAX_CPUS * TXT_BOOT_STACK_SIZE), 1, 0
+SYM_DATA_END_LABEL(sl_stacks, SYM_L_LOCAL, sl_stacks_end)
+
+/* This is the end of the relocated AP wake code block */
+	.global sl_txt_ap_wake_end
+sl_txt_ap_wake_end:
+
+	.data
+	.balign 8
+SYM_DATA_START_LOCAL(sl_gdt_desc)
+	.word	sl_gdt_end - sl_gdt - 1
+	.long	sl_gdt - sl_gdt_desc
+SYM_DATA_END_LABEL(sl_gdt_desc, SYM_L_LOCAL, sl_gdt_desc_end)
+
+	.balign	8
+SYM_DATA_START_LOCAL(sl_gdt)
+	.quad	0x0000000000000000	/* NULL */
+	.quad	0x00cf9a000000ffff	/* __SL32_CS */
+	.quad	0x00cf92000000ffff	/* __SL32_DS */
+SYM_DATA_END_LABEL(sl_gdt, SYM_L_LOCAL, sl_gdt_end)
+
+	.balign 8
+SYM_DATA_START_LOCAL(sl_smx_rlp_mle_join)
+	.long	sl_gdt_end - sl_gdt - 1	/* GDT limit */
+	.long	0x00000000		/* GDT base */
+	.long	__SL32_CS	/* Seg Sel - CS (DS, ES, SS = seg_sel+8) */
+	.long	0x00000000	/* Entry point physical address */
+SYM_DATA_END(sl_smx_rlp_mle_join)
+
+SYM_DATA(sl_cpu_type, .long 0x00000000)
+
+SYM_DATA(sl_mle_start, .long 0x00000000)
+
+SYM_DATA_LOCAL(sl_txt_spin_lock, .long 0x00000000)
+
+SYM_DATA_LOCAL(sl_txt_stack_index, .long 0x00000000)
+
+SYM_DATA_LOCAL(sl_txt_cpu_count, .long 0x00000000)
+
+SYM_DATA_LOCAL(sl_txt_ap_wake_block, .long 0x00000000)
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index 01d19fc..74e3e7df 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -26,6 +26,7 @@
 /* loadflags */
 #define LOADED_HIGH	(1<<0)
 #define KASLR_FLAG	(1<<1)
+#define SLAUNCH_FLAG	(1<<2)
 #define QUIET_FLAG	(1<<5)
 #define KEEP_SEGMENTS	(1<<6)
 #define CAN_USE_HEAP	(1<<7)
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index dc35763..960d471 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -13,6 +13,8 @@
 #include <linux/hardirq.h>
 #include <linux/suspend.h>
 #include <linux/kbuild.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
 #include <asm/processor.h>
 #include <asm/thread_info.h>
 #include <asm/sigframe.h>
@@ -127,4 +129,22 @@ static void __used common(void)
 	OFFSET(ARIA_CTX_rounds, aria_ctx, rounds);
 #endif
 
+#ifdef CONFIG_SECURE_LAUNCH
+	BLANK();
+	OFFSET(SL_txt_info, txt_os_mle_data, txt_info);
+	OFFSET(SL_mle_scratch, txt_os_mle_data, mle_scratch);
+	OFFSET(SL_boot_params_addr, txt_os_mle_data, boot_params_addr);
+	OFFSET(SL_ap_wake_block, txt_os_mle_data, ap_wake_block);
+	OFFSET(SL_ap_wake_block_size, txt_os_mle_data, ap_wake_block_size);
+	OFFSET(SL_saved_misc_enable_msr, slr_entry_intel_info, saved_misc_enable_msr);
+	OFFSET(SL_saved_bsp_mtrrs, slr_entry_intel_info, saved_bsp_mtrrs);
+	OFFSET(SL_num_logical_procs, txt_bios_data, num_logical_procs);
+	OFFSET(SL_capabilities, txt_os_sinit_data, capabilities);
+	OFFSET(SL_mle_size, txt_os_sinit_data, mle_size);
+	OFFSET(SL_vtd_pmr_lo_base, txt_os_sinit_data, vtd_pmr_lo_base);
+	OFFSET(SL_vtd_pmr_lo_size, txt_os_sinit_data, vtd_pmr_lo_size);
+	OFFSET(SL_rlp_wakeup_addr, txt_sinit_mle_data, rlp_wakeup_addr);
+	OFFSET(SL_rlp_gdt_base, smx_rlp_mle_join, rlp_gdt_base);
+	OFFSET(SL_rlp_entry_point, smx_rlp_mle_join, rlp_entry_point);
+#endif
 }
-- 
1.8.3.1


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

* [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

The Secure Launch (SL) stub provides the entry point for Intel TXT (and
later AMD SKINIT) to vector to during the late launch. The symbol
sl_stub_entry is that entry point and its offset into the kernel is
conveyed to the launching code using the MLE (Measured Launch
Environment) header in the structure named mle_header. The offset of the
MLE header is set in the kernel_info. The routine sl_stub contains the
very early late launch setup code responsible for setting up the basic
environment to allow the normal kernel startup_32 code to proceed. It is
also responsible for properly waking and handling the APs on Intel
platforms. The routine sl_main which runs after entering 64b mode is
responsible for measuring configuration and module information before
it is used like the boot params, the kernel command line, the TXT heap,
an external initramfs, etc.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 Documentation/arch/x86/boot.rst        |  21 +
 arch/x86/boot/compressed/Makefile      |   3 +-
 arch/x86/boot/compressed/head_64.S     |  37 ++
 arch/x86/boot/compressed/kernel_info.S |  34 ++
 arch/x86/boot/compressed/sl_main.c     | 599 ++++++++++++++++++++++++++++
 arch/x86/boot/compressed/sl_stub.S     | 690 +++++++++++++++++++++++++++++++++
 arch/x86/include/uapi/asm/bootparam.h  |   1 +
 arch/x86/kernel/asm-offsets.c          |  20 +
 8 files changed, 1404 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/boot/compressed/sl_main.c
 create mode 100644 arch/x86/boot/compressed/sl_stub.S

diff --git a/Documentation/arch/x86/boot.rst b/Documentation/arch/x86/boot.rst
index 33520ec..90552f7 100644
--- a/Documentation/arch/x86/boot.rst
+++ b/Documentation/arch/x86/boot.rst
@@ -482,6 +482,14 @@ Protocol:	2.00+
 	    - If 1, KASLR enabled.
 	    - If 0, KASLR disabled.
 
+  Bit 2 (kernel internal): SLAUNCH_FLAG
+
+	- Used internally by the compressed kernel to communicate
+	  Secure Launch status to kernel proper.
+
+	    - If 1, Secure Launch enabled.
+	    - If 0, Secure Launch disabled.
+
   Bit 5 (write): QUIET_FLAG
 
 	- If 0, print early messages.
@@ -1027,6 +1035,19 @@ Offset/size:	0x000c/4
 
   This field contains maximal allowed type for setup_data and setup_indirect structs.
 
+============	=================
+Field name:	mle_header_offset
+Offset/size:	0x0010/4
+============	=================
+
+  This field contains the offset to the Secure Launch Measured Launch Environment
+  (MLE) header. This offset is used to locate information needed during a secure
+  late launch using Intel TXT. If the offset is zero, the kernel does not have
+  Secure Launch capabilities. The MLE entry point is called from TXT on the BSP
+  following a success measured launch. The specific state of the processors is
+  outlined in the TXT Software Development Guide, the latest can be found here:
+  https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
+
 
 The Image Checksum
 ==================
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 1d327d4..7f31473 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -112,7 +112,8 @@ vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
 vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
 vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
 
-vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/early_sha1.o $(obj)/early_sha256.o
+vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/early_sha1.o $(obj)/early_sha256.o \
+	$(obj)/sl_main.o $(obj)/sl_stub.o
 
 $(obj)/vmlinux: $(vmlinux-objs-y) FORCE
 	$(call if_changed,ld)
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 03c4328..d079d8d 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -492,6 +492,17 @@ trampoline_return:
 	pushq	$0
 	popfq
 
+#ifdef CONFIG_SECURE_LAUNCH
+	pushq	%rsi
+
+	/* Ensure the relocation region coverd by a PMR */
+	movq	%rbx, %rdi
+	movl	$(_bss - startup_32), %esi
+	callq	sl_check_region
+
+	popq	%rsi
+#endif
+
 /*
  * Copy the compressed kernel to the end of our buffer
  * where decompression in place becomes safe.
@@ -551,6 +562,32 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
 	shrq	$3, %rcx
 	rep	stosq
 
+#ifdef CONFIG_SECURE_LAUNCH
+	/*
+	 * Have to do the final early sl stub work in 64b area.
+	 *
+	 * *********** NOTE ***********
+	 *
+	 * Several boot params get used before we get a chance to measure
+	 * them in this call. This is a known issue and we currently don't
+	 * have a solution. The scratch field doesn't matter. There is no
+	 * obvious way to do anything about the use of kernel_alignment or
+	 * init_size though these seem low risk with all the PMR and overlap
+	 * checks in place.
+	 */
+	pushq	%rsi
+
+	movq	%rsi, %rdi
+	callq	sl_main
+
+	/* Ensure the decompression location is coverd by a PMR */
+	movq	%rbp, %rdi
+	movq	output_len(%rip), %rsi
+	callq	sl_check_region
+
+	popq	%rsi
+#endif
+
 	pushq	%rsi
 	call	load_stage2_idt
 
diff --git a/arch/x86/boot/compressed/kernel_info.S b/arch/x86/boot/compressed/kernel_info.S
index c18f071..e199b87 100644
--- a/arch/x86/boot/compressed/kernel_info.S
+++ b/arch/x86/boot/compressed/kernel_info.S
@@ -28,6 +28,40 @@ SYM_DATA_START(kernel_info)
 	/* Maximal allowed type for setup_data and setup_indirect structs. */
 	.long	SETUP_TYPE_MAX
 
+	/* Offset to the MLE header structure */
+#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
+	.long	rva(mle_header)
+#else
+	.long	0
+#endif
+
 kernel_info_var_len_data:
 	/* Empty for time being... */
 SYM_DATA_END_LABEL(kernel_info, SYM_L_LOCAL, kernel_info_end)
+
+#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
+	/*
+	 * The MLE Header per the TXT Specification, section 2.1
+	 * MLE capabilities, see table 4. Capabilities set:
+	 * bit 0: Support for GETSEC[WAKEUP] for RLP wakeup
+	 * bit 1: Support for RLP wakeup using MONITOR address
+	 * bit 2: The ECX register will contain the pointer to the MLE page table
+	 * bit 5: TPM 1.2 family: Details/authorities PCR usage support
+	 * bit 9: Supported format of TPM 2.0 event log - TCG compliant
+	 */
+SYM_DATA_START(mle_header)
+	.long	0x9082ac5a  /* UUID0 */
+	.long	0x74a7476f  /* UUID1 */
+	.long	0xa2555c0f  /* UUID2 */
+	.long	0x42b651cb  /* UUID3 */
+	.long	0x00000034  /* MLE header size */
+	.long	0x00020002  /* MLE version 2.2 */
+	.long	rva(sl_stub_entry) /* Linear entry point of MLE (virt. address) */
+	.long	0x00000000  /* First valid page of MLE */
+	.long	0x00000000  /* Offset within binary of first byte of MLE */
+	.long	rva(_edata) /* Offset within binary of last byte + 1 of MLE */
+	.long	0x00000227  /* Bit vector of MLE-supported capabilities */
+	.long	0x00000000  /* Starting linear address of command line (unused) */
+	.long	0x00000000  /* Ending linear address of command line (unused) */
+SYM_DATA_END(mle_header)
+#endif
diff --git a/arch/x86/boot/compressed/sl_main.c b/arch/x86/boot/compressed/sl_main.c
new file mode 100644
index 0000000..23d7722
--- /dev/null
+++ b/arch/x86/boot/compressed/sl_main.c
@@ -0,0 +1,599 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Secure Launch early measurement and validation routines.
+ *
+ * Copyright (c) 2022, Oracle and/or its affiliates.
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/boot.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/processor-flags.h>
+#include <asm/asm-offsets.h>
+#include <asm/bootparam.h>
+#include <asm/bootparam_utils.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
+#include <crypto/sha1.h>
+#include <crypto/sha2.h>
+
+#include "early_sha1.h"
+
+#define CAPS_VARIABLE_MTRR_COUNT_MASK	0xff
+
+#define SL_TPM12_LOG		1
+#define SL_TPM20_LOG		2
+
+#define SL_TPM20_MAX_ALGS	2
+
+#define SL_MAX_EVENT_DATA	64
+#define SL_TPM12_LOG_SIZE	(sizeof(struct tcg_pcr_event) + \
+				SL_MAX_EVENT_DATA)
+#define SL_TPM20_LOG_SIZE	(sizeof(struct tcg_pcr_event2_head) + \
+				SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + \
+				sizeof(struct tcg_event_field) + \
+				SL_MAX_EVENT_DATA)
+
+static void *evtlog_base;
+static u32 evtlog_size;
+static struct txt_heap_event_log_pointer2_1_element *log20_elem;
+static u32 tpm_log_ver = SL_TPM12_LOG;
+struct tcg_efi_specid_event_algs tpm_algs[SL_TPM20_MAX_ALGS] = {0};
+
+extern u32 sl_cpu_type;
+extern u32 sl_mle_start;
+extern struct boot_params *boot_params;
+
+static u64 sl_txt_read(u32 reg)
+{
+	return readq((void *)(u64)(TXT_PRIV_CONFIG_REGS_BASE + reg));
+}
+
+static void sl_txt_write(u32 reg, u64 val)
+{
+	writeq(val, (void *)(u64)(TXT_PRIV_CONFIG_REGS_BASE + reg));
+}
+
+static void __noreturn sl_txt_reset(u64 error)
+{
+	/* Reading the E2STS register acts as a barrier for TXT registers */
+	sl_txt_write(TXT_CR_ERRORCODE, error);
+	sl_txt_read(TXT_CR_E2STS);
+	sl_txt_write(TXT_CR_CMD_UNLOCK_MEM_CONFIG, 1);
+	sl_txt_read(TXT_CR_E2STS);
+	sl_txt_write(TXT_CR_CMD_RESET, 1);
+
+	for ( ; ; )
+		asm volatile ("hlt");
+
+	unreachable();
+}
+
+static u64 sl_rdmsr(u32 reg)
+{
+	u64 lo, hi;
+
+	asm volatile ("rdmsr" : "=a" (lo), "=d" (hi) : "c" (reg));
+
+	return (hi << 32) | lo;
+}
+
+static struct slr_table *sl_locate_and_validate_slrt(void)
+{
+	struct txt_os_mle_data *os_mle_data;
+	struct slr_table *slrt;
+	void *txt_heap;
+
+	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+	os_mle_data = txt_os_mle_data_start(txt_heap);
+
+	if (!os_mle_data->slrt)
+		sl_txt_reset(SL_ERROR_INVALID_SLRT);
+
+	slrt = (struct slr_table *)os_mle_data->slrt;
+
+	if (slrt->magic != SLR_TABLE_MAGIC)
+		sl_txt_reset(SL_ERROR_INVALID_SLRT);
+
+	if (slrt->architecture != SLR_INTEL_TXT)
+		sl_txt_reset(SL_ERROR_INVALID_SLRT);
+
+	return slrt;
+}
+
+static void sl_check_pmr_coverage(void *base, u32 size, bool allow_hi)
+{
+	struct txt_os_sinit_data *os_sinit_data;
+	void *end = base + size;
+	void *txt_heap;
+
+	if (!(sl_cpu_type & SL_CPU_INTEL))
+		return;
+
+	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+	os_sinit_data = txt_os_sinit_data_start(txt_heap);
+
+	if ((end >= (void *)0x100000000ULL) &&
+	    (base < (void *)0x100000000ULL))
+		sl_txt_reset(SL_ERROR_REGION_STRADDLE_4GB);
+
+	/*
+	 * Note that the late stub code validates that the hi PMR covers
+	 * all memory above 4G. At this point the code can only check that
+	 * regions are within the hi PMR but that is sufficient.
+	 */
+	if ((end > (void *)0x100000000ULL) &&
+	    (base >= (void *)0x100000000ULL)) {
+		if (allow_hi) {
+			if (end >= (void *)(os_sinit_data->vtd_pmr_hi_base +
+					   os_sinit_data->vtd_pmr_hi_size))
+				sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
+		} else
+			sl_txt_reset(SL_ERROR_REGION_ABOVE_4GB);
+	}
+
+	if (end >= (void *)os_sinit_data->vtd_pmr_lo_size)
+		sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
+}
+
+/*
+ * Some MSRs are modified by the pre-launch code including the MTRRs.
+ * The early MLE code has to restore these values. This code validates
+ * the values after they are measured.
+ */
+static void sl_txt_validate_msrs(struct txt_os_mle_data *os_mle_data)
+{
+	struct slr_txt_mtrr_state *saved_bsp_mtrrs;
+	u64 mtrr_caps, mtrr_def_type, mtrr_var;
+	struct slr_entry_intel_info *txt_info;
+	u64 misc_en_msr;
+	u32 vcnt, i;
+
+	txt_info = (struct slr_entry_intel_info *)os_mle_data->txt_info;
+	saved_bsp_mtrrs = &(txt_info->saved_bsp_mtrrs);
+
+	mtrr_caps = sl_rdmsr(MSR_MTRRcap);
+	vcnt = (u32)(mtrr_caps & CAPS_VARIABLE_MTRR_COUNT_MASK);
+
+	if (saved_bsp_mtrrs->mtrr_vcnt > vcnt)
+		sl_txt_reset(SL_ERROR_MTRR_INV_VCNT);
+	if (saved_bsp_mtrrs->mtrr_vcnt > TXT_OS_MLE_MAX_VARIABLE_MTRRS)
+		sl_txt_reset(SL_ERROR_MTRR_INV_VCNT);
+
+	mtrr_def_type = sl_rdmsr(MSR_MTRRdefType);
+	if (saved_bsp_mtrrs->default_mem_type != mtrr_def_type)
+		sl_txt_reset(SL_ERROR_MTRR_INV_DEF_TYPE);
+
+	for (i = 0; i < saved_bsp_mtrrs->mtrr_vcnt; i++) {
+		mtrr_var = sl_rdmsr(MTRRphysBase_MSR(i));
+		if (saved_bsp_mtrrs->mtrr_pair[i].mtrr_physbase != mtrr_var)
+			sl_txt_reset(SL_ERROR_MTRR_INV_BASE);
+		mtrr_var = sl_rdmsr(MTRRphysMask_MSR(i));
+		if (saved_bsp_mtrrs->mtrr_pair[i].mtrr_physmask != mtrr_var)
+			sl_txt_reset(SL_ERROR_MTRR_INV_MASK);
+	}
+
+	misc_en_msr = sl_rdmsr(MSR_IA32_MISC_ENABLE);
+	if (txt_info->saved_misc_enable_msr != misc_en_msr)
+		sl_txt_reset(SL_ERROR_MSR_INV_MISC_EN);
+}
+
+static void sl_find_event_log(struct slr_table *slrt)
+{
+	struct txt_os_sinit_data *os_sinit_data;
+	struct slr_entry_log_info *log_info;
+	void *txt_heap;
+
+	log_info = (struct slr_entry_log_info *)
+			slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
+	if (!log_info)
+		sl_txt_reset(SL_ERROR_SLRT_MISSING_ENTRY);
+
+	evtlog_base = (void *)log_info->addr;
+	evtlog_size = log_info->size;
+
+	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+
+	/*
+	 * For TPM 2.0, the event log 2.1 extended data structure has to also
+	 * be located and fixed up.
+	 */
+	os_sinit_data = txt_os_sinit_data_start(txt_heap);
+
+	/*
+	 * Only support version 6 and later that properly handle the
+	 * list of ExtDataElements in the OS-SINIT structure.
+	 */
+	if (os_sinit_data->version < 6)
+		sl_txt_reset(SL_ERROR_OS_SINIT_BAD_VERSION);
+
+	/* Find the TPM2.0 logging extended heap element */
+	log20_elem = tpm20_find_log2_1_element(os_sinit_data);
+
+	/* If found, this implies TPM20 log and family */
+	if (log20_elem)
+		tpm_log_ver = SL_TPM20_LOG;
+}
+
+static void sl_validate_event_log_buffer(void)
+{
+	struct txt_os_sinit_data *os_sinit_data;
+	void *txt_heap, *txt_end;
+	void *mle_base, *mle_end;
+	void *evtlog_end;
+
+	if ((u64)evtlog_size > (LLONG_MAX - (u64)evtlog_base))
+		sl_txt_reset(SL_ERROR_INTEGER_OVERFLOW);
+	evtlog_end = evtlog_base + evtlog_size;
+
+	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+	txt_end = txt_heap + sl_txt_read(TXT_CR_HEAP_SIZE);
+	os_sinit_data = txt_os_sinit_data_start(txt_heap);
+
+	mle_base = (void *)(u64)sl_mle_start;
+	mle_end = mle_base + os_sinit_data->mle_size;
+
+	/*
+	 * This check is to ensure the event log buffer does not overlap with
+	 * the MLE image.
+	 */
+	if ((evtlog_base >= mle_end) &&
+	    (evtlog_end > mle_end))
+		goto pmr_check; /* above */
+
+	if ((evtlog_end <= mle_base) &&
+	    (evtlog_base < mle_base))
+		goto pmr_check; /* below */
+
+	sl_txt_reset(SL_ERROR_MLE_BUFFER_OVERLAP);
+
+pmr_check:
+	/*
+	 * The TXT heap is protected by the DPR. If the TPM event log is
+	 * inside the TXT heap, there is no need for a PMR check.
+	 */
+	if ((evtlog_base > txt_heap) &&
+	    (evtlog_end < txt_end))
+		return;
+
+	sl_check_pmr_coverage(evtlog_base, evtlog_size, true);
+}
+
+static void sl_find_event_log_algorithms(void)
+{
+	struct tcg_efi_specid_event_head *efi_head =
+		(struct tcg_efi_specid_event_head *)(evtlog_base +
+					log20_elem->first_record_offset +
+					sizeof(struct tcg_pcr_event));
+
+	if (efi_head->num_algs == 0 || efi_head->num_algs > 2)
+		sl_txt_reset(SL_ERROR_TPM_NUMBER_ALGS);
+
+	memcpy(&tpm_algs[0], &efi_head->digest_sizes[0],
+	       sizeof(struct tcg_efi_specid_event_algs) * efi_head->num_algs);
+}
+
+static void sl_tpm12_log_event(u32 pcr, u32 event_type,
+			       const u8 *data, u32 length,
+			       const u8 *event_data, u32 event_size)
+{
+	u8 sha1_hash[SHA1_DIGEST_SIZE] = {0};
+	u8 log_buf[SL_TPM12_LOG_SIZE] = {0};
+	struct tcg_pcr_event *pcr_event;
+	struct sha1_state sctx = {0};
+	u32 total_size;
+
+	pcr_event = (struct tcg_pcr_event *)log_buf;
+	pcr_event->pcr_idx = pcr;
+	pcr_event->event_type = event_type;
+	if (length > 0) {
+		early_sha1_init(&sctx);
+		early_sha1_update(&sctx, data, length);
+		early_sha1_final(&sctx, &sha1_hash[0]);
+		memcpy(&pcr_event->digest[0], &sha1_hash[0], SHA1_DIGEST_SIZE);
+	}
+	pcr_event->event_size = event_size;
+	if (event_size > 0)
+		memcpy((u8 *)pcr_event + sizeof(struct tcg_pcr_event),
+		       event_data, event_size);
+
+	total_size = sizeof(struct tcg_pcr_event) + event_size;
+
+	if (tpm12_log_event(evtlog_base, evtlog_size, total_size, pcr_event))
+		sl_txt_reset(SL_ERROR_TPM_LOGGING_FAILED);
+}
+
+static void sl_tpm20_log_event(u32 pcr, u32 event_type,
+			       const u8 *data, u32 length,
+			       const u8 *event_data, u32 event_size)
+{
+	u8 sha256_hash[SHA256_DIGEST_SIZE] = {0};
+	u8 sha1_hash[SHA1_DIGEST_SIZE] = {0};
+	u8 log_buf[SL_TPM20_LOG_SIZE] = {0};
+	struct sha256_state sctx256 = {0};
+	struct tcg_pcr_event2_head *head;
+	struct tcg_event_field *event;
+	struct sha1_state sctx1 = {0};
+	u32 total_size;
+	u16 *alg_ptr;
+	u8 *dgst_ptr;
+
+	head = (struct tcg_pcr_event2_head *)log_buf;
+	head->pcr_idx = pcr;
+	head->event_type = event_type;
+	total_size = sizeof(struct tcg_pcr_event2_head);
+	alg_ptr = (u16 *)(log_buf + sizeof(struct tcg_pcr_event2_head));
+
+	for ( ; head->count < 2; head->count++) {
+		if (!tpm_algs[head->count].alg_id)
+			break;
+
+		*alg_ptr = tpm_algs[head->count].alg_id;
+		dgst_ptr = (u8 *)alg_ptr + sizeof(u16);
+
+		if (tpm_algs[head->count].alg_id == TPM_ALG_SHA256 &&
+		    length) {
+			sha256_init(&sctx256);
+			sha256_update(&sctx256, data, length);
+			sha256_final(&sctx256, &sha256_hash[0]);
+		} else if (tpm_algs[head->count].alg_id == TPM_ALG_SHA1 &&
+			   length) {
+			early_sha1_init(&sctx1);
+			early_sha1_update(&sctx1, data, length);
+			early_sha1_final(&sctx1, &sha1_hash[0]);
+		}
+
+		if (tpm_algs[head->count].alg_id == TPM_ALG_SHA256) {
+			memcpy(dgst_ptr, &sha256_hash[0], SHA256_DIGEST_SIZE);
+			total_size += SHA256_DIGEST_SIZE + sizeof(u16);
+			alg_ptr = (u16 *)((u8 *)alg_ptr + SHA256_DIGEST_SIZE + sizeof(u16));
+		} else if (tpm_algs[head->count].alg_id == TPM_ALG_SHA1) {
+			memcpy(dgst_ptr, &sha1_hash[0], SHA1_DIGEST_SIZE);
+			total_size += SHA1_DIGEST_SIZE + sizeof(u16);
+			alg_ptr = (u16 *)((u8 *)alg_ptr + SHA1_DIGEST_SIZE + sizeof(u16));
+		} else
+			sl_txt_reset(SL_ERROR_TPM_UNKNOWN_DIGEST);
+	}
+
+	event = (struct tcg_event_field *)(log_buf + total_size);
+	event->event_size = event_size;
+	if (event_size > 0)
+		memcpy((u8 *)event + sizeof(struct tcg_event_field),
+		       event_data, event_size);
+	total_size += sizeof(struct tcg_event_field) + event_size;
+
+	if (tpm20_log_event(log20_elem, evtlog_base, evtlog_size,
+	    total_size, &log_buf[0]))
+		sl_txt_reset(SL_ERROR_TPM_LOGGING_FAILED);
+}
+
+static void sl_tpm_extend_evtlog(u32 pcr, u32 type,
+				 const u8 *data, u32 length, const char *desc)
+{
+	if (tpm_log_ver == SL_TPM20_LOG)
+		sl_tpm20_log_event(pcr, type, data, length,
+				   (const u8 *)desc, strlen(desc));
+	else
+		sl_tpm12_log_event(pcr, type, data, length,
+				   (const u8 *)desc, strlen(desc));
+}
+
+static struct setup_data *sl_handle_setup_data(struct setup_data *curr,
+					       struct slr_policy_entry *entry)
+{
+	struct setup_indirect *ind;
+	struct setup_data *next;
+
+	if (!curr)
+		return NULL;
+
+	next = (struct setup_data *)(unsigned long)curr->next;
+
+	/* SETUP_INDIRECT instances have to be handled differently */
+	if (curr->type == SETUP_INDIRECT) {
+		ind = (struct setup_indirect *)
+			((u8 *)curr + offsetof(struct setup_data, data));
+
+		sl_check_pmr_coverage((void *)ind->addr, ind->len, true);
+
+		sl_tpm_extend_evtlog(entry->pcr, TXT_EVTYPE_SLAUNCH,
+				     (void *)ind->addr, ind->len,
+				     entry->evt_info);
+
+		return next;
+	}
+
+	sl_check_pmr_coverage(((u8 *)curr) + sizeof(struct setup_data),
+			      curr->len, true);
+
+	sl_tpm_extend_evtlog(entry->pcr, TXT_EVTYPE_SLAUNCH,
+			     ((u8 *)curr) + sizeof(struct setup_data),
+			     curr->len,
+			     entry->evt_info);
+
+	return next;
+}
+
+static void sl_extend_setup_data(struct slr_policy_entry *entry)
+{
+	struct setup_data *data;
+
+	/*
+	 * Measuring the boot params measured the fixed e820 memory map.
+	 * Measure any setup_data entries including e820 extended entries.
+	 */
+	data = (struct setup_data *)(unsigned long)entry->entity;
+	while (data)
+		data = sl_handle_setup_data(data, entry);
+}
+
+static void sl_extend_slrt(struct slr_policy_entry *entry)
+{
+	struct slr_table *slrt = (struct slr_table *)entry->entity;
+	struct slr_entry_intel_info *intel_info;
+
+	/*
+	 * In revision one of the SLRT, the only table that needs to be
+	 * measured is the Intel info table. Everything else is meta-data,
+	 * addresses and sizes.
+	 */
+	if (slrt->revision == 1) {
+		intel_info = (struct slr_entry_intel_info *)
+				slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO);
+		if (!intel_info)
+			sl_txt_reset(SL_ERROR_SLRT_MISSING_ENTRY);
+
+		sl_tpm_extend_evtlog(entry->pcr, TXT_EVTYPE_SLAUNCH,
+				     (void *)entry->entity, entry->size,
+				     entry->evt_info);
+	}
+}
+
+static void sl_extend_txt_os2mle(struct slr_policy_entry *entry)
+{
+	struct txt_os_mle_data *os_mle_data;
+	void *txt_heap;
+
+	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+	os_mle_data = txt_os_mle_data_start(txt_heap);
+
+	/*
+	 * Version 1 of the OS-MLE heap structure has no fields to measure. It just
+	 * has addresses and sizes and a scratch buffer.
+	 */
+	if (os_mle_data->version == 1)
+		return;
+}
+
+static void sl_process_extend_policy(struct slr_table *slrt)
+{
+	struct slr_entry_policy *policy;
+	struct slr_policy_entry *entry;
+	u16 i = 0;
+
+	policy =(struct slr_entry_policy *)
+		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_ENTRY_POLICY);
+	if (!policy)
+		sl_txt_reset(SL_ERROR_SLRT_MISSING_ENTRY);
+
+	entry = (struct slr_policy_entry *)((u8 *)policy + sizeof(*policy));
+
+	for ( ; i < policy->nr_entries; i++, entry++) {
+		switch (entry->entity_type) {
+		case SLR_ET_SETUP_DATA:
+			sl_extend_setup_data(entry);
+			break;
+		case SLR_ET_SLRT:
+			sl_extend_slrt(entry);
+			break;
+		case SLR_ET_TXT_OS2MLE:
+			sl_extend_txt_os2mle(entry);
+			break;
+		case SLR_ET_UNUSED:
+			continue;
+		default:
+			sl_tpm_extend_evtlog(entry->pcr, TXT_EVTYPE_SLAUNCH,
+					     (void *)entry->entity, entry->size,
+					     entry->evt_info);
+		}
+	}
+}
+
+static void sl_process_extend_uefi_config(struct slr_table *slrt)
+{
+	struct slr_entry_uefi_config *uefi_config;
+	struct slr_uefi_cfg_entry *uefi_entry;
+	u64 i;
+
+	uefi_config =(struct slr_entry_uefi_config *)
+		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_UEFI_CONFIG);
+
+	/* Optionally here depending on how SL kernel was booted */
+	if (!uefi_config)
+		return;
+
+	uefi_entry = (struct slr_uefi_cfg_entry *)((u8 *)uefi_config + sizeof(*uefi_config));
+
+	for ( ; i < uefi_config->nr_entries; i++, uefi_entry++) {
+		sl_tpm_extend_evtlog(uefi_entry->pcr, TXT_EVTYPE_SLAUNCH,
+				     (void *)uefi_entry->cfg, uefi_entry->size,
+				     uefi_entry->evt_info);
+	}
+}
+
+asmlinkage __visible void sl_check_region(void *base, u32 size)
+{
+	sl_check_pmr_coverage(base, size, false);
+}
+
+asmlinkage __visible void sl_main(void *bootparams)
+{
+	struct boot_params *bp  = (struct boot_params *)bootparams;
+	struct txt_os_mle_data *os_mle_data;
+	struct slr_table *slrt;
+	void *txt_heap;
+
+	/*
+	 * Ensure loadflags do not indicate a secure launch was done
+	 * unless it really was.
+	 */
+	bp->hdr.loadflags &= ~SLAUNCH_FLAG;
+
+	/*
+	 * Currently only Intel TXT is supported for Secure Launch. Testing
+	 * this value also indicates that the kernel was booted successfully
+	 * through the Secure Launch entry point and is in SMX mode.
+	 */
+	if (!(sl_cpu_type & SL_CPU_INTEL))
+		return;
+
+	slrt = sl_locate_and_validate_slrt();
+
+	/* Locate the TPM event log. */
+	sl_find_event_log(slrt);
+
+	/* Validate the location of the event log buffer before using it */
+	sl_validate_event_log_buffer();
+
+	/*
+	 * Find the TPM hash algorithms used by the ACM and recorded in the
+	 * event log.
+	 */
+	if (tpm_log_ver == SL_TPM20_LOG)
+		sl_find_event_log_algorithms();
+
+	/*
+	 * Sanitize them before measuring. Set the SLAUNCH_FLAG early since if
+	 * anything fails, the system will reset anyway.
+	 */
+	boot_params = (struct boot_params *)bootparams;
+	sanitize_boot_params(boot_params);
+	bp->hdr.loadflags |= SLAUNCH_FLAG;
+
+	sl_check_pmr_coverage(bootparams, PAGE_SIZE, false);
+
+	/* Place event log SL specific tags before and after measurements */
+	sl_tpm_extend_evtlog(17, TXT_EVTYPE_SLAUNCH_START, NULL, 0, "");
+
+	/* Process all policy entries and extend the measurements to the evtlog */
+	sl_process_extend_policy(slrt);
+
+	/* Process all EFI config entries and extend the measurements to the evtlog */
+	sl_process_extend_uefi_config(slrt);
+
+	sl_tpm_extend_evtlog(17, TXT_EVTYPE_SLAUNCH_END, NULL, 0, "");
+
+	/* No PMR check is needed, the TXT heap is covered by the DPR */
+	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+	os_mle_data = txt_os_mle_data_start(txt_heap);
+
+	/*
+	 * Now that the OS-MLE data is measured, ensure the MTRR and
+	 * misc enable MSRs are what we expect.
+	 */
+	sl_txt_validate_msrs(os_mle_data);
+}
diff --git a/arch/x86/boot/compressed/sl_stub.S b/arch/x86/boot/compressed/sl_stub.S
new file mode 100644
index 0000000..2d8aa3a
--- /dev/null
+++ b/arch/x86/boot/compressed/sl_stub.S
@@ -0,0 +1,690 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Secure Launch protected mode entry point.
+ *
+ * Copyright (c) 2022, Oracle and/or its affiliates.
+ */
+	.code32
+	.text
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/msr.h>
+#include <asm/processor-flags.h>
+#include <asm/asm-offsets.h>
+#include <asm/bootparam.h>
+#include <asm/page_types.h>
+#include <asm/irq_vectors.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
+
+/* CPUID: leaf 1, ECX, SMX feature bit */
+#define X86_FEATURE_BIT_SMX	(1 << 6)
+
+/* Can't include apiddef.h in asm */
+#define XAPIC_ENABLE	(1 << 11)
+#define X2APIC_ENABLE	(1 << 10)
+
+/* Can't include traps.h in asm */
+#define X86_TRAP_NMI	2
+
+/* Can't include mtrr.h in asm */
+#define MTRRphysBase0	0x200
+
+#define IDT_VECTOR_LO_BITS	0
+#define IDT_VECTOR_HI_BITS	6
+
+/*
+ * See the comment in head_64.S for detailed informatoin on what this macro
+ * is used for.
+ */
+#define rva(X) ((X) - sl_stub_entry)
+
+/*
+ * The GETSEC op code is open coded because older versions of
+ * GCC do not support the getsec mnemonic.
+ */
+.macro GETSEC leaf
+	pushl	%ebx
+	xorl	%ebx, %ebx	/* Must be zero for SMCTRL */
+	movl	\leaf, %eax	/* Leaf function */
+	.byte 	0x0f, 0x37	/* GETSEC opcode */
+	popl	%ebx
+.endm
+
+.macro TXT_RESET error
+	/*
+	 * Set a sticky error value and reset. Note the movs to %eax act as
+	 * TXT register barriers.
+	 */
+	movl	\error, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_ERRORCODE)
+	movl	(TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_E2STS), %eax
+	movl	$1, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_CMD_NO_SECRETS)
+	movl	(TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_E2STS), %eax
+	movl	$1, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_CMD_UNLOCK_MEM_CONFIG)
+	movl	(TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_E2STS), %eax
+	movl	$1, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_CMD_RESET)
+1:
+	hlt
+	jmp	1b
+.endm
+
+	.code32
+SYM_FUNC_START(sl_stub_entry)
+	cli
+	cld
+
+	/*
+	 * On entry, %ebx has the entry abs offset to sl_stub_entry. This
+	 * will be correctly scaled using the rva macro and avoid causing
+	 * relocations. Only %cs and %ds segments are known good.
+	 */
+
+	/* Load GDT, set segment regs and lret to __SL32_CS */
+	leal	rva(sl_gdt_desc)(%ebx), %eax
+	addl	%eax, 2(%eax)
+	lgdt	(%eax)
+
+	movl	$(__SL32_DS), %eax
+	movw	%ax, %ds
+	movw	%ax, %es
+	movw	%ax, %fs
+	movw	%ax, %gs
+	movw	%ax, %ss
+
+	/*
+	 * Now that %ss is known good, take the first stack for the BSP. The
+	 * AP stacks are only used on Intel.
+	 */
+	leal	rva(sl_stacks_end)(%ebx), %esp
+
+	leal	rva(.Lsl_cs)(%ebx), %eax
+	pushl	$(__SL32_CS)
+	pushl	%eax
+	lret
+
+.Lsl_cs:
+	/* Save our base pointer reg and page table for MLE */
+	pushl	%ebx
+	pushl	%ecx
+
+	/* See if SMX feature is supported. */
+	movl	$1, %eax
+	cpuid
+	testl	$(X86_FEATURE_BIT_SMX), %ecx
+	jz	.Ldo_unknown_cpu
+
+	popl	%ecx
+	popl	%ebx
+
+	/* Know it is Intel */
+	movl	$(SL_CPU_INTEL), rva(sl_cpu_type)(%ebx)
+
+	/* Locate the base of the MLE using the page tables in %ecx */
+	call	sl_find_mle_base
+
+	/* Increment CPU count for BSP */
+	incl	rva(sl_txt_cpu_count)(%ebx)
+
+	/*
+	 * Enable SMI with GETSEC[SMCTRL] which were disabled by SENTER.
+	 * NMIs were also disabled by SENTER. Since there is no IDT for the BSP,
+	 * allow the mainline kernel re-enable them in the normal course of
+	 * booting.
+	 */
+	GETSEC	$(SMX_X86_GETSEC_SMCTRL)
+
+	/* Clear the TXT error registers for a clean start of day */
+	movl	$0, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_ERRORCODE)
+	movl	$0xffffffff, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_ESTS)
+
+	/* On Intel, the zero page address is passed in the TXT heap */
+	/* Read physical base of heap into EAX */
+	movl	(TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_HEAP_BASE), %eax
+	/* Read the size of the BIOS data into ECX (first 8 bytes) */
+	movl	(%eax), %ecx
+	/* Skip over BIOS data and size of OS to MLE data section */
+	leal	8(%eax, %ecx), %eax
+
+	/* Need to verify the values in the OS-MLE struct passed in */
+	call	sl_txt_verify_os_mle_struct
+
+	/*
+	 * Get the boot params address from the heap. Note %esi and %ebx MUST
+	 * be preserved across calls and operations.
+	 */
+	movl	SL_boot_params_addr(%eax), %esi
+
+	/* Save %ebx so the APs can find their way home */
+	movl	%ebx, (SL_mle_scratch + SL_SCRATCH_AP_EBX)(%eax)
+
+	/* Fetch the AP wake code block address from the heap */
+	movl	SL_ap_wake_block(%eax), %edi
+	movl	%edi, rva(sl_txt_ap_wake_block)(%ebx)
+
+	/* Store the offset in the AP wake block to the jmp address */
+	movl	$(sl_ap_jmp_offset - sl_txt_ap_wake_begin), \
+		(SL_mle_scratch + SL_SCRATCH_AP_JMP_OFFSET)(%eax)
+
+	/* %eax still is the base of the OS-MLE block, save it */
+	pushl	%eax
+
+	/* Relocate the AP wake code to the safe block */
+	call	sl_txt_reloc_ap_wake
+
+	/*
+	 * Wake up all APs that are blocked in the ACM and wait for them to
+	 * halt. This should be done before restoring the MTRRs so the ACM is
+	 * still properly in WB memory.
+	 */
+	call	sl_txt_wake_aps
+
+	/* Restore OS-MLE in %eax */
+	popl	%eax
+
+	/*
+	 * %edi is used by this routine to find the MTRRs which are in the SLRT
+	 * in the Intel info.
+	 */
+	movl	SL_txt_info(%eax), %edi
+	call	sl_txt_load_regs
+
+	jmp	.Lcpu_setup_done
+
+.Ldo_unknown_cpu:
+	/* Non-Intel CPUs are not yet supported */
+	ud2
+
+.Lcpu_setup_done:
+	/*
+	 * Don't enable MCE at this point. The kernel will enable
+	 * it on the BSP later when it is ready.
+	 */
+
+	/* Done, jump to normal 32b pm entry */
+	jmp	startup_32
+SYM_FUNC_END(sl_stub_entry)
+
+SYM_FUNC_START(sl_find_mle_base)
+	/* %ecx has PDPT, get first PD */
+	movl	(%ecx), %eax
+	andl	$(PAGE_MASK), %eax
+	/* Get first PT from first PDE */
+	movl	(%eax), %eax
+	andl	$(PAGE_MASK), %eax
+	/* Get MLE base from first PTE */
+	movl	(%eax), %eax
+	andl	$(PAGE_MASK), %eax
+
+	movl	%eax, rva(sl_mle_start)(%ebx)
+	ret
+SYM_FUNC_END(sl_find_mle_base)
+
+SYM_FUNC_START(sl_check_buffer_mle_overlap)
+	/* %ecx: buffer begin %edx: buffer end */
+	/* %ebx: MLE begin %edi: MLE end */
+
+	cmpl	%edi, %ecx
+	jb	.Lnext_check
+	cmpl	%edi, %edx
+	jbe	.Lnext_check
+	jmp	.Lvalid /* Buffer above MLE */
+
+.Lnext_check:
+	cmpl	%ebx, %edx
+	ja	.Linvalid
+	cmpl	%ebx, %ecx
+	jae	.Linvalid
+	jmp	.Lvalid /* Buffer below MLE */
+
+.Linvalid:
+	TXT_RESET $(SL_ERROR_MLE_BUFFER_OVERLAP)
+
+.Lvalid:
+	ret
+SYM_FUNC_END(sl_check_buffer_mle_overlap)
+
+SYM_FUNC_START(sl_txt_verify_os_mle_struct)
+	pushl	%ebx
+	/*
+	 * %eax points to the base of the OS-MLE struct. Need to also
+	 * read some values from the OS-SINIT struct too.
+	 */
+	movl	-8(%eax), %ecx
+	/* Skip over OS to MLE data section and size of OS-SINIT structure */
+	leal	(%eax, %ecx), %edx
+
+	/* Load MLE image base absolute offset */
+	movl	rva(sl_mle_start)(%ebx), %ebx
+
+	/* Verify the value of the low PMR base. It should always be 0. */
+	movl	SL_vtd_pmr_lo_base(%edx), %esi
+	cmpl	$0, %esi
+	jz	.Lvalid_pmr_base
+	TXT_RESET $(SL_ERROR_LO_PMR_BASE)
+
+.Lvalid_pmr_base:
+	/* Grab some values from OS-SINIT structure */
+	movl	SL_mle_size(%edx), %edi
+	addl	%ebx, %edi
+	jc	.Loverflow_detected
+	movl	SL_vtd_pmr_lo_size(%edx), %esi
+
+	/* Check the AP wake block */
+	movl	SL_ap_wake_block(%eax), %ecx
+	movl	SL_ap_wake_block_size(%eax), %edx
+	addl	%ecx, %edx
+	jc	.Loverflow_detected
+	call	sl_check_buffer_mle_overlap
+	cmpl	%esi, %edx
+	ja	.Lbuffer_beyond_pmr
+
+	/* Check the boot params */
+	movl	SL_boot_params_addr(%eax), %ecx
+	movl	$(PAGE_SIZE), %edx
+	addl	%ecx, %edx
+	jc	.Loverflow_detected
+	call	sl_check_buffer_mle_overlap
+	cmpl	%esi, %edx
+	ja	.Lbuffer_beyond_pmr
+
+	/* Check that the AP wake block is big enough */
+	cmpl	$(sl_txt_ap_wake_end - sl_txt_ap_wake_begin), \
+		SL_ap_wake_block_size(%eax)
+	jae	.Lwake_block_ok
+	TXT_RESET $(SL_ERROR_WAKE_BLOCK_TOO_SMALL)
+
+.Lwake_block_ok:
+	popl	%ebx
+	ret
+
+.Loverflow_detected:
+	TXT_RESET $(SL_ERROR_INTEGER_OVERFLOW)
+
+.Lbuffer_beyond_pmr:
+	TXT_RESET $(SL_ERROR_BUFFER_BEYOND_PMR)
+SYM_FUNC_END(sl_txt_verify_os_mle_struct)
+
+SYM_FUNC_START(sl_txt_ap_entry)
+	cli
+	cld
+	/*
+	 * The %cs and %ds segments are known good after waking the AP.
+	 * First order of business is to find where we are and
+	 * save it in %ebx.
+	 */
+
+	/* Read physical base of heap into EAX */
+	movl	(TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_HEAP_BASE), %eax
+	/* Read the size of the BIOS data into ECX (first 8 bytes) */
+	movl	(%eax), %ecx
+	/* Skip over BIOS data and size of OS to MLE data section */
+	leal	8(%eax, %ecx), %eax
+
+	/* Saved %ebx from the BSP and stash OS-MLE pointer */
+	movl	(SL_mle_scratch + SL_SCRATCH_AP_EBX)(%eax), %ebx
+
+	/* Save TXT info ptr in %edi for call to sl_txt_load_regs */
+	movl	SL_txt_info(%eax), %edi
+
+	/* Lock and get our stack index */
+	movl	$1, %ecx
+.Lspin:
+	xorl	%eax, %eax
+	lock cmpxchgl	%ecx, rva(sl_txt_spin_lock)(%ebx)
+	pause
+	jnz	.Lspin
+
+	/* Increment the stack index and use the next value inside lock */
+	incl	rva(sl_txt_stack_index)(%ebx)
+	movl	rva(sl_txt_stack_index)(%ebx), %eax
+
+	/* Unlock */
+	movl	$0, rva(sl_txt_spin_lock)(%ebx)
+
+	/* Location of the relocated AP wake block */
+	movl	rva(sl_txt_ap_wake_block)(%ebx), %ecx
+
+	/* Load reloc GDT, set segment regs and lret to __SL32_CS */
+	lgdt	(sl_ap_gdt_desc - sl_txt_ap_wake_begin)(%ecx)
+
+	movl	$(__SL32_DS), %edx
+	movw	%dx, %ds
+	movw	%dx, %es
+	movw	%dx, %fs
+	movw	%dx, %gs
+	movw	%dx, %ss
+
+	/* Load our reloc AP stack */
+	movl	$(TXT_BOOT_STACK_SIZE), %edx
+	mull	%edx
+	leal	(sl_stacks_end - sl_txt_ap_wake_begin)(%ecx), %esp
+	subl	%eax, %esp
+
+	/* Switch to AP code segment */
+	leal	rva(.Lsl_ap_cs)(%ebx), %eax
+	pushl	$(__SL32_CS)
+	pushl	%eax
+	lret
+
+.Lsl_ap_cs:
+	/* Load the relocated AP IDT */
+	lidt	(sl_ap_idt_desc - sl_txt_ap_wake_begin)(%ecx)
+
+	/* Fixup MTRRs and misc enable MSR on APs too */
+	call	sl_txt_load_regs
+
+	/* Enable SMI with GETSEC[SMCTRL] */
+	GETSEC $(SMX_X86_GETSEC_SMCTRL)
+
+	/* IRET-to-self can be used to enable NMIs which SENTER disabled */
+	leal	rva(.Lnmi_enabled_ap)(%ebx), %eax
+	pushfl
+	pushl	$(__SL32_CS)
+	pushl	%eax
+	iret
+
+.Lnmi_enabled_ap:
+	/* Put APs in X2APIC mode like the BSP */
+	movl	$(MSR_IA32_APICBASE), %ecx
+	rdmsr
+	orl	$(XAPIC_ENABLE | X2APIC_ENABLE), %eax
+	wrmsr
+
+	/*
+	 * Basically done, increment the CPU count and jump off to the AP
+	 * wake block to wait.
+	 */
+	lock incl	rva(sl_txt_cpu_count)(%ebx)
+
+	movl	rva(sl_txt_ap_wake_block)(%ebx), %eax
+	jmp	*%eax
+SYM_FUNC_END(sl_txt_ap_entry)
+
+SYM_FUNC_START(sl_txt_reloc_ap_wake)
+	/* Save boot params register */
+	pushl	%esi
+
+	movl	rva(sl_txt_ap_wake_block)(%ebx), %edi
+
+	/* Fixup AP IDT and GDT descriptor before relocating */
+	leal	rva(sl_ap_idt_desc)(%ebx), %eax
+	addl	%edi, 2(%eax)
+	leal	rva(sl_ap_gdt_desc)(%ebx), %eax
+	addl	%edi, 2(%eax)
+
+	/*
+	 * Copy the AP wake code and AP GDT/IDT to the protected wake block
+	 * provided by the loader. Destination already in %edi.
+	 */
+	movl	$(sl_txt_ap_wake_end - sl_txt_ap_wake_begin), %ecx
+	leal	rva(sl_txt_ap_wake_begin)(%ebx), %esi
+	rep movsb
+
+	/* Setup the IDT for the APs to use in the relocation block */
+	movl	rva(sl_txt_ap_wake_block)(%ebx), %ecx
+	addl	$(sl_ap_idt - sl_txt_ap_wake_begin), %ecx
+	xorl	%edx, %edx
+
+	/* Form the default reset vector relocation address */
+	movl	rva(sl_txt_ap_wake_block)(%ebx), %esi
+	addl	$(sl_txt_int_reset - sl_txt_ap_wake_begin), %esi
+
+1:
+	cmpw	$(NR_VECTORS), %dx
+	jz	.Lap_idt_done
+
+	cmpw	$(X86_TRAP_NMI), %dx
+	jz	2f
+
+	/* Load all other fixed vectors with reset handler */
+	movl	%esi, %eax
+	movw	%ax, (IDT_VECTOR_LO_BITS)(%ecx)
+	shrl	$16, %eax
+	movw	%ax, (IDT_VECTOR_HI_BITS)(%ecx)
+	jmp	3f
+
+2:
+	/* Load single wake NMI IPI vector at the relocation address */
+	movl	rva(sl_txt_ap_wake_block)(%ebx), %eax
+	addl	$(sl_txt_int_ipi_wake - sl_txt_ap_wake_begin), %eax
+	movw	%ax, (IDT_VECTOR_LO_BITS)(%ecx)
+	shrl	$16, %eax
+	movw	%ax, (IDT_VECTOR_HI_BITS)(%ecx)
+
+3:
+	incw	%dx
+	addl	$8, %ecx
+	jmp	1b
+
+.Lap_idt_done:
+	popl	%esi
+	ret
+SYM_FUNC_END(sl_txt_reloc_ap_wake)
+
+SYM_FUNC_START(sl_txt_load_regs)
+	/* Save base pointer register */
+	pushl	%ebx
+
+	/*
+	 * On Intel, the original variable MTRRs and Misc Enable MSR are
+	 * restored on the BSP at early boot. Each AP will also restore
+	 * its MTRRs and Misc Enable MSR.
+	 */
+	pushl	%edi
+	addl	$(SL_saved_bsp_mtrrs), %edi
+	movl	(%edi), %ebx
+	pushl	%ebx /* default_mem_type lo */
+	addl	$4, %edi
+	movl	(%edi), %ebx
+	pushl	%ebx /* default_mem_type hi */
+	addl	$4, %edi
+	movl	(%edi), %ebx /* mtrr_vcnt lo, don't care about hi part */
+	addl	$8, %edi /* now at MTRR pair array */
+	/* Write the variable MTRRs */
+	movl	$(MTRRphysBase0), %ecx
+1:
+	cmpl	$0, %ebx
+	jz	2f
+
+	movl	(%edi), %eax /* MTRRphysBaseX lo */
+	addl	$4, %edi
+	movl	(%edi), %edx /* MTRRphysBaseX hi */
+	wrmsr
+	addl	$4, %edi
+	incl	%ecx
+	movl	(%edi), %eax /* MTRRphysMaskX lo */
+	addl	$4, %edi
+	movl	(%edi), %edx /* MTRRphysMaskX hi */
+	wrmsr
+	addl	$4, %edi
+	incl	%ecx
+
+	decl	%ebx
+	jmp	1b
+2:
+	/* Write the default MTRR register */
+	popl	%edx
+	popl	%eax
+	movl	$(MSR_MTRRdefType), %ecx
+	wrmsr
+
+	/* Return to beginning and write the misc enable msr */
+	popl	%edi
+	addl	$(SL_saved_misc_enable_msr), %edi
+	movl	(%edi), %eax /* saved_misc_enable_msr lo */
+	addl	$4, %edi
+	movl	(%edi), %edx /* saved_misc_enable_msr hi */
+	movl	$(MSR_IA32_MISC_ENABLE), %ecx
+	wrmsr
+
+	popl	%ebx
+	ret
+SYM_FUNC_END(sl_txt_load_regs)
+
+SYM_FUNC_START(sl_txt_wake_aps)
+	/* Save boot params register */
+	pushl	%esi
+
+	/* First setup the MLE join structure and load it into TXT reg */
+	leal	rva(sl_gdt)(%ebx), %eax
+	leal	rva(sl_txt_ap_entry)(%ebx), %ecx
+	leal	rva(sl_smx_rlp_mle_join)(%ebx), %edx
+	movl	%eax, SL_rlp_gdt_base(%edx)
+	movl	%ecx, SL_rlp_entry_point(%edx)
+	movl	%edx, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_MLE_JOIN)
+
+	/* Another TXT heap walk to find various values needed to wake APs */
+	movl	(TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_HEAP_BASE), %eax
+	/* At BIOS data size, find the number of logical processors */
+	movl	(SL_num_logical_procs + 8)(%eax), %edx
+	/* Skip over BIOS data */
+	movl	(%eax), %ecx
+	addl	%ecx, %eax
+	/* Skip over OS to MLE */
+	movl	(%eax), %ecx
+	addl	%ecx, %eax
+	/* At OS-SNIT size, get capabilities to know how to wake up the APs */
+	movl	(SL_capabilities + 8)(%eax), %esi
+	/* Skip over OS to SNIT */
+	movl	(%eax), %ecx
+	addl	%ecx, %eax
+	/* At SINIT-MLE size, get the AP wake MONITOR address */
+	movl	(SL_rlp_wakeup_addr + 8)(%eax), %edi
+
+	/* Determine how to wake up the APs */
+	testl	$(1 << TXT_SINIT_MLE_CAP_WAKE_MONITOR), %esi
+	jz	.Lwake_getsec
+
+	/* Wake using MWAIT MONITOR */
+	movl	$1, (%edi)
+	jmp	.Laps_awake
+
+.Lwake_getsec:
+	/* Wake using GETSEC(WAKEUP) */
+	GETSEC	$(SMX_X86_GETSEC_WAKEUP)
+
+.Laps_awake:
+	/*
+	 * All of the APs are woken up and rendesvous in the relocated wake
+	 * block starting at sl_txt_ap_wake_begin. Wait for all of them to
+	 * halt.
+	 */
+	pause
+	cmpl	rva(sl_txt_cpu_count)(%ebx), %edx
+	jne	.Laps_awake
+
+	popl	%esi
+	ret
+SYM_FUNC_END(sl_txt_wake_aps)
+
+/* This is the beginning of the relocated AP wake code block */
+	.global sl_txt_ap_wake_begin
+sl_txt_ap_wake_begin:
+
+	/*
+	 * Wait for NMI IPI in the relocated AP wake block which was provided
+	 * and protected in the memory map by the prelaunch code. Leave all
+	 * other interrupts masked since we do not expect anything but an NMI.
+	 */
+	xorl	%edx, %edx
+
+1:
+	hlt
+	testl	%edx, %edx
+	jz	1b
+
+	/*
+	 * This is the long absolute jump to the 32b Secure Launch protected
+	 * mode stub code in the rmpiggy. The jump address will be fixed in
+	 * the SMP boot code when the first AP is brought up. This whole area
+	 * is provided and protected in the memory map by the prelaunch code.
+	 */
+	.byte	0xea
+sl_ap_jmp_offset:
+	.long	0x00000000
+	.word	__SL32_CS
+
+SYM_FUNC_START(sl_txt_int_ipi_wake)
+	movl	$1, %edx
+
+	/* NMI context, just IRET */
+	iret
+SYM_FUNC_END(sl_txt_int_ipi_wake)
+
+SYM_FUNC_START(sl_txt_int_reset)
+	TXT_RESET $(SL_ERROR_INV_AP_INTERRUPT)
+SYM_FUNC_END(sl_txt_int_reset)
+
+	.balign 8
+SYM_DATA_START_LOCAL(sl_ap_idt_desc)
+	.word	sl_ap_idt_end - sl_ap_idt - 1		/* Limit */
+	.long	sl_ap_idt - sl_txt_ap_wake_begin	/* Base */
+SYM_DATA_END_LABEL(sl_ap_idt_desc, SYM_L_LOCAL, sl_ap_idt_desc_end)
+
+	.balign 8
+SYM_DATA_START_LOCAL(sl_ap_idt)
+	.rept	NR_VECTORS
+	.word	0x0000		/* Offset 15 to 0 */
+	.word	__SL32_CS	/* Segment selector */
+	.word	0x8e00		/* Present, DPL=0, 32b Vector, Interrupt */
+	.word	0x0000		/* Offset 31 to 16 */
+	.endr
+SYM_DATA_END_LABEL(sl_ap_idt, SYM_L_LOCAL, sl_ap_idt_end)
+
+	.balign 8
+SYM_DATA_START_LOCAL(sl_ap_gdt_desc)
+	.word	sl_ap_gdt_end - sl_ap_gdt - 1
+	.long	sl_ap_gdt - sl_txt_ap_wake_begin
+SYM_DATA_END_LABEL(sl_ap_gdt_desc, SYM_L_LOCAL, sl_ap_gdt_desc_end)
+
+	.balign	8
+SYM_DATA_START_LOCAL(sl_ap_gdt)
+	.quad	0x0000000000000000	/* NULL */
+	.quad	0x00cf9a000000ffff	/* __SL32_CS */
+	.quad	0x00cf92000000ffff	/* __SL32_DS */
+SYM_DATA_END_LABEL(sl_ap_gdt, SYM_L_LOCAL, sl_ap_gdt_end)
+
+	/* Small stacks for BSP and APs to work with */
+	.balign 4
+SYM_DATA_START_LOCAL(sl_stacks)
+	.fill (TXT_MAX_CPUS * TXT_BOOT_STACK_SIZE), 1, 0
+SYM_DATA_END_LABEL(sl_stacks, SYM_L_LOCAL, sl_stacks_end)
+
+/* This is the end of the relocated AP wake code block */
+	.global sl_txt_ap_wake_end
+sl_txt_ap_wake_end:
+
+	.data
+	.balign 8
+SYM_DATA_START_LOCAL(sl_gdt_desc)
+	.word	sl_gdt_end - sl_gdt - 1
+	.long	sl_gdt - sl_gdt_desc
+SYM_DATA_END_LABEL(sl_gdt_desc, SYM_L_LOCAL, sl_gdt_desc_end)
+
+	.balign	8
+SYM_DATA_START_LOCAL(sl_gdt)
+	.quad	0x0000000000000000	/* NULL */
+	.quad	0x00cf9a000000ffff	/* __SL32_CS */
+	.quad	0x00cf92000000ffff	/* __SL32_DS */
+SYM_DATA_END_LABEL(sl_gdt, SYM_L_LOCAL, sl_gdt_end)
+
+	.balign 8
+SYM_DATA_START_LOCAL(sl_smx_rlp_mle_join)
+	.long	sl_gdt_end - sl_gdt - 1	/* GDT limit */
+	.long	0x00000000		/* GDT base */
+	.long	__SL32_CS	/* Seg Sel - CS (DS, ES, SS = seg_sel+8) */
+	.long	0x00000000	/* Entry point physical address */
+SYM_DATA_END(sl_smx_rlp_mle_join)
+
+SYM_DATA(sl_cpu_type, .long 0x00000000)
+
+SYM_DATA(sl_mle_start, .long 0x00000000)
+
+SYM_DATA_LOCAL(sl_txt_spin_lock, .long 0x00000000)
+
+SYM_DATA_LOCAL(sl_txt_stack_index, .long 0x00000000)
+
+SYM_DATA_LOCAL(sl_txt_cpu_count, .long 0x00000000)
+
+SYM_DATA_LOCAL(sl_txt_ap_wake_block, .long 0x00000000)
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index 01d19fc..74e3e7df 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -26,6 +26,7 @@
 /* loadflags */
 #define LOADED_HIGH	(1<<0)
 #define KASLR_FLAG	(1<<1)
+#define SLAUNCH_FLAG	(1<<2)
 #define QUIET_FLAG	(1<<5)
 #define KEEP_SEGMENTS	(1<<6)
 #define CAN_USE_HEAP	(1<<7)
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index dc35763..960d471 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -13,6 +13,8 @@
 #include <linux/hardirq.h>
 #include <linux/suspend.h>
 #include <linux/kbuild.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
 #include <asm/processor.h>
 #include <asm/thread_info.h>
 #include <asm/sigframe.h>
@@ -127,4 +129,22 @@ static void __used common(void)
 	OFFSET(ARIA_CTX_rounds, aria_ctx, rounds);
 #endif
 
+#ifdef CONFIG_SECURE_LAUNCH
+	BLANK();
+	OFFSET(SL_txt_info, txt_os_mle_data, txt_info);
+	OFFSET(SL_mle_scratch, txt_os_mle_data, mle_scratch);
+	OFFSET(SL_boot_params_addr, txt_os_mle_data, boot_params_addr);
+	OFFSET(SL_ap_wake_block, txt_os_mle_data, ap_wake_block);
+	OFFSET(SL_ap_wake_block_size, txt_os_mle_data, ap_wake_block_size);
+	OFFSET(SL_saved_misc_enable_msr, slr_entry_intel_info, saved_misc_enable_msr);
+	OFFSET(SL_saved_bsp_mtrrs, slr_entry_intel_info, saved_bsp_mtrrs);
+	OFFSET(SL_num_logical_procs, txt_bios_data, num_logical_procs);
+	OFFSET(SL_capabilities, txt_os_sinit_data, capabilities);
+	OFFSET(SL_mle_size, txt_os_sinit_data, mle_size);
+	OFFSET(SL_vtd_pmr_lo_base, txt_os_sinit_data, vtd_pmr_lo_base);
+	OFFSET(SL_vtd_pmr_lo_size, txt_os_sinit_data, vtd_pmr_lo_size);
+	OFFSET(SL_rlp_wakeup_addr, txt_sinit_mle_data, rlp_wakeup_addr);
+	OFFSET(SL_rlp_gdt_base, smx_rlp_mle_join, rlp_gdt_base);
+	OFFSET(SL_rlp_entry_point, smx_rlp_mle_join, rlp_entry_point);
+#endif
 }
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

The routine slaunch_setup is called out of the x86 specific setup_arch
routine during early kernel boot. After determining what platform is
present, various operations specific to that platform occur. This
includes finalizing setting for the platform late launch and verifying
that memory protections are in place.

For TXT, this code also reserves the original compressed kernel setup
area where the APs were left looping so that this memory cannot be used.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/kernel/Makefile   |   1 +
 arch/x86/kernel/setup.c    |   3 +
 arch/x86/kernel/slaunch.c  | 497 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/iommu/intel/dmar.c |   4 +
 4 files changed, 505 insertions(+)
 create mode 100644 arch/x86/kernel/slaunch.c

diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index dd61752..3d2a33e 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_X86_32)		+= tls.o
 obj-$(CONFIG_IA32_EMULATION)	+= tls.o
 obj-y				+= step.o
 obj-$(CONFIG_INTEL_TXT)		+= tboot.o
+obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
 obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
 obj-y				+= stacktrace.o
 obj-y				+= cpu/
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 16babff..592c09e 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -21,6 +21,7 @@
 #include <linux/root_dev.h>
 #include <linux/hugetlb.h>
 #include <linux/tboot.h>
+#include <linux/slaunch.h>
 #include <linux/usb/xhci-dbgp.h>
 #include <linux/static_call.h>
 #include <linux/swiotlb.h>
@@ -1063,6 +1064,8 @@ void __init setup_arch(char **cmdline_p)
 	early_gart_iommu_check();
 #endif
 
+	slaunch_setup_txt();
+
 	/*
 	 * partially used pages are not usable - thus
 	 * we are rounding upwards:
diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
new file mode 100644
index 0000000..7dba088
--- /dev/null
+++ b/arch/x86/kernel/slaunch.c
@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Secure Launch late validation/setup and finalization support.
+ *
+ * Copyright (c) 2022, Oracle and/or its affiliates.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/security.h>
+#include <linux/memblock.h>
+#include <asm/segment.h>
+#include <asm/sections.h>
+#include <asm/tlbflush.h>
+#include <asm/e820/api.h>
+#include <asm/setup.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
+
+static u32 sl_flags;
+static struct sl_ap_wake_info ap_wake_info;
+static u64 evtlog_addr;
+static u32 evtlog_size;
+static u64 vtd_pmr_lo_size;
+
+/* This should be plenty of room */
+static u8 txt_dmar[PAGE_SIZE] __aligned(16);
+
+u32 slaunch_get_flags(void)
+{
+	return sl_flags;
+}
+EXPORT_SYMBOL(slaunch_get_flags);
+
+struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
+{
+	return &ap_wake_info;
+}
+
+struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
+{
+	/* The DMAR is only stashed and provided via TXT on Intel systems */
+	if (memcmp(txt_dmar, "DMAR", 4))
+		return dmar;
+
+	return (struct acpi_table_header *)(&txt_dmar[0]);
+}
+
+void __noreturn slaunch_txt_reset(void __iomem *txt,
+				  const char *msg, u64 error)
+{
+	u64 one = 1, val;
+
+	pr_err("%s", msg);
+
+	/*
+	 * This performs a TXT reset with a sticky error code. The reads of
+	 * TXT_CR_E2STS act as barriers.
+	 */
+	memcpy_toio(txt + TXT_CR_ERRORCODE, &error, sizeof(error));
+	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+	memcpy_toio(txt + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
+	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+	memcpy_toio(txt + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
+	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+	memcpy_toio(txt + TXT_CR_CMD_RESET, &one, sizeof(one));
+
+	for ( ; ; )
+		asm volatile ("hlt");
+
+	unreachable();
+}
+
+/*
+ * The TXT heap is too big to map all at once with early_ioremap
+ * so it is done a table at a time.
+ */
+static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
+					     u32 bytes)
+{
+	u64 base, size, offset = 0;
+	void *heap;
+	int i;
+
+	if (type > TXT_SINIT_TABLE_MAX)
+		slaunch_txt_reset(txt,
+			"Error invalid table type for early heap walk\n",
+			SL_ERROR_HEAP_WALK);
+
+	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
+	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
+
+	/* Iterate over heap tables looking for table of "type" */
+	for (i = 0; i < type; i++) {
+		base += offset;
+		heap = early_memremap(base, sizeof(u64));
+		if (!heap)
+			slaunch_txt_reset(txt,
+				"Error early_memremap of heap for heap walk\n",
+				SL_ERROR_HEAP_MAP);
+
+		offset = *((u64 *)heap);
+
+		/*
+		 * After the first iteration, any offset of zero is invalid and
+		 * implies the TXT heap is corrupted.
+		 */
+		if (!offset)
+			slaunch_txt_reset(txt,
+				"Error invalid 0 offset in heap walk\n",
+				SL_ERROR_HEAP_ZERO_OFFSET);
+
+		early_memunmap(heap, sizeof(u64));
+	}
+
+	/* Skip the size field at the head of each table */
+	base += sizeof(u64);
+	heap = early_memremap(base, bytes);
+	if (!heap)
+		slaunch_txt_reset(txt,
+				  "Error early_memremap of heap section\n",
+				  SL_ERROR_HEAP_MAP);
+
+	return heap;
+}
+
+static void __init txt_early_put_heap_table(void *addr, unsigned long size)
+{
+	early_memunmap(addr, size);
+}
+
+/*
+ * TXT uses a special set of VTd registers to protect all of memory from DMA
+ * until the IOMMU can be programmed to protect memory. There is the low
+ * memory PMR that can protect all memory up to 4G. The high memory PRM can
+ * be setup to protect all memory beyond 4Gb. Validate that these values cover
+ * what is expected.
+ */
+static void __init slaunch_verify_pmrs(void __iomem *txt)
+{
+	struct txt_os_sinit_data *os_sinit_data;
+	u32 field_offset, err = 0;
+	const char *errmsg = "";
+	unsigned long last_pfn;
+
+	field_offset = offsetof(struct txt_os_sinit_data, lcp_po_base);
+	os_sinit_data = txt_early_get_heap_table(txt, TXT_OS_SINIT_DATA_TABLE,
+						 field_offset);
+
+	/* Save a copy */
+	vtd_pmr_lo_size = os_sinit_data->vtd_pmr_lo_size;
+
+	last_pfn = e820__end_of_ram_pfn();
+
+	/*
+	 * First make sure the hi PMR covers all memory above 4G. In the
+	 * unlikely case where there is < 4G on the system, the hi PMR will
+	 * not be set.
+	 */
+	if (os_sinit_data->vtd_pmr_hi_base != 0x0ULL) {
+		if (os_sinit_data->vtd_pmr_hi_base != 0x100000000ULL) {
+			err = SL_ERROR_HI_PMR_BASE;
+			errmsg =  "Error hi PMR base\n";
+			goto out;
+		}
+
+		if (PFN_PHYS(last_pfn) > os_sinit_data->vtd_pmr_hi_base +
+		    os_sinit_data->vtd_pmr_hi_size) {
+			err = SL_ERROR_HI_PMR_SIZE;
+			errmsg = "Error hi PMR size\n";
+			goto out;
+		}
+	}
+
+	/*
+	 * Lo PMR base should always be 0. This was already checked in
+	 * early stub.
+	 */
+
+	/*
+	 * Check that if the kernel was loaded below 4G, that it is protected
+	 * by the lo PMR. Note this is the decompressed kernel. The ACM would
+	 * have ensured the compressed kernel (the MLE image) was protected.
+	 */
+	if ((__pa_symbol(_end) < 0x100000000ULL) &&
+	    (__pa_symbol(_end) > os_sinit_data->vtd_pmr_lo_size)) {
+		err = SL_ERROR_LO_PMR_MLE;
+		errmsg = "Error lo PMR does not cover MLE kernel\n";
+	}
+
+	/*
+	 * Other regions of interest like boot param, AP wake block, cmdline
+	 * already checked for PMR coverage in the early stub code.
+	 */
+
+out:
+	txt_early_put_heap_table(os_sinit_data, field_offset);
+
+	if (err)
+		slaunch_txt_reset(txt, errmsg, err);
+}
+
+static void __init slaunch_txt_reserve_range(u64 base, u64 size)
+{
+	int type;
+
+	type = e820__get_entry_type(base, base + size - 1);
+	if (type == E820_TYPE_RAM) {
+		pr_info("memblock reserve base: %llx size: %llx\n", base, size);
+		memblock_reserve(base, size);
+	}
+}
+
+/*
+ * For Intel, certain regions of memory must be marked as reserved by putting
+ * them on the memblock reserved list if they are not already e820 reserved.
+ * This includes:
+ *  - The TXT HEAP
+ *  - The ACM area
+ *  - The TXT private register bank
+ *  - The MDR list sent to the MLE by the ACM (see TXT specification)
+ *  (Normally the above are properly reserved by firmware but if it was not
+ *  done, reserve them now)
+ *  - The AP wake block
+ *  - TPM log external to the TXT heap
+ *
+ * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
+ * the low PMR must be reservered too.
+ */
+static void __init slaunch_txt_reserve(void __iomem *txt)
+{
+	struct txt_sinit_memory_descriptor_record *mdr;
+	struct txt_sinit_mle_data *sinit_mle_data;
+	u64 base, size, heap_base, heap_size;
+	u32 mdrnum, mdroffset, mdrslen;
+	u32 field_offset, i;
+	void *mdrs;
+
+	base = TXT_PRIV_CONFIG_REGS_BASE;
+	size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
+	slaunch_txt_reserve_range(base, size);
+
+	memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
+	memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
+	slaunch_txt_reserve_range(heap_base, heap_size);
+
+	memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
+	memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
+	slaunch_txt_reserve_range(base, size);
+
+	field_offset = offsetof(struct txt_sinit_mle_data,
+				sinit_vtd_dmar_table_size);
+	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
+						  field_offset);
+
+	mdrnum = sinit_mle_data->num_of_sinit_mdrs;
+	mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
+
+	txt_early_put_heap_table(sinit_mle_data, field_offset);
+
+	if (!mdrnum)
+		goto nomdr;
+
+	mdrslen = mdrnum * sizeof(struct txt_sinit_memory_descriptor_record);
+
+	mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
+					mdroffset + mdrslen - 8);
+
+	mdr = mdrs + mdroffset - 8;
+
+	for (i = 0; i < mdrnum; i++, mdr++) {
+		/* Spec says some entries can have length 0, ignore them */
+		if (mdr->type > 0 && mdr->length > 0)
+			slaunch_txt_reserve_range(mdr->address, mdr->length);
+	}
+
+	txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
+
+nomdr:
+	slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
+				  ap_wake_info.ap_wake_block_size);
+
+	/*
+	 * Earlier checks ensured that the event log was properly situated
+	 * either inside the TXT heap or outside. This is a check to see if the
+	 * event log needs to be reserved. If it is in the TXT heap, it is
+	 * already reserved.
+	 */
+	if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
+		slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
+
+	for (i = 0; i < e820_table->nr_entries; i++) {
+		base = e820_table->entries[i].addr;
+		size = e820_table->entries[i].size;
+		if ((base >= vtd_pmr_lo_size) && (base < 0x100000000ULL))
+			slaunch_txt_reserve_range(base, size);
+		else if ((base < vtd_pmr_lo_size) &&
+			 (base + size > vtd_pmr_lo_size))
+			slaunch_txt_reserve_range(vtd_pmr_lo_size,
+						  base + size - vtd_pmr_lo_size);
+	}
+}
+
+/*
+ * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
+ * It is stored in the TXT heap. Fetch it from there and make it available
+ * to the IOMMU driver.
+ */
+static void __init slaunch_copy_dmar_table(void __iomem *txt)
+{
+	struct txt_sinit_mle_data *sinit_mle_data;
+	u32 field_offset, dmar_size, dmar_offset;
+	void *dmar;
+
+	memset(&txt_dmar, 0, PAGE_SIZE);
+
+	field_offset = offsetof(struct txt_sinit_mle_data,
+				processor_scrtm_status);
+	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
+						  field_offset);
+
+	dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
+	dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
+
+	txt_early_put_heap_table(sinit_mle_data, field_offset);
+
+	if (!dmar_size || !dmar_offset)
+		slaunch_txt_reset(txt,
+				  "Error invalid DMAR table values\n",
+				  SL_ERROR_HEAP_INVALID_DMAR);
+
+	if (unlikely(dmar_size > PAGE_SIZE))
+		slaunch_txt_reset(txt,
+				  "Error DMAR too big to store\n",
+				  SL_ERROR_HEAP_DMAR_SIZE);
+
+
+	dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
+					dmar_offset + dmar_size - 8);
+	if (!dmar)
+		slaunch_txt_reset(txt,
+				  "Error early_ioremap of DMAR\n",
+				  SL_ERROR_HEAP_DMAR_MAP);
+
+	memcpy(&txt_dmar[0], dmar + dmar_offset - 8, dmar_size);
+
+	txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
+}
+
+/*
+ * The location of the safe AP wake code block is stored in the TXT heap.
+ * Fetch needed values here in the early init code for later use in SMP
+ * startup.
+ *
+ * Also get the TPM event log values are in the SLRT and have to be fetched.
+ * They will be put on the memblock reserve list later.
+ */
+static void __init slaunch_fetch_values(void __iomem *txt)
+{
+	struct txt_os_mle_data *os_mle_data;
+	struct slr_entry_log_info *log_info;
+	struct slr_table *slrt;
+	u8 *jmp_offset;
+	u32 size;
+
+	os_mle_data = txt_early_get_heap_table(txt, TXT_OS_MLE_DATA_TABLE,
+					       sizeof(*os_mle_data));
+
+	ap_wake_info.ap_wake_block = os_mle_data->ap_wake_block;
+	ap_wake_info.ap_wake_block_size = os_mle_data->ap_wake_block_size;
+
+	jmp_offset = os_mle_data->mle_scratch + SL_SCRATCH_AP_JMP_OFFSET;
+	ap_wake_info.ap_jmp_offset = *((u32 *)jmp_offset);
+
+	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, sizeof(*slrt));
+	if (!slrt)
+		slaunch_txt_reset(txt,
+			"Error early_memremap of SLRT failed\n",
+			SL_ERROR_SLRT_MAP);
+
+	size = slrt->size;
+	early_memunmap(slrt, sizeof(*slrt));
+
+	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, size);
+	if (!slrt)
+		slaunch_txt_reset(txt,
+			"Error early_memremap of SLRT failed\n",
+			SL_ERROR_SLRT_MAP);
+
+	log_info = (struct slr_entry_log_info *)
+		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
+
+	if (!log_info)
+		slaunch_txt_reset(txt,
+				  "SLRT missing logging info entry\n",
+				  SL_ERROR_SLRT_MISSING_ENTRY);
+
+	evtlog_addr = log_info->addr;
+	evtlog_size = log_info->size;
+
+	early_memunmap(slrt, size);
+
+	txt_early_put_heap_table(os_mle_data, sizeof(*os_mle_data));
+}
+
+/*
+ * Intel TXT specific late stub setup and validation.
+ */
+void __init slaunch_setup_txt(void)
+{
+	u64 one = TXT_REGVALUE_ONE, val;
+	void __iomem *txt;
+
+	if (!boot_cpu_has(X86_FEATURE_SMX))
+		return;
+
+	/*
+	 * If booted through secure launch entry point, the loadflags
+	 * option will be set.
+	 */
+	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
+		return;
+
+	/*
+	 * See if SENTER was done by reading the status register in the
+	 * public space. If the public register space cannot be read, TXT may
+	 * be disabled.
+	 */
+	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
+			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
+	if (!txt)
+		return;
+
+	memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
+	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
+
+	/* SENTER should have been done */
+	if (!(val & TXT_SENTER_DONE_STS))
+		panic("Error TXT.STS SENTER_DONE not set\n");
+
+	/* SEXIT should have been cleared */
+	if (val & TXT_SEXIT_DONE_STS)
+		panic("Error TXT.STS SEXIT_DONE set\n");
+
+	/* Now we want to use the private register space */
+	txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
+			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
+	if (!txt) {
+		/* This is really bad, no where to go from here */
+		panic("Error early_ioremap of TXT priv registers\n");
+	}
+
+	/*
+	 * Try to read the Intel VID from the TXT private registers to see if
+	 * TXT measured launch happened properly and the private space is
+	 * available.
+	 */
+	memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
+	if ((val & 0xffff) != 0x8086) {
+		/*
+		 * Can't do a proper TXT reset since it appears something is
+		 * wrong even though SENTER happened and it should be in SMX
+		 * mode.
+		 */
+		panic("Invalid TXT vendor ID, not in SMX mode\n");
+	}
+
+	/* Set flags so subsequent code knows the status of the launch */
+	sl_flags |= (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT);
+
+	/*
+	 * Reading the proper DIDVID from the private register space means we
+	 * are in SMX mode and private registers are open for read/write.
+	 */
+
+	/* On Intel, have to handle TPM localities via TXT */
+	memcpy_toio(txt + TXT_CR_CMD_SECRETS, &one, sizeof(one));
+	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+	memcpy_toio(txt + TXT_CR_CMD_OPEN_LOCALITY1, &one, sizeof(one));
+	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+
+	slaunch_fetch_values(txt);
+
+	slaunch_verify_pmrs(txt);
+
+	slaunch_txt_reserve(txt);
+
+	slaunch_copy_dmar_table(txt);
+
+	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
+
+	pr_info("Intel TXT setup complete\n");
+}
diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index a3414af..5d1ac8d 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -28,6 +28,7 @@
 #include <linux/iommu.h>
 #include <linux/numa.h>
 #include <linux/limits.h>
+#include <linux/slaunch.h>
 #include <asm/irq_remapping.h>
 
 #include "iommu.h"
@@ -660,6 +661,9 @@ static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar,
 	 */
 	dmar_tbl = tboot_get_dmar_table(dmar_tbl);
 
+	/* If Secure Launch is active, it has similar logic */
+	dmar_tbl = slaunch_get_dmar_table(dmar_tbl);
+
 	dmar = (struct acpi_table_dmar *)dmar_tbl;
 	if (!dmar)
 		return -ENODEV;
-- 
1.8.3.1


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

* [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

The routine slaunch_setup is called out of the x86 specific setup_arch
routine during early kernel boot. After determining what platform is
present, various operations specific to that platform occur. This
includes finalizing setting for the platform late launch and verifying
that memory protections are in place.

For TXT, this code also reserves the original compressed kernel setup
area where the APs were left looping so that this memory cannot be used.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/kernel/Makefile   |   1 +
 arch/x86/kernel/setup.c    |   3 +
 arch/x86/kernel/slaunch.c  | 497 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/iommu/intel/dmar.c |   4 +
 4 files changed, 505 insertions(+)
 create mode 100644 arch/x86/kernel/slaunch.c

diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index dd61752..3d2a33e 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_X86_32)		+= tls.o
 obj-$(CONFIG_IA32_EMULATION)	+= tls.o
 obj-y				+= step.o
 obj-$(CONFIG_INTEL_TXT)		+= tboot.o
+obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
 obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
 obj-y				+= stacktrace.o
 obj-y				+= cpu/
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 16babff..592c09e 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -21,6 +21,7 @@
 #include <linux/root_dev.h>
 #include <linux/hugetlb.h>
 #include <linux/tboot.h>
+#include <linux/slaunch.h>
 #include <linux/usb/xhci-dbgp.h>
 #include <linux/static_call.h>
 #include <linux/swiotlb.h>
@@ -1063,6 +1064,8 @@ void __init setup_arch(char **cmdline_p)
 	early_gart_iommu_check();
 #endif
 
+	slaunch_setup_txt();
+
 	/*
 	 * partially used pages are not usable - thus
 	 * we are rounding upwards:
diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
new file mode 100644
index 0000000..7dba088
--- /dev/null
+++ b/arch/x86/kernel/slaunch.c
@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Secure Launch late validation/setup and finalization support.
+ *
+ * Copyright (c) 2022, Oracle and/or its affiliates.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/security.h>
+#include <linux/memblock.h>
+#include <asm/segment.h>
+#include <asm/sections.h>
+#include <asm/tlbflush.h>
+#include <asm/e820/api.h>
+#include <asm/setup.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
+
+static u32 sl_flags;
+static struct sl_ap_wake_info ap_wake_info;
+static u64 evtlog_addr;
+static u32 evtlog_size;
+static u64 vtd_pmr_lo_size;
+
+/* This should be plenty of room */
+static u8 txt_dmar[PAGE_SIZE] __aligned(16);
+
+u32 slaunch_get_flags(void)
+{
+	return sl_flags;
+}
+EXPORT_SYMBOL(slaunch_get_flags);
+
+struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
+{
+	return &ap_wake_info;
+}
+
+struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
+{
+	/* The DMAR is only stashed and provided via TXT on Intel systems */
+	if (memcmp(txt_dmar, "DMAR", 4))
+		return dmar;
+
+	return (struct acpi_table_header *)(&txt_dmar[0]);
+}
+
+void __noreturn slaunch_txt_reset(void __iomem *txt,
+				  const char *msg, u64 error)
+{
+	u64 one = 1, val;
+
+	pr_err("%s", msg);
+
+	/*
+	 * This performs a TXT reset with a sticky error code. The reads of
+	 * TXT_CR_E2STS act as barriers.
+	 */
+	memcpy_toio(txt + TXT_CR_ERRORCODE, &error, sizeof(error));
+	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+	memcpy_toio(txt + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
+	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+	memcpy_toio(txt + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
+	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+	memcpy_toio(txt + TXT_CR_CMD_RESET, &one, sizeof(one));
+
+	for ( ; ; )
+		asm volatile ("hlt");
+
+	unreachable();
+}
+
+/*
+ * The TXT heap is too big to map all at once with early_ioremap
+ * so it is done a table at a time.
+ */
+static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
+					     u32 bytes)
+{
+	u64 base, size, offset = 0;
+	void *heap;
+	int i;
+
+	if (type > TXT_SINIT_TABLE_MAX)
+		slaunch_txt_reset(txt,
+			"Error invalid table type for early heap walk\n",
+			SL_ERROR_HEAP_WALK);
+
+	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
+	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
+
+	/* Iterate over heap tables looking for table of "type" */
+	for (i = 0; i < type; i++) {
+		base += offset;
+		heap = early_memremap(base, sizeof(u64));
+		if (!heap)
+			slaunch_txt_reset(txt,
+				"Error early_memremap of heap for heap walk\n",
+				SL_ERROR_HEAP_MAP);
+
+		offset = *((u64 *)heap);
+
+		/*
+		 * After the first iteration, any offset of zero is invalid and
+		 * implies the TXT heap is corrupted.
+		 */
+		if (!offset)
+			slaunch_txt_reset(txt,
+				"Error invalid 0 offset in heap walk\n",
+				SL_ERROR_HEAP_ZERO_OFFSET);
+
+		early_memunmap(heap, sizeof(u64));
+	}
+
+	/* Skip the size field at the head of each table */
+	base += sizeof(u64);
+	heap = early_memremap(base, bytes);
+	if (!heap)
+		slaunch_txt_reset(txt,
+				  "Error early_memremap of heap section\n",
+				  SL_ERROR_HEAP_MAP);
+
+	return heap;
+}
+
+static void __init txt_early_put_heap_table(void *addr, unsigned long size)
+{
+	early_memunmap(addr, size);
+}
+
+/*
+ * TXT uses a special set of VTd registers to protect all of memory from DMA
+ * until the IOMMU can be programmed to protect memory. There is the low
+ * memory PMR that can protect all memory up to 4G. The high memory PRM can
+ * be setup to protect all memory beyond 4Gb. Validate that these values cover
+ * what is expected.
+ */
+static void __init slaunch_verify_pmrs(void __iomem *txt)
+{
+	struct txt_os_sinit_data *os_sinit_data;
+	u32 field_offset, err = 0;
+	const char *errmsg = "";
+	unsigned long last_pfn;
+
+	field_offset = offsetof(struct txt_os_sinit_data, lcp_po_base);
+	os_sinit_data = txt_early_get_heap_table(txt, TXT_OS_SINIT_DATA_TABLE,
+						 field_offset);
+
+	/* Save a copy */
+	vtd_pmr_lo_size = os_sinit_data->vtd_pmr_lo_size;
+
+	last_pfn = e820__end_of_ram_pfn();
+
+	/*
+	 * First make sure the hi PMR covers all memory above 4G. In the
+	 * unlikely case where there is < 4G on the system, the hi PMR will
+	 * not be set.
+	 */
+	if (os_sinit_data->vtd_pmr_hi_base != 0x0ULL) {
+		if (os_sinit_data->vtd_pmr_hi_base != 0x100000000ULL) {
+			err = SL_ERROR_HI_PMR_BASE;
+			errmsg =  "Error hi PMR base\n";
+			goto out;
+		}
+
+		if (PFN_PHYS(last_pfn) > os_sinit_data->vtd_pmr_hi_base +
+		    os_sinit_data->vtd_pmr_hi_size) {
+			err = SL_ERROR_HI_PMR_SIZE;
+			errmsg = "Error hi PMR size\n";
+			goto out;
+		}
+	}
+
+	/*
+	 * Lo PMR base should always be 0. This was already checked in
+	 * early stub.
+	 */
+
+	/*
+	 * Check that if the kernel was loaded below 4G, that it is protected
+	 * by the lo PMR. Note this is the decompressed kernel. The ACM would
+	 * have ensured the compressed kernel (the MLE image) was protected.
+	 */
+	if ((__pa_symbol(_end) < 0x100000000ULL) &&
+	    (__pa_symbol(_end) > os_sinit_data->vtd_pmr_lo_size)) {
+		err = SL_ERROR_LO_PMR_MLE;
+		errmsg = "Error lo PMR does not cover MLE kernel\n";
+	}
+
+	/*
+	 * Other regions of interest like boot param, AP wake block, cmdline
+	 * already checked for PMR coverage in the early stub code.
+	 */
+
+out:
+	txt_early_put_heap_table(os_sinit_data, field_offset);
+
+	if (err)
+		slaunch_txt_reset(txt, errmsg, err);
+}
+
+static void __init slaunch_txt_reserve_range(u64 base, u64 size)
+{
+	int type;
+
+	type = e820__get_entry_type(base, base + size - 1);
+	if (type == E820_TYPE_RAM) {
+		pr_info("memblock reserve base: %llx size: %llx\n", base, size);
+		memblock_reserve(base, size);
+	}
+}
+
+/*
+ * For Intel, certain regions of memory must be marked as reserved by putting
+ * them on the memblock reserved list if they are not already e820 reserved.
+ * This includes:
+ *  - The TXT HEAP
+ *  - The ACM area
+ *  - The TXT private register bank
+ *  - The MDR list sent to the MLE by the ACM (see TXT specification)
+ *  (Normally the above are properly reserved by firmware but if it was not
+ *  done, reserve them now)
+ *  - The AP wake block
+ *  - TPM log external to the TXT heap
+ *
+ * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
+ * the low PMR must be reservered too.
+ */
+static void __init slaunch_txt_reserve(void __iomem *txt)
+{
+	struct txt_sinit_memory_descriptor_record *mdr;
+	struct txt_sinit_mle_data *sinit_mle_data;
+	u64 base, size, heap_base, heap_size;
+	u32 mdrnum, mdroffset, mdrslen;
+	u32 field_offset, i;
+	void *mdrs;
+
+	base = TXT_PRIV_CONFIG_REGS_BASE;
+	size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
+	slaunch_txt_reserve_range(base, size);
+
+	memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
+	memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
+	slaunch_txt_reserve_range(heap_base, heap_size);
+
+	memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
+	memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
+	slaunch_txt_reserve_range(base, size);
+
+	field_offset = offsetof(struct txt_sinit_mle_data,
+				sinit_vtd_dmar_table_size);
+	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
+						  field_offset);
+
+	mdrnum = sinit_mle_data->num_of_sinit_mdrs;
+	mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
+
+	txt_early_put_heap_table(sinit_mle_data, field_offset);
+
+	if (!mdrnum)
+		goto nomdr;
+
+	mdrslen = mdrnum * sizeof(struct txt_sinit_memory_descriptor_record);
+
+	mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
+					mdroffset + mdrslen - 8);
+
+	mdr = mdrs + mdroffset - 8;
+
+	for (i = 0; i < mdrnum; i++, mdr++) {
+		/* Spec says some entries can have length 0, ignore them */
+		if (mdr->type > 0 && mdr->length > 0)
+			slaunch_txt_reserve_range(mdr->address, mdr->length);
+	}
+
+	txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
+
+nomdr:
+	slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
+				  ap_wake_info.ap_wake_block_size);
+
+	/*
+	 * Earlier checks ensured that the event log was properly situated
+	 * either inside the TXT heap or outside. This is a check to see if the
+	 * event log needs to be reserved. If it is in the TXT heap, it is
+	 * already reserved.
+	 */
+	if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
+		slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
+
+	for (i = 0; i < e820_table->nr_entries; i++) {
+		base = e820_table->entries[i].addr;
+		size = e820_table->entries[i].size;
+		if ((base >= vtd_pmr_lo_size) && (base < 0x100000000ULL))
+			slaunch_txt_reserve_range(base, size);
+		else if ((base < vtd_pmr_lo_size) &&
+			 (base + size > vtd_pmr_lo_size))
+			slaunch_txt_reserve_range(vtd_pmr_lo_size,
+						  base + size - vtd_pmr_lo_size);
+	}
+}
+
+/*
+ * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
+ * It is stored in the TXT heap. Fetch it from there and make it available
+ * to the IOMMU driver.
+ */
+static void __init slaunch_copy_dmar_table(void __iomem *txt)
+{
+	struct txt_sinit_mle_data *sinit_mle_data;
+	u32 field_offset, dmar_size, dmar_offset;
+	void *dmar;
+
+	memset(&txt_dmar, 0, PAGE_SIZE);
+
+	field_offset = offsetof(struct txt_sinit_mle_data,
+				processor_scrtm_status);
+	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
+						  field_offset);
+
+	dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
+	dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
+
+	txt_early_put_heap_table(sinit_mle_data, field_offset);
+
+	if (!dmar_size || !dmar_offset)
+		slaunch_txt_reset(txt,
+				  "Error invalid DMAR table values\n",
+				  SL_ERROR_HEAP_INVALID_DMAR);
+
+	if (unlikely(dmar_size > PAGE_SIZE))
+		slaunch_txt_reset(txt,
+				  "Error DMAR too big to store\n",
+				  SL_ERROR_HEAP_DMAR_SIZE);
+
+
+	dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
+					dmar_offset + dmar_size - 8);
+	if (!dmar)
+		slaunch_txt_reset(txt,
+				  "Error early_ioremap of DMAR\n",
+				  SL_ERROR_HEAP_DMAR_MAP);
+
+	memcpy(&txt_dmar[0], dmar + dmar_offset - 8, dmar_size);
+
+	txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
+}
+
+/*
+ * The location of the safe AP wake code block is stored in the TXT heap.
+ * Fetch needed values here in the early init code for later use in SMP
+ * startup.
+ *
+ * Also get the TPM event log values are in the SLRT and have to be fetched.
+ * They will be put on the memblock reserve list later.
+ */
+static void __init slaunch_fetch_values(void __iomem *txt)
+{
+	struct txt_os_mle_data *os_mle_data;
+	struct slr_entry_log_info *log_info;
+	struct slr_table *slrt;
+	u8 *jmp_offset;
+	u32 size;
+
+	os_mle_data = txt_early_get_heap_table(txt, TXT_OS_MLE_DATA_TABLE,
+					       sizeof(*os_mle_data));
+
+	ap_wake_info.ap_wake_block = os_mle_data->ap_wake_block;
+	ap_wake_info.ap_wake_block_size = os_mle_data->ap_wake_block_size;
+
+	jmp_offset = os_mle_data->mle_scratch + SL_SCRATCH_AP_JMP_OFFSET;
+	ap_wake_info.ap_jmp_offset = *((u32 *)jmp_offset);
+
+	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, sizeof(*slrt));
+	if (!slrt)
+		slaunch_txt_reset(txt,
+			"Error early_memremap of SLRT failed\n",
+			SL_ERROR_SLRT_MAP);
+
+	size = slrt->size;
+	early_memunmap(slrt, sizeof(*slrt));
+
+	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, size);
+	if (!slrt)
+		slaunch_txt_reset(txt,
+			"Error early_memremap of SLRT failed\n",
+			SL_ERROR_SLRT_MAP);
+
+	log_info = (struct slr_entry_log_info *)
+		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
+
+	if (!log_info)
+		slaunch_txt_reset(txt,
+				  "SLRT missing logging info entry\n",
+				  SL_ERROR_SLRT_MISSING_ENTRY);
+
+	evtlog_addr = log_info->addr;
+	evtlog_size = log_info->size;
+
+	early_memunmap(slrt, size);
+
+	txt_early_put_heap_table(os_mle_data, sizeof(*os_mle_data));
+}
+
+/*
+ * Intel TXT specific late stub setup and validation.
+ */
+void __init slaunch_setup_txt(void)
+{
+	u64 one = TXT_REGVALUE_ONE, val;
+	void __iomem *txt;
+
+	if (!boot_cpu_has(X86_FEATURE_SMX))
+		return;
+
+	/*
+	 * If booted through secure launch entry point, the loadflags
+	 * option will be set.
+	 */
+	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
+		return;
+
+	/*
+	 * See if SENTER was done by reading the status register in the
+	 * public space. If the public register space cannot be read, TXT may
+	 * be disabled.
+	 */
+	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
+			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
+	if (!txt)
+		return;
+
+	memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
+	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
+
+	/* SENTER should have been done */
+	if (!(val & TXT_SENTER_DONE_STS))
+		panic("Error TXT.STS SENTER_DONE not set\n");
+
+	/* SEXIT should have been cleared */
+	if (val & TXT_SEXIT_DONE_STS)
+		panic("Error TXT.STS SEXIT_DONE set\n");
+
+	/* Now we want to use the private register space */
+	txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
+			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
+	if (!txt) {
+		/* This is really bad, no where to go from here */
+		panic("Error early_ioremap of TXT priv registers\n");
+	}
+
+	/*
+	 * Try to read the Intel VID from the TXT private registers to see if
+	 * TXT measured launch happened properly and the private space is
+	 * available.
+	 */
+	memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
+	if ((val & 0xffff) != 0x8086) {
+		/*
+		 * Can't do a proper TXT reset since it appears something is
+		 * wrong even though SENTER happened and it should be in SMX
+		 * mode.
+		 */
+		panic("Invalid TXT vendor ID, not in SMX mode\n");
+	}
+
+	/* Set flags so subsequent code knows the status of the launch */
+	sl_flags |= (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT);
+
+	/*
+	 * Reading the proper DIDVID from the private register space means we
+	 * are in SMX mode and private registers are open for read/write.
+	 */
+
+	/* On Intel, have to handle TPM localities via TXT */
+	memcpy_toio(txt + TXT_CR_CMD_SECRETS, &one, sizeof(one));
+	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+	memcpy_toio(txt + TXT_CR_CMD_OPEN_LOCALITY1, &one, sizeof(one));
+	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+
+	slaunch_fetch_values(txt);
+
+	slaunch_verify_pmrs(txt);
+
+	slaunch_txt_reserve(txt);
+
+	slaunch_copy_dmar_table(txt);
+
+	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
+
+	pr_info("Intel TXT setup complete\n");
+}
diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index a3414af..5d1ac8d 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -28,6 +28,7 @@
 #include <linux/iommu.h>
 #include <linux/numa.h>
 #include <linux/limits.h>
+#include <linux/slaunch.h>
 #include <asm/irq_remapping.h>
 
 #include "iommu.h"
@@ -660,6 +661,9 @@ static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar,
 	 */
 	dmar_tbl = tboot_get_dmar_table(dmar_tbl);
 
+	/* If Secure Launch is active, it has similar logic */
+	dmar_tbl = slaunch_get_dmar_table(dmar_tbl);
+
 	dmar = (struct acpi_table_dmar *)dmar_tbl;
 	if (!dmar)
 		return -ENODEV;
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 09/14] x86: Secure Launch SMP bringup support
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Intel, the APs are left in a well documented state after TXT performs
the late launch. Specifically they cannot have #INIT asserted on them so
a standard startup via INIT/SIPI/SIPI cannot be performed. Instead the
early SL stub code parked the APs in a pause/jmp loop waiting for an NMI.
The modified SMP boot code is called for the Secure Launch case. The
jump address for the RM piggy entry point is fixed up in the jump where
the APs are waiting and an NMI IPI is sent to the AP. The AP vectors to
the Secure Launch entry point in the RM piggy which mimics what the real
mode code would do then jumps to the standard RM piggy protected mode
entry point.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/include/asm/realmode.h      |  3 ++
 arch/x86/kernel/smpboot.c            | 86 ++++++++++++++++++++++++++++++++++++
 arch/x86/realmode/rm/header.S        |  3 ++
 arch/x86/realmode/rm/trampoline_64.S | 37 ++++++++++++++++
 4 files changed, 129 insertions(+)

diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index f6a1737..576fe62 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -38,6 +38,9 @@ struct real_mode_header {
 #ifdef CONFIG_X86_64
 	u32	machine_real_restart_seg;
 #endif
+#ifdef CONFIG_SECURE_LAUNCH
+	u32	sl_trampoline_start32;
+#endif
 };
 
 /* This must match data at realmode/rm/trampoline_{32,64}.S */
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 352f0ce..07d740be 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -57,6 +57,7 @@
 #include <linux/pgtable.h>
 #include <linux/overflow.h>
 #include <linux/stackprotector.h>
+#include <linux/slaunch.h>
 
 #include <asm/acpi.h>
 #include <asm/cacheinfo.h>
@@ -1068,6 +1069,83 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
 	return 0;
 }
 
+#ifdef CONFIG_SECURE_LAUNCH
+
+static atomic_t first_ap_only = {1};
+
+/*
+ * Called to fix the long jump address for the waiting APs to vector to
+ * the correct startup location in the Secure Launch stub in the rmpiggy.
+ */
+static int
+slaunch_fixup_jump_vector(void)
+{
+	struct sl_ap_wake_info *ap_wake_info;
+	u32 *ap_jmp_ptr = NULL;
+
+	if (!atomic_dec_and_test(&first_ap_only))
+		return 0;
+
+	ap_wake_info = slaunch_get_ap_wake_info();
+
+	ap_jmp_ptr = (u32 *)__va(ap_wake_info->ap_wake_block +
+				 ap_wake_info->ap_jmp_offset);
+
+	*ap_jmp_ptr = real_mode_header->sl_trampoline_start32;
+
+	pr_debug("TXT AP long jump address updated\n");
+
+	return 0;
+}
+
+/*
+ * TXT AP startup is quite different than normal. The APs cannot have #INIT
+ * asserted on them or receive SIPIs. The early Secure Launch code has parked
+ * the APs in a pause loop waiting to receive an NMI. This will wake the APs
+ * and have them jump to the protected mode code in the rmpiggy where the rest
+ * of the SMP boot of the AP will proceed normally.
+ */
+static int
+slaunch_wakeup_cpu_from_txt(int cpu, int apicid)
+{
+	unsigned long send_status = 0, accept_status = 0;
+
+	/* Only done once */
+	if (slaunch_fixup_jump_vector())
+		return -1;
+
+	/* Send NMI IPI to idling AP and wake it up */
+	apic_icr_write(APIC_DM_NMI, apicid);
+
+	if (init_udelay == 0)
+		udelay(10);
+	else
+		udelay(300);
+
+	send_status = safe_apic_wait_icr_idle();
+
+	if (init_udelay == 0)
+		udelay(10);
+	else
+		udelay(300);
+
+	accept_status = (apic_read(APIC_ESR) & 0xEF);
+
+	if (send_status)
+		pr_err("Secure Launch IPI never delivered???\n");
+	if (accept_status)
+		pr_err("Secure Launch IPI delivery error (%lx)\n",
+			accept_status);
+
+	return (send_status | accept_status);
+}
+
+#else
+
+#define slaunch_wakeup_cpu_from_txt(cpu, apicid)	0
+
+#endif  /* !CONFIG_SECURE_LAUNCH */
+
 /*
  * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
  * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
@@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
 	cpumask_clear_cpu(cpu, cpu_initialized_mask);
 	smp_mb();
 
+	/* With Intel TXT, the AP startup is totally different */
+	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==
+	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {
+		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
+		goto txt_wake;
+	}
+
 	/*
 	 * Wake up a CPU in difference cases:
 	 * - Use a method from the APIC driver if one defined, with wakeup
@@ -1147,6 +1232,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
 		boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
 						     cpu0_nmi_registered);
 
+txt_wake:
 	if (!boot_error) {
 		/*
 		 * Wait 10s total for first sign of life from AP
diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
index 2eb62be..3b5cbcb 100644
--- a/arch/x86/realmode/rm/header.S
+++ b/arch/x86/realmode/rm/header.S
@@ -37,6 +37,9 @@ SYM_DATA_START(real_mode_header)
 #ifdef CONFIG_X86_64
 	.long	__KERNEL32_CS
 #endif
+#ifdef CONFIG_SECURE_LAUNCH
+	.long	pa_sl_trampoline_start32
+#endif
 SYM_DATA_END(real_mode_header)
 
 	/* End signature, used to verify integrity */
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
index e38d61d..8bb4b0d 100644
--- a/arch/x86/realmode/rm/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -104,6 +104,43 @@ SYM_CODE_END(sev_es_trampoline_start)
 
 	.section ".text32","ax"
 	.code32
+#ifdef CONFIG_SECURE_LAUNCH
+	.balign 4
+SYM_CODE_START(sl_trampoline_start32)
+	/*
+	 * The early secure launch stub AP wakeup code has taken care of all
+	 * the vagaries of launching out of TXT. This bit just mimics what the
+	 * 16b entry code does and jumps off to the real startup_32.
+	 */
+	cli
+	wbinvd
+
+	/*
+	 * The %ebx provided is not terribly useful since it is the physical
+	 * address of tb_trampoline_start and not the base of the image.
+	 * Use pa_real_mode_base, which is fixed up, to get a run time
+	 * base register to use for offsets to location that do not have
+	 * pa_ symbols.
+	 */
+	movl    $pa_real_mode_base, %ebx
+
+	/*
+	 * This may seem a little odd but this is what %esp would have had in
+	 * it on the jmp from real mode because all real mode fixups were done
+	 * via the code segment. The base is added at the 32b entry.
+	 */
+	movl	rm_stack_end, %esp
+
+	lgdt    tr_gdt(%ebx)
+	lidt    tr_idt(%ebx)
+
+	movw	$__KERNEL_DS, %dx	# Data segment descriptor
+
+	/* Jump to where the 16b code would have jumped */
+	ljmpl	$__KERNEL32_CS, $pa_startup_32
+SYM_CODE_END(sl_trampoline_start32)
+#endif
+
 	.balign 4
 SYM_CODE_START(startup_32)
 	movl	%edx, %ss
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 09/14] x86: Secure Launch SMP bringup support
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Intel, the APs are left in a well documented state after TXT performs
the late launch. Specifically they cannot have #INIT asserted on them so
a standard startup via INIT/SIPI/SIPI cannot be performed. Instead the
early SL stub code parked the APs in a pause/jmp loop waiting for an NMI.
The modified SMP boot code is called for the Secure Launch case. The
jump address for the RM piggy entry point is fixed up in the jump where
the APs are waiting and an NMI IPI is sent to the AP. The AP vectors to
the Secure Launch entry point in the RM piggy which mimics what the real
mode code would do then jumps to the standard RM piggy protected mode
entry point.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/include/asm/realmode.h      |  3 ++
 arch/x86/kernel/smpboot.c            | 86 ++++++++++++++++++++++++++++++++++++
 arch/x86/realmode/rm/header.S        |  3 ++
 arch/x86/realmode/rm/trampoline_64.S | 37 ++++++++++++++++
 4 files changed, 129 insertions(+)

diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index f6a1737..576fe62 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -38,6 +38,9 @@ struct real_mode_header {
 #ifdef CONFIG_X86_64
 	u32	machine_real_restart_seg;
 #endif
+#ifdef CONFIG_SECURE_LAUNCH
+	u32	sl_trampoline_start32;
+#endif
 };
 
 /* This must match data at realmode/rm/trampoline_{32,64}.S */
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 352f0ce..07d740be 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -57,6 +57,7 @@
 #include <linux/pgtable.h>
 #include <linux/overflow.h>
 #include <linux/stackprotector.h>
+#include <linux/slaunch.h>
 
 #include <asm/acpi.h>
 #include <asm/cacheinfo.h>
@@ -1068,6 +1069,83 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
 	return 0;
 }
 
+#ifdef CONFIG_SECURE_LAUNCH
+
+static atomic_t first_ap_only = {1};
+
+/*
+ * Called to fix the long jump address for the waiting APs to vector to
+ * the correct startup location in the Secure Launch stub in the rmpiggy.
+ */
+static int
+slaunch_fixup_jump_vector(void)
+{
+	struct sl_ap_wake_info *ap_wake_info;
+	u32 *ap_jmp_ptr = NULL;
+
+	if (!atomic_dec_and_test(&first_ap_only))
+		return 0;
+
+	ap_wake_info = slaunch_get_ap_wake_info();
+
+	ap_jmp_ptr = (u32 *)__va(ap_wake_info->ap_wake_block +
+				 ap_wake_info->ap_jmp_offset);
+
+	*ap_jmp_ptr = real_mode_header->sl_trampoline_start32;
+
+	pr_debug("TXT AP long jump address updated\n");
+
+	return 0;
+}
+
+/*
+ * TXT AP startup is quite different than normal. The APs cannot have #INIT
+ * asserted on them or receive SIPIs. The early Secure Launch code has parked
+ * the APs in a pause loop waiting to receive an NMI. This will wake the APs
+ * and have them jump to the protected mode code in the rmpiggy where the rest
+ * of the SMP boot of the AP will proceed normally.
+ */
+static int
+slaunch_wakeup_cpu_from_txt(int cpu, int apicid)
+{
+	unsigned long send_status = 0, accept_status = 0;
+
+	/* Only done once */
+	if (slaunch_fixup_jump_vector())
+		return -1;
+
+	/* Send NMI IPI to idling AP and wake it up */
+	apic_icr_write(APIC_DM_NMI, apicid);
+
+	if (init_udelay == 0)
+		udelay(10);
+	else
+		udelay(300);
+
+	send_status = safe_apic_wait_icr_idle();
+
+	if (init_udelay == 0)
+		udelay(10);
+	else
+		udelay(300);
+
+	accept_status = (apic_read(APIC_ESR) & 0xEF);
+
+	if (send_status)
+		pr_err("Secure Launch IPI never delivered???\n");
+	if (accept_status)
+		pr_err("Secure Launch IPI delivery error (%lx)\n",
+			accept_status);
+
+	return (send_status | accept_status);
+}
+
+#else
+
+#define slaunch_wakeup_cpu_from_txt(cpu, apicid)	0
+
+#endif  /* !CONFIG_SECURE_LAUNCH */
+
 /*
  * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
  * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
@@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
 	cpumask_clear_cpu(cpu, cpu_initialized_mask);
 	smp_mb();
 
+	/* With Intel TXT, the AP startup is totally different */
+	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==
+	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {
+		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
+		goto txt_wake;
+	}
+
 	/*
 	 * Wake up a CPU in difference cases:
 	 * - Use a method from the APIC driver if one defined, with wakeup
@@ -1147,6 +1232,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
 		boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
 						     cpu0_nmi_registered);
 
+txt_wake:
 	if (!boot_error) {
 		/*
 		 * Wait 10s total for first sign of life from AP
diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
index 2eb62be..3b5cbcb 100644
--- a/arch/x86/realmode/rm/header.S
+++ b/arch/x86/realmode/rm/header.S
@@ -37,6 +37,9 @@ SYM_DATA_START(real_mode_header)
 #ifdef CONFIG_X86_64
 	.long	__KERNEL32_CS
 #endif
+#ifdef CONFIG_SECURE_LAUNCH
+	.long	pa_sl_trampoline_start32
+#endif
 SYM_DATA_END(real_mode_header)
 
 	/* End signature, used to verify integrity */
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
index e38d61d..8bb4b0d 100644
--- a/arch/x86/realmode/rm/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -104,6 +104,43 @@ SYM_CODE_END(sev_es_trampoline_start)
 
 	.section ".text32","ax"
 	.code32
+#ifdef CONFIG_SECURE_LAUNCH
+	.balign 4
+SYM_CODE_START(sl_trampoline_start32)
+	/*
+	 * The early secure launch stub AP wakeup code has taken care of all
+	 * the vagaries of launching out of TXT. This bit just mimics what the
+	 * 16b entry code does and jumps off to the real startup_32.
+	 */
+	cli
+	wbinvd
+
+	/*
+	 * The %ebx provided is not terribly useful since it is the physical
+	 * address of tb_trampoline_start and not the base of the image.
+	 * Use pa_real_mode_base, which is fixed up, to get a run time
+	 * base register to use for offsets to location that do not have
+	 * pa_ symbols.
+	 */
+	movl    $pa_real_mode_base, %ebx
+
+	/*
+	 * This may seem a little odd but this is what %esp would have had in
+	 * it on the jmp from real mode because all real mode fixups were done
+	 * via the code segment. The base is added at the 32b entry.
+	 */
+	movl	rm_stack_end, %esp
+
+	lgdt    tr_gdt(%ebx)
+	lidt    tr_idt(%ebx)
+
+	movw	$__KERNEL_DS, %dx	# Data segment descriptor
+
+	/* Jump to where the 16b code would have jumped */
+	ljmpl	$__KERNEL32_CS, $pa_startup_32
+SYM_CODE_END(sl_trampoline_start32)
+#endif
+
 	.balign 4
 SYM_CODE_START(startup_32)
 	movl	%edx, %ss
-- 
1.8.3.1


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

* [PATCH v6 10/14] kexec: Secure Launch kexec SEXIT support
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

Prior to running the next kernel via kexec, the Secure Launch code
closes down private SMX resources and does an SEXIT. This allows the
next kernel to start normally without any issues starting the APs etc.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/kernel/slaunch.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
 kernel/kexec_core.c       |  4 +++
 2 files changed, 73 insertions(+)

diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
index 7dba088..176c029 100644
--- a/arch/x86/kernel/slaunch.c
+++ b/arch/x86/kernel/slaunch.c
@@ -495,3 +495,72 @@ void __init slaunch_setup_txt(void)
 
 	pr_info("Intel TXT setup complete\n");
 }
+
+static inline void smx_getsec_sexit(void)
+{
+	asm volatile (".byte 0x0f,0x37\n"
+		      : : "a" (SMX_X86_GETSEC_SEXIT));
+}
+
+void slaunch_finalize(int do_sexit)
+{
+	u64 one = TXT_REGVALUE_ONE, val;
+	void __iomem *config;
+
+	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
+	    (SL_FLAG_ACTIVE | SL_FLAG_ARCH_TXT))
+		return;
+
+	config = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
+			 PAGE_SIZE);
+	if (!config) {
+		pr_emerg("Error SEXIT failed to ioremap TXT private reqs\n");
+		return;
+	}
+
+	/* Clear secrets bit for SEXIT */
+	memcpy_toio(config + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
+	memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
+
+	/* Unlock memory configurations */
+	memcpy_toio(config + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
+	memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
+
+	/* Close the TXT private register space */
+	memcpy_toio(config + TXT_CR_CMD_CLOSE_PRIVATE, &one, sizeof(one));
+	memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
+
+	/*
+	 * Calls to iounmap are not being done because of the state of the
+	 * system this late in the kexec process. Local IRQs are disabled and
+	 * iounmap causes a TLB flush which in turn causes a warning. Leaving
+	 * thse mappings is not an issue since the next kernel is going to
+	 * completely re-setup memory management.
+	 */
+
+	/* Map public registers and do a final read fence */
+	config = ioremap(TXT_PUB_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
+			 PAGE_SIZE);
+	if (!config) {
+		pr_emerg("Error SEXIT failed to ioremap TXT public reqs\n");
+		return;
+	}
+
+	memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
+
+	pr_emerg("TXT clear secrets bit and unlock memory complete.\n");
+
+	if (!do_sexit)
+		return;
+
+	if (smp_processor_id() != 0)
+		panic("Error TXT SEXIT must be called on CPU 0\n");
+
+	/* Disable SMX mode */
+	cr4_set_bits(X86_CR4_SMXE);
+
+	/* Do the SEXIT SMX operation */
+	smx_getsec_sexit();
+
+	pr_info("TXT SEXIT complete.\n");
+}
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 3d578c6..5d66d68 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -40,6 +40,7 @@
 #include <linux/hugetlb.h>
 #include <linux/objtool.h>
 #include <linux/kmsg_dump.h>
+#include <linux/slaunch.h>
 
 #include <asm/page.h>
 #include <asm/sections.h>
@@ -1275,6 +1276,9 @@ int kernel_kexec(void)
 		cpu_hotplug_enable();
 		pr_notice("Starting new kernel\n");
 		machine_shutdown();
+
+		/* Finalize TXT registers and do SEXIT */
+		slaunch_finalize(1);
 	}
 
 	kmsg_dump(KMSG_DUMP_SHUTDOWN);
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 10/14] kexec: Secure Launch kexec SEXIT support
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

Prior to running the next kernel via kexec, the Secure Launch code
closes down private SMX resources and does an SEXIT. This allows the
next kernel to start normally without any issues starting the APs etc.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/kernel/slaunch.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
 kernel/kexec_core.c       |  4 +++
 2 files changed, 73 insertions(+)

diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
index 7dba088..176c029 100644
--- a/arch/x86/kernel/slaunch.c
+++ b/arch/x86/kernel/slaunch.c
@@ -495,3 +495,72 @@ void __init slaunch_setup_txt(void)
 
 	pr_info("Intel TXT setup complete\n");
 }
+
+static inline void smx_getsec_sexit(void)
+{
+	asm volatile (".byte 0x0f,0x37\n"
+		      : : "a" (SMX_X86_GETSEC_SEXIT));
+}
+
+void slaunch_finalize(int do_sexit)
+{
+	u64 one = TXT_REGVALUE_ONE, val;
+	void __iomem *config;
+
+	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
+	    (SL_FLAG_ACTIVE | SL_FLAG_ARCH_TXT))
+		return;
+
+	config = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
+			 PAGE_SIZE);
+	if (!config) {
+		pr_emerg("Error SEXIT failed to ioremap TXT private reqs\n");
+		return;
+	}
+
+	/* Clear secrets bit for SEXIT */
+	memcpy_toio(config + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
+	memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
+
+	/* Unlock memory configurations */
+	memcpy_toio(config + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
+	memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
+
+	/* Close the TXT private register space */
+	memcpy_toio(config + TXT_CR_CMD_CLOSE_PRIVATE, &one, sizeof(one));
+	memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
+
+	/*
+	 * Calls to iounmap are not being done because of the state of the
+	 * system this late in the kexec process. Local IRQs are disabled and
+	 * iounmap causes a TLB flush which in turn causes a warning. Leaving
+	 * thse mappings is not an issue since the next kernel is going to
+	 * completely re-setup memory management.
+	 */
+
+	/* Map public registers and do a final read fence */
+	config = ioremap(TXT_PUB_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
+			 PAGE_SIZE);
+	if (!config) {
+		pr_emerg("Error SEXIT failed to ioremap TXT public reqs\n");
+		return;
+	}
+
+	memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
+
+	pr_emerg("TXT clear secrets bit and unlock memory complete.\n");
+
+	if (!do_sexit)
+		return;
+
+	if (smp_processor_id() != 0)
+		panic("Error TXT SEXIT must be called on CPU 0\n");
+
+	/* Disable SMX mode */
+	cr4_set_bits(X86_CR4_SMXE);
+
+	/* Do the SEXIT SMX operation */
+	smx_getsec_sexit();
+
+	pr_info("TXT SEXIT complete.\n");
+}
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 3d578c6..5d66d68 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -40,6 +40,7 @@
 #include <linux/hugetlb.h>
 #include <linux/objtool.h>
 #include <linux/kmsg_dump.h>
+#include <linux/slaunch.h>
 
 #include <asm/page.h>
 #include <asm/sections.h>
@@ -1275,6 +1276,9 @@ int kernel_kexec(void)
 		cpu_hotplug_enable();
 		pr_notice("Starting new kernel\n");
 		machine_shutdown();
+
+		/* Finalize TXT registers and do SEXIT */
+		slaunch_finalize(1);
 	}
 
 	kmsg_dump(KMSG_DUMP_SHUTDOWN);
-- 
1.8.3.1


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

* [PATCH v6 11/14] reboot: Secure Launch SEXIT support on reboot paths
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

If the MLE kernel is being powered off, rebooted or halted,
then SEXIT must be called. Note that the SEXIT GETSEC leaf
can only be called after a machine_shutdown() has been done on
these paths. The machine_shutdown() is not called on a few paths
like when poweroff action does not have a poweroff callback (into
ACPI code) or when an emergency reset is done. In these cases,
just the TXT registers are finalized but SEXIT is skipped.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/kernel/reboot.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 3adbe97..732c81b 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -12,6 +12,7 @@
 #include <linux/delay.h>
 #include <linux/objtool.h>
 #include <linux/pgtable.h>
+#include <linux/slaunch.h>
 #include <acpi/reboot.h>
 #include <asm/io.h>
 #include <asm/apic.h>
@@ -720,6 +721,7 @@ static void native_machine_restart(char *__unused)
 
 	if (!reboot_force)
 		machine_shutdown();
+	slaunch_finalize(!reboot_force);
 	__machine_emergency_restart(0);
 }
 
@@ -730,6 +732,9 @@ static void native_machine_halt(void)
 
 	tboot_shutdown(TB_SHUTDOWN_HALT);
 
+	/* SEXIT done after machine_shutdown() to meet TXT requirements */
+	slaunch_finalize(1);
+
 	stop_this_cpu(NULL);
 }
 
@@ -738,8 +743,12 @@ static void native_machine_power_off(void)
 	if (kernel_can_power_off()) {
 		if (!reboot_force)
 			machine_shutdown();
+		slaunch_finalize(!reboot_force);
 		do_kernel_power_off();
+	} else {
+		slaunch_finalize(0);
 	}
+
 	/* A fallback in case there is no PM info available */
 	tboot_shutdown(TB_SHUTDOWN_HALT);
 }
@@ -767,6 +776,7 @@ void machine_shutdown(void)
 
 void machine_emergency_restart(void)
 {
+	slaunch_finalize(0);
 	__machine_emergency_restart(1);
 }
 
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 11/14] reboot: Secure Launch SEXIT support on reboot paths
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

If the MLE kernel is being powered off, rebooted or halted,
then SEXIT must be called. Note that the SEXIT GETSEC leaf
can only be called after a machine_shutdown() has been done on
these paths. The machine_shutdown() is not called on a few paths
like when poweroff action does not have a poweroff callback (into
ACPI code) or when an emergency reset is done. In these cases,
just the TXT registers are finalized but SEXIT is skipped.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/kernel/reboot.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 3adbe97..732c81b 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -12,6 +12,7 @@
 #include <linux/delay.h>
 #include <linux/objtool.h>
 #include <linux/pgtable.h>
+#include <linux/slaunch.h>
 #include <acpi/reboot.h>
 #include <asm/io.h>
 #include <asm/apic.h>
@@ -720,6 +721,7 @@ static void native_machine_restart(char *__unused)
 
 	if (!reboot_force)
 		machine_shutdown();
+	slaunch_finalize(!reboot_force);
 	__machine_emergency_restart(0);
 }
 
@@ -730,6 +732,9 @@ static void native_machine_halt(void)
 
 	tboot_shutdown(TB_SHUTDOWN_HALT);
 
+	/* SEXIT done after machine_shutdown() to meet TXT requirements */
+	slaunch_finalize(1);
+
 	stop_this_cpu(NULL);
 }
 
@@ -738,8 +743,12 @@ static void native_machine_power_off(void)
 	if (kernel_can_power_off()) {
 		if (!reboot_force)
 			machine_shutdown();
+		slaunch_finalize(!reboot_force);
 		do_kernel_power_off();
+	} else {
+		slaunch_finalize(0);
 	}
+
 	/* A fallback in case there is no PM info available */
 	tboot_shutdown(TB_SHUTDOWN_HALT);
 }
@@ -767,6 +776,7 @@ void machine_shutdown(void)
 
 void machine_emergency_restart(void)
 {
+	slaunch_finalize(0);
 	__machine_emergency_restart(1);
 }
 
-- 
1.8.3.1


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

* [PATCH v6 12/14] x86: Secure Launch late initcall platform module
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

From: "Daniel P. Smith" <dpsmith@apertussolutions.com>

The Secure Launch platform module is a late init module. During the
init call, the TPM event log is read and measurements taken in the
early boot stub code are located. These measurements are extended
into the TPM PCRs using the mainline TPM kernel driver.

The platform module also registers the securityfs nodes to allow
access to TXT register fields on Intel along with the fetching of
and writing events to the late launch TPM log.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/kernel/Makefile   |   1 +
 arch/x86/kernel/slmodule.c | 520 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 521 insertions(+)
 create mode 100644 arch/x86/kernel/slmodule.c

diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 3d2a33e..ee3fe300 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_IA32_EMULATION)	+= tls.o
 obj-y				+= step.o
 obj-$(CONFIG_INTEL_TXT)		+= tboot.o
 obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
+obj-$(CONFIG_SECURE_LAUNCH)	+= slmodule.o
 obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
 obj-y				+= stacktrace.o
 obj-y				+= cpu/
diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
new file mode 100644
index 0000000..70dcff5
--- /dev/null
+++ b/arch/x86/kernel/slmodule.c
@@ -0,0 +1,520 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Secure Launch late validation/setup, securityfs exposure and
+ * finalization support.
+ *
+ * Copyright (c) 2022 Apertus Solutions, LLC
+ * Copyright (c) 2021 Assured Information Security, Inc.
+ * Copyright (c) 2022, Oracle and/or its affiliates.
+ *
+ * Author(s):
+ *     Daniel P. Smith <dpsmith@apertussolutions.com>
+ *     Garnet T. Grimm <grimmg@ainfosec.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/security.h>
+#include <linux/memblock.h>
+#include <asm/segment.h>
+#include <asm/sections.h>
+#include <crypto/sha2.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
+
+#define DECLARE_TXT_PUB_READ_U(size, fmt, msg_size)			\
+static ssize_t txt_pub_read_u##size(unsigned int offset,		\
+		loff_t *read_offset,					\
+		size_t read_len,					\
+		char __user *buf)					\
+{									\
+	void __iomem *txt;						\
+	char msg_buffer[msg_size];					\
+	u##size reg_value = 0;						\
+	txt = ioremap(TXT_PUB_CONFIG_REGS_BASE,				\
+			TXT_NR_CONFIG_PAGES * PAGE_SIZE);		\
+	if (!txt)						\
+		return -EFAULT;					\
+	memcpy_fromio(&reg_value, txt + offset, sizeof(u##size));	\
+	iounmap(txt);							\
+	snprintf(msg_buffer, msg_size, fmt, reg_value);			\
+	return simple_read_from_buffer(buf, read_len, read_offset,	\
+			&msg_buffer, msg_size);				\
+}
+
+DECLARE_TXT_PUB_READ_U(8, "%#04x\n", 6);
+DECLARE_TXT_PUB_READ_U(32, "%#010x\n", 12);
+DECLARE_TXT_PUB_READ_U(64, "%#018llx\n", 20);
+
+#define DECLARE_TXT_FOPS(reg_name, reg_offset, reg_size)		\
+static ssize_t txt_##reg_name##_read(struct file *flip,			\
+		char __user *buf, size_t read_len, loff_t *read_offset)	\
+{									\
+	return txt_pub_read_u##reg_size(reg_offset, read_offset,	\
+			read_len, buf);					\
+}									\
+static const struct file_operations reg_name##_ops = {			\
+	.read = txt_##reg_name##_read,					\
+}
+
+DECLARE_TXT_FOPS(sts, TXT_CR_STS, 64);
+DECLARE_TXT_FOPS(ests, TXT_CR_ESTS, 8);
+DECLARE_TXT_FOPS(errorcode, TXT_CR_ERRORCODE, 32);
+DECLARE_TXT_FOPS(didvid, TXT_CR_DIDVID, 64);
+DECLARE_TXT_FOPS(e2sts, TXT_CR_E2STS, 64);
+DECLARE_TXT_FOPS(ver_emif, TXT_CR_VER_EMIF, 32);
+DECLARE_TXT_FOPS(scratchpad, TXT_CR_SCRATCHPAD, 64);
+
+/*
+ * Securityfs exposure
+ */
+struct memfile {
+	char *name;
+	void *addr;
+	size_t size;
+};
+
+static struct memfile sl_evtlog = {"eventlog", 0, 0};
+static void *txt_heap;
+static struct txt_heap_event_log_pointer2_1_element __iomem *evtlog20;
+static DEFINE_MUTEX(sl_evt_log_mutex);
+
+static ssize_t sl_evtlog_read(struct file *file, char __user *buf,
+			      size_t count, loff_t *pos)
+{
+	ssize_t size;
+
+	if (!sl_evtlog.addr)
+		return 0;
+
+	mutex_lock(&sl_evt_log_mutex);
+	size = simple_read_from_buffer(buf, count, pos, sl_evtlog.addr,
+				       sl_evtlog.size);
+	mutex_unlock(&sl_evt_log_mutex);
+
+	return size;
+}
+
+static ssize_t sl_evtlog_write(struct file *file, const char __user *buf,
+				size_t datalen, loff_t *ppos)
+{
+	ssize_t result;
+	char *data;
+
+	if (!sl_evtlog.addr)
+		return 0;
+
+	/* No partial writes. */
+	result = -EINVAL;
+	if (*ppos != 0)
+		goto out;
+
+	data = memdup_user(buf, datalen);
+	if (IS_ERR(data)) {
+		result = PTR_ERR(data);
+		goto out;
+	}
+
+	mutex_lock(&sl_evt_log_mutex);
+	if (evtlog20)
+		result = tpm20_log_event(evtlog20, sl_evtlog.addr,
+					 sl_evtlog.size, datalen, data);
+	else
+		result = tpm12_log_event(sl_evtlog.addr, sl_evtlog.size,
+					 datalen, data);
+	mutex_unlock(&sl_evt_log_mutex);
+
+	kfree(data);
+out:
+	return result;
+}
+
+static const struct file_operations sl_evtlog_ops = {
+	.read = sl_evtlog_read,
+	.write = sl_evtlog_write,
+	.llseek	= default_llseek,
+};
+
+struct sfs_file {
+	const char *name;
+	const struct file_operations *fops;
+};
+
+#define SL_TXT_ENTRY_COUNT	7
+static const struct sfs_file sl_txt_files[] = {
+	{ "sts", &sts_ops },
+	{ "ests", &ests_ops },
+	{ "errorcode", &errorcode_ops },
+	{ "didvid", &didvid_ops },
+	{ "ver_emif", &ver_emif_ops },
+	{ "scratchpad", &scratchpad_ops },
+	{ "e2sts", &e2sts_ops }
+};
+
+/* sysfs file handles */
+static struct dentry *slaunch_dir;
+static struct dentry *event_file;
+static struct dentry *txt_dir;
+static struct dentry *txt_entries[SL_TXT_ENTRY_COUNT];
+
+static long slaunch_expose_securityfs(void)
+{
+	long ret = 0;
+	int i;
+
+	slaunch_dir = securityfs_create_dir("slaunch", NULL);
+	if (IS_ERR(slaunch_dir))
+		return PTR_ERR(slaunch_dir);
+
+	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
+		txt_dir = securityfs_create_dir("txt", slaunch_dir);
+		if (IS_ERR(txt_dir)) {
+			ret = PTR_ERR(txt_dir);
+			goto remove_slaunch;
+		}
+
+		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++) {
+			txt_entries[i] = securityfs_create_file(
+						sl_txt_files[i].name, 0440,
+						txt_dir, NULL,
+						sl_txt_files[i].fops);
+			if (IS_ERR(txt_entries[i])) {
+				ret = PTR_ERR(txt_entries[i]);
+				goto remove_files;
+			}
+		}
+
+	}
+
+	if (sl_evtlog.addr > 0) {
+		event_file = securityfs_create_file(
+					sl_evtlog.name, 0440,
+					slaunch_dir, NULL,
+					&sl_evtlog_ops);
+		if (IS_ERR(event_file)) {
+			ret = PTR_ERR(event_file);
+			goto remove_files;
+		}
+	}
+
+	return 0;
+
+remove_files:
+	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
+		while (--i >= 0)
+			securityfs_remove(txt_entries[i]);
+		securityfs_remove(txt_dir);
+	}
+remove_slaunch:
+	securityfs_remove(slaunch_dir);
+
+	return ret;
+}
+
+static void slaunch_teardown_securityfs(void)
+{
+	int i;
+
+	securityfs_remove(event_file);
+	if (sl_evtlog.addr) {
+		memunmap(sl_evtlog.addr);
+		sl_evtlog.addr = NULL;
+	}
+	sl_evtlog.size = 0;
+
+	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
+		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++)
+			securityfs_remove(txt_entries[i]);
+
+		securityfs_remove(txt_dir);
+
+		if (txt_heap) {
+			memunmap(txt_heap);
+			txt_heap = NULL;
+		}
+	}
+
+	securityfs_remove(slaunch_dir);
+}
+
+static void slaunch_intel_evtlog(void __iomem *txt)
+{
+	struct slr_entry_log_info *log_info;
+	struct txt_os_mle_data *params;
+	struct slr_table *slrt;
+	void *os_sinit_data;
+	u64 base, size;
+
+	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
+	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
+
+	/* now map TXT heap */
+	txt_heap = memremap(base, size, MEMREMAP_WB);
+	if (!txt_heap)
+		slaunch_txt_reset(txt,
+			"Error failed to memremap TXT heap\n",
+			SL_ERROR_HEAP_MAP);
+
+	params = (struct txt_os_mle_data *)txt_os_mle_data_start(txt_heap);
+
+	/* Get the SLRT and remap it */
+	slrt = memremap(params->slrt, sizeof(*slrt), MEMREMAP_WB);
+	if (!slrt)
+		slaunch_txt_reset(txt,
+			"Error failed to memremap SLR Table\n",
+			SL_ERROR_SLRT_MAP);
+	size = slrt->size;
+	memunmap(slrt);
+
+	slrt = memremap(params->slrt, size, MEMREMAP_WB);
+	if (!slrt)
+		slaunch_txt_reset(txt,
+			"Error failed to memremap SLR Table\n",
+			SL_ERROR_SLRT_MAP);
+
+	log_info = (struct slr_entry_log_info *)
+			slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
+	if (!log_info)
+		slaunch_txt_reset(txt,
+			"Error failed to memremap SLR Table\n",
+			SL_ERROR_SLRT_MISSING_ENTRY);
+
+	sl_evtlog.size = log_info->size;
+	sl_evtlog.addr = memremap(log_info->addr, log_info->size,
+				  MEMREMAP_WB);
+	if (!sl_evtlog.addr)
+		slaunch_txt_reset(txt,
+			"Error failed to memremap TPM event log\n",
+			SL_ERROR_EVENTLOG_MAP);
+
+	memunmap(slrt);
+
+	/* Determine if this is TPM 1.2 or 2.0 event log */
+	if (memcmp(sl_evtlog.addr + sizeof(struct tcg_pcr_event),
+		    TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
+		return; /* looks like it is not 2.0 */
+
+	/* For TPM 2.0 logs, the extended heap element must be located */
+	os_sinit_data = txt_os_sinit_data_start(txt_heap);
+
+	evtlog20 = tpm20_find_log2_1_element(os_sinit_data);
+
+	/*
+	 * If this fails, things are in really bad shape. Any attempt to write
+	 * events to the log will fail.
+	 */
+	if (!evtlog20)
+		slaunch_txt_reset(txt,
+			"Error failed to find TPM20 event log element\n",
+			SL_ERROR_TPM_INVALID_LOG20);
+}
+
+static void slaunch_tpm20_extend_event(struct tpm_chip *tpm, void __iomem *txt,
+				       struct tcg_pcr_event2_head *event)
+{
+	u16 *alg_id_field = (u16 *)((u8 *)event +
+				    sizeof(struct tcg_pcr_event2_head));
+	struct tpm_digest *digests;
+	u8 *dptr;
+	int ret;
+	u32 i, j;
+
+	digests = kcalloc(tpm->nr_allocated_banks, sizeof(*digests),
+			  GFP_KERNEL);
+	if (!digests)
+		slaunch_txt_reset(txt,
+			"Failed to allocate array of digests\n",
+			SL_ERROR_GENERIC);
+
+	for (i = 0; i < tpm->nr_allocated_banks; i++)
+		digests[i].alg_id = tpm->allocated_banks[i].alg_id;
+
+
+	/* Early SL code ensured there was a max count of 2 digests */
+	for (i = 0; i < event->count; i++) {
+		dptr = (u8 *)alg_id_field + sizeof(u16);
+
+		for (j = 0; j < tpm->nr_allocated_banks; j++) {
+			if (digests[j].alg_id != *alg_id_field)
+				continue;
+
+			switch (digests[j].alg_id) {
+			case TPM_ALG_SHA256:
+				memcpy(&digests[j].digest[0], dptr,
+				       SHA256_DIGEST_SIZE);
+				alg_id_field = (u16 *)((u8 *)alg_id_field +
+					SHA256_DIGEST_SIZE + sizeof(u16));
+				break;
+			case TPM_ALG_SHA1:
+				memcpy(&digests[j].digest[0], dptr,
+				       SHA1_DIGEST_SIZE);
+				alg_id_field = (u16 *)((u8 *)alg_id_field +
+					SHA1_DIGEST_SIZE + sizeof(u16));
+			default:
+				break;
+			}
+		}
+	}
+
+	ret = tpm_pcr_extend(tpm, event->pcr_idx, digests);
+	if (ret) {
+		pr_err("Error extending TPM20 PCR, result: %d\n", ret);
+		slaunch_txt_reset(txt,
+			"Failed to extend TPM20 PCR\n",
+			SL_ERROR_TPM_EXTEND);
+	}
+
+	kfree(digests);
+}
+
+static void slaunch_tpm20_extend(struct tpm_chip *tpm, void __iomem *txt)
+{
+	struct tcg_pcr_event *event_header;
+	struct tcg_pcr_event2_head *event;
+	int start = 0, end = 0, size;
+
+	event_header = (struct tcg_pcr_event *)(sl_evtlog.addr +
+						evtlog20->first_record_offset);
+
+	/* Skip first TPM 1.2 event to get to first TPM 2.0 event */
+	event = (struct tcg_pcr_event2_head *)((u8 *)event_header +
+						sizeof(struct tcg_pcr_event) +
+						event_header->event_size);
+
+	while ((void  *)event < sl_evtlog.addr + evtlog20->next_record_offset) {
+		size = __calc_tpm2_event_size(event, event_header, false);
+		if (!size)
+			slaunch_txt_reset(txt,
+				"TPM20 invalid event in event log\n",
+				SL_ERROR_TPM_INVALID_EVENT);
+
+		/*
+		 * Marker events indicate where the Secure Launch early stub
+		 * started and ended adding post launch events.
+		 */
+		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
+			end = 1;
+			break;
+		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
+			start = 1;
+			goto next;
+		}
+
+		if (start)
+			slaunch_tpm20_extend_event(tpm, txt, event);
+
+next:
+		event = (struct tcg_pcr_event2_head *)((u8 *)event + size);
+	}
+
+	if (!start || !end)
+		slaunch_txt_reset(txt,
+			"Missing start or end events for extending TPM20 PCRs\n",
+			SL_ERROR_TPM_EXTEND);
+}
+
+static void slaunch_tpm12_extend(struct tpm_chip *tpm, void __iomem *txt)
+{
+	struct tpm12_event_log_header *event_header;
+	struct tcg_pcr_event *event;
+	struct tpm_digest digest;
+	int start = 0, end = 0;
+	int size, ret;
+
+	event_header = (struct tpm12_event_log_header *)sl_evtlog.addr;
+	event = (struct tcg_pcr_event *)((u8 *)event_header +
+				sizeof(struct tpm12_event_log_header));
+
+	while ((void  *)event < sl_evtlog.addr + event_header->next_event_offset) {
+		size = sizeof(struct tcg_pcr_event) + event->event_size;
+
+		/*
+		 * Marker events indicate where the Secure Launch early stub
+		 * started and ended adding post launch events.
+		 */
+		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
+			end = 1;
+			break;
+		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
+			start = 1;
+			goto next;
+		}
+
+		if (start) {
+			memset(&digest.digest[0], 0, TPM_MAX_DIGEST_SIZE);
+			digest.alg_id = TPM_ALG_SHA1;
+			memcpy(&digest.digest[0], &event->digest[0],
+			       SHA1_DIGEST_SIZE);
+
+			ret = tpm_pcr_extend(tpm, event->pcr_idx, &digest);
+			if (ret) {
+				pr_err("Error extending TPM12 PCR, result: %d\n", ret);
+				slaunch_txt_reset(txt,
+					"Failed to extend TPM12 PCR\n",
+					SL_ERROR_TPM_EXTEND);
+			}
+		}
+
+next:
+		event = (struct tcg_pcr_event *)((u8 *)event + size);
+	}
+
+	if (!start || !end)
+		slaunch_txt_reset(txt,
+			"Missing start or end events for extending TPM12 PCRs\n",
+			SL_ERROR_TPM_EXTEND);
+}
+
+static void slaunch_pcr_extend(void __iomem *txt)
+{
+	struct tpm_chip *tpm;
+
+	tpm = tpm_default_chip();
+	if (!tpm)
+		slaunch_txt_reset(txt,
+			"Could not get default TPM chip\n",
+			SL_ERROR_TPM_INIT);
+	if (evtlog20)
+		slaunch_tpm20_extend(tpm, txt);
+	else
+		slaunch_tpm12_extend(tpm, txt);
+}
+
+static int __init slaunch_module_init(void)
+{
+	void __iomem *txt;
+
+	/* Check to see if Secure Launch happened */
+	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
+	    (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT))
+		return 0;
+
+	txt = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
+		      PAGE_SIZE);
+	if (!txt)
+		panic("Error ioremap of TXT priv registers\n");
+
+	/* Only Intel TXT is supported at this point */
+	slaunch_intel_evtlog(txt);
+
+	slaunch_pcr_extend(txt);
+
+	iounmap(txt);
+
+	return slaunch_expose_securityfs();
+}
+
+static void __exit slaunch_module_exit(void)
+{
+	slaunch_teardown_securityfs();
+}
+
+late_initcall(slaunch_module_init);
+
+__exitcall(slaunch_module_exit);
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 12/14] x86: Secure Launch late initcall platform module
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

From: "Daniel P. Smith" <dpsmith@apertussolutions.com>

The Secure Launch platform module is a late init module. During the
init call, the TPM event log is read and measurements taken in the
early boot stub code are located. These measurements are extended
into the TPM PCRs using the mainline TPM kernel driver.

The platform module also registers the securityfs nodes to allow
access to TXT register fields on Intel along with the fetching of
and writing events to the late launch TPM log.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/kernel/Makefile   |   1 +
 arch/x86/kernel/slmodule.c | 520 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 521 insertions(+)
 create mode 100644 arch/x86/kernel/slmodule.c

diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 3d2a33e..ee3fe300 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_IA32_EMULATION)	+= tls.o
 obj-y				+= step.o
 obj-$(CONFIG_INTEL_TXT)		+= tboot.o
 obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
+obj-$(CONFIG_SECURE_LAUNCH)	+= slmodule.o
 obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
 obj-y				+= stacktrace.o
 obj-y				+= cpu/
diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
new file mode 100644
index 0000000..70dcff5
--- /dev/null
+++ b/arch/x86/kernel/slmodule.c
@@ -0,0 +1,520 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Secure Launch late validation/setup, securityfs exposure and
+ * finalization support.
+ *
+ * Copyright (c) 2022 Apertus Solutions, LLC
+ * Copyright (c) 2021 Assured Information Security, Inc.
+ * Copyright (c) 2022, Oracle and/or its affiliates.
+ *
+ * Author(s):
+ *     Daniel P. Smith <dpsmith@apertussolutions.com>
+ *     Garnet T. Grimm <grimmg@ainfosec.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/security.h>
+#include <linux/memblock.h>
+#include <asm/segment.h>
+#include <asm/sections.h>
+#include <crypto/sha2.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
+
+#define DECLARE_TXT_PUB_READ_U(size, fmt, msg_size)			\
+static ssize_t txt_pub_read_u##size(unsigned int offset,		\
+		loff_t *read_offset,					\
+		size_t read_len,					\
+		char __user *buf)					\
+{									\
+	void __iomem *txt;						\
+	char msg_buffer[msg_size];					\
+	u##size reg_value = 0;						\
+	txt = ioremap(TXT_PUB_CONFIG_REGS_BASE,				\
+			TXT_NR_CONFIG_PAGES * PAGE_SIZE);		\
+	if (!txt)						\
+		return -EFAULT;					\
+	memcpy_fromio(&reg_value, txt + offset, sizeof(u##size));	\
+	iounmap(txt);							\
+	snprintf(msg_buffer, msg_size, fmt, reg_value);			\
+	return simple_read_from_buffer(buf, read_len, read_offset,	\
+			&msg_buffer, msg_size);				\
+}
+
+DECLARE_TXT_PUB_READ_U(8, "%#04x\n", 6);
+DECLARE_TXT_PUB_READ_U(32, "%#010x\n", 12);
+DECLARE_TXT_PUB_READ_U(64, "%#018llx\n", 20);
+
+#define DECLARE_TXT_FOPS(reg_name, reg_offset, reg_size)		\
+static ssize_t txt_##reg_name##_read(struct file *flip,			\
+		char __user *buf, size_t read_len, loff_t *read_offset)	\
+{									\
+	return txt_pub_read_u##reg_size(reg_offset, read_offset,	\
+			read_len, buf);					\
+}									\
+static const struct file_operations reg_name##_ops = {			\
+	.read = txt_##reg_name##_read,					\
+}
+
+DECLARE_TXT_FOPS(sts, TXT_CR_STS, 64);
+DECLARE_TXT_FOPS(ests, TXT_CR_ESTS, 8);
+DECLARE_TXT_FOPS(errorcode, TXT_CR_ERRORCODE, 32);
+DECLARE_TXT_FOPS(didvid, TXT_CR_DIDVID, 64);
+DECLARE_TXT_FOPS(e2sts, TXT_CR_E2STS, 64);
+DECLARE_TXT_FOPS(ver_emif, TXT_CR_VER_EMIF, 32);
+DECLARE_TXT_FOPS(scratchpad, TXT_CR_SCRATCHPAD, 64);
+
+/*
+ * Securityfs exposure
+ */
+struct memfile {
+	char *name;
+	void *addr;
+	size_t size;
+};
+
+static struct memfile sl_evtlog = {"eventlog", 0, 0};
+static void *txt_heap;
+static struct txt_heap_event_log_pointer2_1_element __iomem *evtlog20;
+static DEFINE_MUTEX(sl_evt_log_mutex);
+
+static ssize_t sl_evtlog_read(struct file *file, char __user *buf,
+			      size_t count, loff_t *pos)
+{
+	ssize_t size;
+
+	if (!sl_evtlog.addr)
+		return 0;
+
+	mutex_lock(&sl_evt_log_mutex);
+	size = simple_read_from_buffer(buf, count, pos, sl_evtlog.addr,
+				       sl_evtlog.size);
+	mutex_unlock(&sl_evt_log_mutex);
+
+	return size;
+}
+
+static ssize_t sl_evtlog_write(struct file *file, const char __user *buf,
+				size_t datalen, loff_t *ppos)
+{
+	ssize_t result;
+	char *data;
+
+	if (!sl_evtlog.addr)
+		return 0;
+
+	/* No partial writes. */
+	result = -EINVAL;
+	if (*ppos != 0)
+		goto out;
+
+	data = memdup_user(buf, datalen);
+	if (IS_ERR(data)) {
+		result = PTR_ERR(data);
+		goto out;
+	}
+
+	mutex_lock(&sl_evt_log_mutex);
+	if (evtlog20)
+		result = tpm20_log_event(evtlog20, sl_evtlog.addr,
+					 sl_evtlog.size, datalen, data);
+	else
+		result = tpm12_log_event(sl_evtlog.addr, sl_evtlog.size,
+					 datalen, data);
+	mutex_unlock(&sl_evt_log_mutex);
+
+	kfree(data);
+out:
+	return result;
+}
+
+static const struct file_operations sl_evtlog_ops = {
+	.read = sl_evtlog_read,
+	.write = sl_evtlog_write,
+	.llseek	= default_llseek,
+};
+
+struct sfs_file {
+	const char *name;
+	const struct file_operations *fops;
+};
+
+#define SL_TXT_ENTRY_COUNT	7
+static const struct sfs_file sl_txt_files[] = {
+	{ "sts", &sts_ops },
+	{ "ests", &ests_ops },
+	{ "errorcode", &errorcode_ops },
+	{ "didvid", &didvid_ops },
+	{ "ver_emif", &ver_emif_ops },
+	{ "scratchpad", &scratchpad_ops },
+	{ "e2sts", &e2sts_ops }
+};
+
+/* sysfs file handles */
+static struct dentry *slaunch_dir;
+static struct dentry *event_file;
+static struct dentry *txt_dir;
+static struct dentry *txt_entries[SL_TXT_ENTRY_COUNT];
+
+static long slaunch_expose_securityfs(void)
+{
+	long ret = 0;
+	int i;
+
+	slaunch_dir = securityfs_create_dir("slaunch", NULL);
+	if (IS_ERR(slaunch_dir))
+		return PTR_ERR(slaunch_dir);
+
+	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
+		txt_dir = securityfs_create_dir("txt", slaunch_dir);
+		if (IS_ERR(txt_dir)) {
+			ret = PTR_ERR(txt_dir);
+			goto remove_slaunch;
+		}
+
+		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++) {
+			txt_entries[i] = securityfs_create_file(
+						sl_txt_files[i].name, 0440,
+						txt_dir, NULL,
+						sl_txt_files[i].fops);
+			if (IS_ERR(txt_entries[i])) {
+				ret = PTR_ERR(txt_entries[i]);
+				goto remove_files;
+			}
+		}
+
+	}
+
+	if (sl_evtlog.addr > 0) {
+		event_file = securityfs_create_file(
+					sl_evtlog.name, 0440,
+					slaunch_dir, NULL,
+					&sl_evtlog_ops);
+		if (IS_ERR(event_file)) {
+			ret = PTR_ERR(event_file);
+			goto remove_files;
+		}
+	}
+
+	return 0;
+
+remove_files:
+	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
+		while (--i >= 0)
+			securityfs_remove(txt_entries[i]);
+		securityfs_remove(txt_dir);
+	}
+remove_slaunch:
+	securityfs_remove(slaunch_dir);
+
+	return ret;
+}
+
+static void slaunch_teardown_securityfs(void)
+{
+	int i;
+
+	securityfs_remove(event_file);
+	if (sl_evtlog.addr) {
+		memunmap(sl_evtlog.addr);
+		sl_evtlog.addr = NULL;
+	}
+	sl_evtlog.size = 0;
+
+	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
+		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++)
+			securityfs_remove(txt_entries[i]);
+
+		securityfs_remove(txt_dir);
+
+		if (txt_heap) {
+			memunmap(txt_heap);
+			txt_heap = NULL;
+		}
+	}
+
+	securityfs_remove(slaunch_dir);
+}
+
+static void slaunch_intel_evtlog(void __iomem *txt)
+{
+	struct slr_entry_log_info *log_info;
+	struct txt_os_mle_data *params;
+	struct slr_table *slrt;
+	void *os_sinit_data;
+	u64 base, size;
+
+	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
+	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
+
+	/* now map TXT heap */
+	txt_heap = memremap(base, size, MEMREMAP_WB);
+	if (!txt_heap)
+		slaunch_txt_reset(txt,
+			"Error failed to memremap TXT heap\n",
+			SL_ERROR_HEAP_MAP);
+
+	params = (struct txt_os_mle_data *)txt_os_mle_data_start(txt_heap);
+
+	/* Get the SLRT and remap it */
+	slrt = memremap(params->slrt, sizeof(*slrt), MEMREMAP_WB);
+	if (!slrt)
+		slaunch_txt_reset(txt,
+			"Error failed to memremap SLR Table\n",
+			SL_ERROR_SLRT_MAP);
+	size = slrt->size;
+	memunmap(slrt);
+
+	slrt = memremap(params->slrt, size, MEMREMAP_WB);
+	if (!slrt)
+		slaunch_txt_reset(txt,
+			"Error failed to memremap SLR Table\n",
+			SL_ERROR_SLRT_MAP);
+
+	log_info = (struct slr_entry_log_info *)
+			slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
+	if (!log_info)
+		slaunch_txt_reset(txt,
+			"Error failed to memremap SLR Table\n",
+			SL_ERROR_SLRT_MISSING_ENTRY);
+
+	sl_evtlog.size = log_info->size;
+	sl_evtlog.addr = memremap(log_info->addr, log_info->size,
+				  MEMREMAP_WB);
+	if (!sl_evtlog.addr)
+		slaunch_txt_reset(txt,
+			"Error failed to memremap TPM event log\n",
+			SL_ERROR_EVENTLOG_MAP);
+
+	memunmap(slrt);
+
+	/* Determine if this is TPM 1.2 or 2.0 event log */
+	if (memcmp(sl_evtlog.addr + sizeof(struct tcg_pcr_event),
+		    TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
+		return; /* looks like it is not 2.0 */
+
+	/* For TPM 2.0 logs, the extended heap element must be located */
+	os_sinit_data = txt_os_sinit_data_start(txt_heap);
+
+	evtlog20 = tpm20_find_log2_1_element(os_sinit_data);
+
+	/*
+	 * If this fails, things are in really bad shape. Any attempt to write
+	 * events to the log will fail.
+	 */
+	if (!evtlog20)
+		slaunch_txt_reset(txt,
+			"Error failed to find TPM20 event log element\n",
+			SL_ERROR_TPM_INVALID_LOG20);
+}
+
+static void slaunch_tpm20_extend_event(struct tpm_chip *tpm, void __iomem *txt,
+				       struct tcg_pcr_event2_head *event)
+{
+	u16 *alg_id_field = (u16 *)((u8 *)event +
+				    sizeof(struct tcg_pcr_event2_head));
+	struct tpm_digest *digests;
+	u8 *dptr;
+	int ret;
+	u32 i, j;
+
+	digests = kcalloc(tpm->nr_allocated_banks, sizeof(*digests),
+			  GFP_KERNEL);
+	if (!digests)
+		slaunch_txt_reset(txt,
+			"Failed to allocate array of digests\n",
+			SL_ERROR_GENERIC);
+
+	for (i = 0; i < tpm->nr_allocated_banks; i++)
+		digests[i].alg_id = tpm->allocated_banks[i].alg_id;
+
+
+	/* Early SL code ensured there was a max count of 2 digests */
+	for (i = 0; i < event->count; i++) {
+		dptr = (u8 *)alg_id_field + sizeof(u16);
+
+		for (j = 0; j < tpm->nr_allocated_banks; j++) {
+			if (digests[j].alg_id != *alg_id_field)
+				continue;
+
+			switch (digests[j].alg_id) {
+			case TPM_ALG_SHA256:
+				memcpy(&digests[j].digest[0], dptr,
+				       SHA256_DIGEST_SIZE);
+				alg_id_field = (u16 *)((u8 *)alg_id_field +
+					SHA256_DIGEST_SIZE + sizeof(u16));
+				break;
+			case TPM_ALG_SHA1:
+				memcpy(&digests[j].digest[0], dptr,
+				       SHA1_DIGEST_SIZE);
+				alg_id_field = (u16 *)((u8 *)alg_id_field +
+					SHA1_DIGEST_SIZE + sizeof(u16));
+			default:
+				break;
+			}
+		}
+	}
+
+	ret = tpm_pcr_extend(tpm, event->pcr_idx, digests);
+	if (ret) {
+		pr_err("Error extending TPM20 PCR, result: %d\n", ret);
+		slaunch_txt_reset(txt,
+			"Failed to extend TPM20 PCR\n",
+			SL_ERROR_TPM_EXTEND);
+	}
+
+	kfree(digests);
+}
+
+static void slaunch_tpm20_extend(struct tpm_chip *tpm, void __iomem *txt)
+{
+	struct tcg_pcr_event *event_header;
+	struct tcg_pcr_event2_head *event;
+	int start = 0, end = 0, size;
+
+	event_header = (struct tcg_pcr_event *)(sl_evtlog.addr +
+						evtlog20->first_record_offset);
+
+	/* Skip first TPM 1.2 event to get to first TPM 2.0 event */
+	event = (struct tcg_pcr_event2_head *)((u8 *)event_header +
+						sizeof(struct tcg_pcr_event) +
+						event_header->event_size);
+
+	while ((void  *)event < sl_evtlog.addr + evtlog20->next_record_offset) {
+		size = __calc_tpm2_event_size(event, event_header, false);
+		if (!size)
+			slaunch_txt_reset(txt,
+				"TPM20 invalid event in event log\n",
+				SL_ERROR_TPM_INVALID_EVENT);
+
+		/*
+		 * Marker events indicate where the Secure Launch early stub
+		 * started and ended adding post launch events.
+		 */
+		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
+			end = 1;
+			break;
+		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
+			start = 1;
+			goto next;
+		}
+
+		if (start)
+			slaunch_tpm20_extend_event(tpm, txt, event);
+
+next:
+		event = (struct tcg_pcr_event2_head *)((u8 *)event + size);
+	}
+
+	if (!start || !end)
+		slaunch_txt_reset(txt,
+			"Missing start or end events for extending TPM20 PCRs\n",
+			SL_ERROR_TPM_EXTEND);
+}
+
+static void slaunch_tpm12_extend(struct tpm_chip *tpm, void __iomem *txt)
+{
+	struct tpm12_event_log_header *event_header;
+	struct tcg_pcr_event *event;
+	struct tpm_digest digest;
+	int start = 0, end = 0;
+	int size, ret;
+
+	event_header = (struct tpm12_event_log_header *)sl_evtlog.addr;
+	event = (struct tcg_pcr_event *)((u8 *)event_header +
+				sizeof(struct tpm12_event_log_header));
+
+	while ((void  *)event < sl_evtlog.addr + event_header->next_event_offset) {
+		size = sizeof(struct tcg_pcr_event) + event->event_size;
+
+		/*
+		 * Marker events indicate where the Secure Launch early stub
+		 * started and ended adding post launch events.
+		 */
+		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
+			end = 1;
+			break;
+		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
+			start = 1;
+			goto next;
+		}
+
+		if (start) {
+			memset(&digest.digest[0], 0, TPM_MAX_DIGEST_SIZE);
+			digest.alg_id = TPM_ALG_SHA1;
+			memcpy(&digest.digest[0], &event->digest[0],
+			       SHA1_DIGEST_SIZE);
+
+			ret = tpm_pcr_extend(tpm, event->pcr_idx, &digest);
+			if (ret) {
+				pr_err("Error extending TPM12 PCR, result: %d\n", ret);
+				slaunch_txt_reset(txt,
+					"Failed to extend TPM12 PCR\n",
+					SL_ERROR_TPM_EXTEND);
+			}
+		}
+
+next:
+		event = (struct tcg_pcr_event *)((u8 *)event + size);
+	}
+
+	if (!start || !end)
+		slaunch_txt_reset(txt,
+			"Missing start or end events for extending TPM12 PCRs\n",
+			SL_ERROR_TPM_EXTEND);
+}
+
+static void slaunch_pcr_extend(void __iomem *txt)
+{
+	struct tpm_chip *tpm;
+
+	tpm = tpm_default_chip();
+	if (!tpm)
+		slaunch_txt_reset(txt,
+			"Could not get default TPM chip\n",
+			SL_ERROR_TPM_INIT);
+	if (evtlog20)
+		slaunch_tpm20_extend(tpm, txt);
+	else
+		slaunch_tpm12_extend(tpm, txt);
+}
+
+static int __init slaunch_module_init(void)
+{
+	void __iomem *txt;
+
+	/* Check to see if Secure Launch happened */
+	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
+	    (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT))
+		return 0;
+
+	txt = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
+		      PAGE_SIZE);
+	if (!txt)
+		panic("Error ioremap of TXT priv registers\n");
+
+	/* Only Intel TXT is supported at this point */
+	slaunch_intel_evtlog(txt);
+
+	slaunch_pcr_extend(txt);
+
+	iounmap(txt);
+
+	return slaunch_expose_securityfs();
+}
+
+static void __exit slaunch_module_exit(void)
+{
+	slaunch_teardown_securityfs();
+}
+
+late_initcall(slaunch_module_init);
+
+__exitcall(slaunch_module_exit);
-- 
1.8.3.1


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

* [PATCH v6 13/14] tpm: Allow locality 2 to be set when initializing the TPM for Secure Launch
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

The Secure Launch MLE environment uses PCRs that are only accessible from
the DRTM locality 2. By default the TPM drivers always initialize the
locality to 0. When a Secure Launch is in progress, initialize the
locality to 2.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 drivers/char/tpm/tpm-chip.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 80aaa10..5dd2eed 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -23,6 +23,7 @@
 #include <linux/major.h>
 #include <linux/tpm_eventlog.h>
 #include <linux/hw_random.h>
+#include <linux/slaunch.h>
 #include "tpm.h"
 
 DEFINE_IDR(dev_nums_idr);
@@ -34,12 +35,18 @@
 
 static int tpm_request_locality(struct tpm_chip *chip)
 {
+	int locality;
 	int rc;
 
 	if (!chip->ops->request_locality)
 		return 0;
 
-	rc = chip->ops->request_locality(chip, 0);
+	if (slaunch_get_flags() & SL_FLAG_ACTIVE)
+		locality = 2;
+	else
+		locality = 0;
+
+	rc = chip->ops->request_locality(chip, locality);
 	if (rc < 0)
 		return rc;
 
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 13/14] tpm: Allow locality 2 to be set when initializing the TPM for Secure Launch
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

The Secure Launch MLE environment uses PCRs that are only accessible from
the DRTM locality 2. By default the TPM drivers always initialize the
locality to 0. When a Secure Launch is in progress, initialize the
locality to 2.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 drivers/char/tpm/tpm-chip.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 80aaa10..5dd2eed 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -23,6 +23,7 @@
 #include <linux/major.h>
 #include <linux/tpm_eventlog.h>
 #include <linux/hw_random.h>
+#include <linux/slaunch.h>
 #include "tpm.h"
 
 DEFINE_IDR(dev_nums_idr);
@@ -34,12 +35,18 @@
 
 static int tpm_request_locality(struct tpm_chip *chip)
 {
+	int locality;
 	int rc;
 
 	if (!chip->ops->request_locality)
 		return 0;
 
-	rc = chip->ops->request_locality(chip, 0);
+	if (slaunch_get_flags() & SL_FLAG_ACTIVE)
+		locality = 2;
+	else
+		locality = 0;
+
+	rc = chip->ops->request_locality(chip, locality);
 	if (rc < 0)
 		return rc;
 
-- 
1.8.3.1


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

* [PATCH v6 14/14] x86: EFI stub DRTM launch support for Secure Launch
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-04 14:50   ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

This support allows the DRTM launch to be initiated after and EFI stub
launch of the Linux kernel is done. This is accomplished by providing
a handler to jump to when a Secure Launch is in progress.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 drivers/firmware/efi/libstub/x86-stub.c | 55 +++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index a0bfd31..66ff922 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -9,6 +9,7 @@
 #include <linux/efi.h>
 #include <linux/pci.h>
 #include <linux/stddef.h>
+#include <linux/slr_table.h>
 
 #include <asm/efi.h>
 #include <asm/e820/types.h>
@@ -760,6 +761,57 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
 	return EFI_SUCCESS;
 }
 
+static void efi_secure_launch(struct boot_params *boot_params)
+{
+	struct slr_entry_uefi_config *uefi_config;
+	struct slr_uefi_cfg_entry *uefi_entry;
+	struct slr_entry_dl_info *dlinfo;
+	efi_guid_t guid = SLR_TABLE_GUID;
+	struct slr_table *slrt;
+	u64 memmap_hi;
+	void *table;
+	u8 buf[64] = {0};
+
+	table = get_efi_config_table(guid);
+
+	/*
+	 * The presence of this table indicated a Secure Launch
+	 * is being requested.
+	 */
+	if (!table)
+		return;
+
+	slrt = (struct slr_table *)table;
+
+	if (slrt->magic != SLR_TABLE_MAGIC)
+		return;
+
+	/* Add config information to measure the UEFI memory map */
+	uefi_config = (struct slr_entry_uefi_config *)buf;
+	uefi_config->hdr.tag = SLR_ENTRY_UEFI_CONFIG;
+	uefi_config->hdr.size = sizeof(*uefi_config) + sizeof(*uefi_entry);
+	uefi_config->revision = SLR_UEFI_CONFIG_REVISION;
+	uefi_config->nr_entries = 1;
+	uefi_entry = (struct slr_uefi_cfg_entry *)(buf + sizeof(*uefi_config));
+	uefi_entry->pcr = 18;
+	uefi_entry->cfg = boot_params->efi_info.efi_memmap;
+	memmap_hi = boot_params->efi_info.efi_memmap_hi;
+	uefi_entry->cfg |= memmap_hi << 32;
+	uefi_entry->size = boot_params->efi_info.efi_memmap_size;
+	memcpy(&uefi_entry->evt_info[0], "Measured UEFI memory map",
+		strlen("Measured UEFI memory map"));
+
+	if (slr_add_entry(slrt, (struct slr_entry_hdr *)uefi_config))
+		return;
+
+	/* Jump through DL stub to initiate Secure Launch */
+	dlinfo = (struct slr_entry_dl_info *)
+		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_DL_INFO);
+
+	asm volatile ("jmp *%%rax"
+		      : : "a" (dlinfo->dl_handler), "D" (&dlinfo->bl_context));
+}
+
 /*
  * On success, we return the address of startup_32, which has potentially been
  * relocated by efi_relocate_kernel.
@@ -905,6 +957,9 @@ asmlinkage unsigned long efi_main(efi_handle_t handle,
 		goto fail;
 	}
 
+	/* If a secure launch is in progress, this never returns */
+	efi_secure_launch(boot_params);
+
 	return bzimage_addr;
 fail:
 	efi_err("efi_main() failed!\n");
-- 
1.8.3.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* [PATCH v6 14/14] x86: EFI stub DRTM launch support for Secure Launch
@ 2023-05-04 14:50   ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-04 14:50 UTC (permalink / raw)
  To: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

This support allows the DRTM launch to be initiated after and EFI stub
launch of the Linux kernel is done. This is accomplished by providing
a handler to jump to when a Secure Launch is in progress.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 drivers/firmware/efi/libstub/x86-stub.c | 55 +++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index a0bfd31..66ff922 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -9,6 +9,7 @@
 #include <linux/efi.h>
 #include <linux/pci.h>
 #include <linux/stddef.h>
+#include <linux/slr_table.h>
 
 #include <asm/efi.h>
 #include <asm/e820/types.h>
@@ -760,6 +761,57 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
 	return EFI_SUCCESS;
 }
 
+static void efi_secure_launch(struct boot_params *boot_params)
+{
+	struct slr_entry_uefi_config *uefi_config;
+	struct slr_uefi_cfg_entry *uefi_entry;
+	struct slr_entry_dl_info *dlinfo;
+	efi_guid_t guid = SLR_TABLE_GUID;
+	struct slr_table *slrt;
+	u64 memmap_hi;
+	void *table;
+	u8 buf[64] = {0};
+
+	table = get_efi_config_table(guid);
+
+	/*
+	 * The presence of this table indicated a Secure Launch
+	 * is being requested.
+	 */
+	if (!table)
+		return;
+
+	slrt = (struct slr_table *)table;
+
+	if (slrt->magic != SLR_TABLE_MAGIC)
+		return;
+
+	/* Add config information to measure the UEFI memory map */
+	uefi_config = (struct slr_entry_uefi_config *)buf;
+	uefi_config->hdr.tag = SLR_ENTRY_UEFI_CONFIG;
+	uefi_config->hdr.size = sizeof(*uefi_config) + sizeof(*uefi_entry);
+	uefi_config->revision = SLR_UEFI_CONFIG_REVISION;
+	uefi_config->nr_entries = 1;
+	uefi_entry = (struct slr_uefi_cfg_entry *)(buf + sizeof(*uefi_config));
+	uefi_entry->pcr = 18;
+	uefi_entry->cfg = boot_params->efi_info.efi_memmap;
+	memmap_hi = boot_params->efi_info.efi_memmap_hi;
+	uefi_entry->cfg |= memmap_hi << 32;
+	uefi_entry->size = boot_params->efi_info.efi_memmap_size;
+	memcpy(&uefi_entry->evt_info[0], "Measured UEFI memory map",
+		strlen("Measured UEFI memory map"));
+
+	if (slr_add_entry(slrt, (struct slr_entry_hdr *)uefi_config))
+		return;
+
+	/* Jump through DL stub to initiate Secure Launch */
+	dlinfo = (struct slr_entry_dl_info *)
+		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_DL_INFO);
+
+	asm volatile ("jmp *%%rax"
+		      : : "a" (dlinfo->dl_handler), "D" (&dlinfo->bl_context));
+}
+
 /*
  * On success, we return the address of startup_32, which has potentially been
  * relocated by efi_relocate_kernel.
@@ -905,6 +957,9 @@ asmlinkage unsigned long efi_main(efi_handle_t handle,
 		goto fail;
 	}
 
+	/* If a secure launch is in progress, this never returns */
+	efi_secure_launch(boot_params);
+
 	return bzimage_addr;
 fail:
 	efi_err("efi_main() failed!\n");
-- 
1.8.3.1


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

* Re: [PATCH v6 00/14] x86: Trenchboot secure dynamic launch Linux kernel support
  2023-05-04 14:50 ` Ross Philipson
@ 2023-05-05  8:39   ` Bagas Sanjaya
  -1 siblings, 0 replies; 200+ messages in thread
From: Bagas Sanjaya @ 2023-05-05  8:39 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

[-- Attachment #1: Type: text/plain, Size: 601 bytes --]

On Thu, May 04, 2023 at 02:50:09PM +0000, Ross Philipson wrote:
> This patchset provides detailed documentation of DRTM, the approach used for
> adding the capbility, and relevant API/ABI documentation. In addition to the
> documentation the patch set introduces Intel TXT support as the first platform
> for Linux Secure Launch.

I'd like to apply this series, but on what commit it is based on? I
don't see any branch containing this series version in trenchboot tree
[1].

Thanks.

[1]: https://github.com/TrenchBoot/linux

-- 
An old man doll... just what I always wanted! - Clara

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH v6 00/14] x86: Trenchboot secure dynamic launch Linux kernel support
@ 2023-05-05  8:39   ` Bagas Sanjaya
  0 siblings, 0 replies; 200+ messages in thread
From: Bagas Sanjaya @ 2023-05-05  8:39 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel


[-- Attachment #1.1: Type: text/plain, Size: 601 bytes --]

On Thu, May 04, 2023 at 02:50:09PM +0000, Ross Philipson wrote:
> This patchset provides detailed documentation of DRTM, the approach used for
> adding the capbility, and relevant API/ABI documentation. In addition to the
> documentation the patch set introduces Intel TXT support as the first platform
> for Linux Secure Launch.

I'd like to apply this series, but on what commit it is based on? I
don't see any branch containing this series version in trenchboot tree
[1].

Thanks.

[1]: https://github.com/TrenchBoot/linux

-- 
An old man doll... just what I always wanted! - Clara

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 143 bytes --]

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 00/14] x86: Trenchboot secure dynamic launch Linux kernel support
  2023-05-05  8:39   ` Bagas Sanjaya
@ 2023-05-05 15:45     ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 15:45 UTC (permalink / raw)
  To: Bagas Sanjaya, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On 5/5/23 04:39, Bagas Sanjaya wrote:
> On Thu, May 04, 2023 at 02:50:09PM +0000, Ross Philipson wrote:
>> This patchset provides detailed documentation of DRTM, the approach used for
>> adding the capbility, and relevant API/ABI documentation. In addition to the
>> documentation the patch set introduces Intel TXT support as the first platform
>> for Linux Secure Launch.
> 
> I'd like to apply this series, but on what commit it is based on? I
> don't see any branch containing this series version in trenchboot tree
> [1].

Sorry about that. In the future I will include a base-commit field. It 
is based off of torvolds/master as of 5/1/2023. The branch where the 
patches came from is now pushed to the TrenchBoot repository here:

https://github.com/TrenchBoot/linux/tree/linux-sl-master-5-1-23-v6

Thanks
Ross

> 
> Thanks.
> 
> [1]: https://github.com/TrenchBoot/linux
> 


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

* Re: [PATCH v6 00/14] x86: Trenchboot secure dynamic launch Linux kernel support
@ 2023-05-05 15:45     ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 15:45 UTC (permalink / raw)
  To: Bagas Sanjaya, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On 5/5/23 04:39, Bagas Sanjaya wrote:
> On Thu, May 04, 2023 at 02:50:09PM +0000, Ross Philipson wrote:
>> This patchset provides detailed documentation of DRTM, the approach used for
>> adding the capbility, and relevant API/ABI documentation. In addition to the
>> documentation the patch set introduces Intel TXT support as the first platform
>> for Linux Secure Launch.
> 
> I'd like to apply this series, but on what commit it is based on? I
> don't see any branch containing this series version in trenchboot tree
> [1].

Sorry about that. In the future I will include a base-commit field. It 
is based off of torvolds/master as of 5/1/2023. The branch where the 
patches came from is now pushed to the TrenchBoot repository here:

https://github.com/TrenchBoot/linux/tree/linux-sl-master-5-1-23-v6

Thanks
Ross

> 
> Thanks.
> 
> [1]: https://github.com/TrenchBoot/linux
> 


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-05 16:19     ` Simon Horman
  -1 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 16:19 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
> Introduce background, overview and configuration/ABI information
> for the Secure Launch kernel feature.
> 
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>

Hi Ross and Daniel,

some minor nits from my side.

> ---
>  Documentation/security/index.rst                   |   1 +
>  Documentation/security/launch-integrity/index.rst  |  10 +
>  .../security/launch-integrity/principles.rst       | 313 ++++++++++++
>  .../launch-integrity/secure_launch_details.rst     | 564 +++++++++++++++++++++
>  .../launch-integrity/secure_launch_overview.rst    | 220 ++++++++
>  5 files changed, 1108 insertions(+)
>  create mode 100644 Documentation/security/launch-integrity/index.rst
>  create mode 100644 Documentation/security/launch-integrity/principles.rst
>  create mode 100644 Documentation/security/launch-integrity/secure_launch_details.rst
>  create mode 100644 Documentation/security/launch-integrity/secure_launch_overview.rst
> 
> diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst
> index 6ed8d2f..fade37e 100644
> --- a/Documentation/security/index.rst
> +++ b/Documentation/security/index.rst
> @@ -18,3 +18,4 @@ Security Documentation
>     digsig
>     landlock
>     secrets/index
> +   launch-integrity/index
> diff --git a/Documentation/security/launch-integrity/index.rst b/Documentation/security/launch-integrity/index.rst
> new file mode 100644
> index 0000000..28eed91d
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/index.rst
> @@ -0,0 +1,10 @@

I believe an SPDX tag should go at the top of each .rst file.

> +=====================================
> +System Launch Integrity documentation
> +=====================================
> +
> +.. toctree::
> +
> +   principles
> +   secure_launch_overview
> +   secure_launch_details
> +
> diff --git a/Documentation/security/launch-integrity/principles.rst b/Documentation/security/launch-integrity/principles.rst
> new file mode 100644
> index 0000000..73cf063
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/principles.rst
> @@ -0,0 +1,313 @@
> +=======================
> +System Launch Integrity
> +=======================
> +
> +This document serves to establish a common understanding of what is system
> +launch, the integrity concern for system launch, and why using a Root of Trust
> +(RoT) from a Dynamic Launch may be desired. Through out this document
> +terminology from the Trusted Computing Group (TCG) and National Institue for

s/Institue/Institute/

...

> +Trust Chains
> +============
> +
> +Bulding upon the understanding of security mechanisms to establish load-time

s/Bulding/Building/

...

> diff --git a/Documentation/security/launch-integrity/secure_launch_details.rst b/Documentation/security/launch-integrity/secure_launch_details.rst

...

> +Secure Launch Resource Table
> +============================
> +
> +The Secure Launch Resource Table (SLRT) is a platform-agnostic, standard format
> +for providing information for the pre-launch environment and to pass
> +information to the post-launch environment. The table is populated by one or
> +more bootloaders in the boot chain and used by Secure Launch on how to setup
> +the environment during post-launch. The details for the SLRT are documented
> +in the TrenchBoot Secure Launch Specifcation [3]_.

s/Specifcation/Specification/

...

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
@ 2023-05-05 16:19     ` Simon Horman
  0 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 16:19 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
> Introduce background, overview and configuration/ABI information
> for the Secure Launch kernel feature.
> 
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>

Hi Ross and Daniel,

some minor nits from my side.

> ---
>  Documentation/security/index.rst                   |   1 +
>  Documentation/security/launch-integrity/index.rst  |  10 +
>  .../security/launch-integrity/principles.rst       | 313 ++++++++++++
>  .../launch-integrity/secure_launch_details.rst     | 564 +++++++++++++++++++++
>  .../launch-integrity/secure_launch_overview.rst    | 220 ++++++++
>  5 files changed, 1108 insertions(+)
>  create mode 100644 Documentation/security/launch-integrity/index.rst
>  create mode 100644 Documentation/security/launch-integrity/principles.rst
>  create mode 100644 Documentation/security/launch-integrity/secure_launch_details.rst
>  create mode 100644 Documentation/security/launch-integrity/secure_launch_overview.rst
> 
> diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst
> index 6ed8d2f..fade37e 100644
> --- a/Documentation/security/index.rst
> +++ b/Documentation/security/index.rst
> @@ -18,3 +18,4 @@ Security Documentation
>     digsig
>     landlock
>     secrets/index
> +   launch-integrity/index
> diff --git a/Documentation/security/launch-integrity/index.rst b/Documentation/security/launch-integrity/index.rst
> new file mode 100644
> index 0000000..28eed91d
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/index.rst
> @@ -0,0 +1,10 @@

I believe an SPDX tag should go at the top of each .rst file.

> +=====================================
> +System Launch Integrity documentation
> +=====================================
> +
> +.. toctree::
> +
> +   principles
> +   secure_launch_overview
> +   secure_launch_details
> +
> diff --git a/Documentation/security/launch-integrity/principles.rst b/Documentation/security/launch-integrity/principles.rst
> new file mode 100644
> index 0000000..73cf063
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/principles.rst
> @@ -0,0 +1,313 @@
> +=======================
> +System Launch Integrity
> +=======================
> +
> +This document serves to establish a common understanding of what is system
> +launch, the integrity concern for system launch, and why using a Root of Trust
> +(RoT) from a Dynamic Launch may be desired. Through out this document
> +terminology from the Trusted Computing Group (TCG) and National Institue for

s/Institue/Institute/

...

> +Trust Chains
> +============
> +
> +Bulding upon the understanding of security mechanisms to establish load-time

s/Bulding/Building/

...

> diff --git a/Documentation/security/launch-integrity/secure_launch_details.rst b/Documentation/security/launch-integrity/secure_launch_details.rst

...

> +Secure Launch Resource Table
> +============================
> +
> +The Secure Launch Resource Table (SLRT) is a platform-agnostic, standard format
> +for providing information for the pre-launch environment and to pass
> +information to the post-launch environment. The table is populated by one or
> +more bootloaders in the boot chain and used by Secure Launch on how to setup
> +the environment during post-launch. The details for the SLRT are documented
> +in the TrenchBoot Secure Launch Specifcation [3]_.

s/Specifcation/Specification/

...

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-05 16:22     ` Simon Horman
  -1 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 16:22 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:13PM +0000, Ross Philipson wrote:
> Introduce the Secure Launch Resource Table which forms the formal
> interface between the pre and post launch code.
> 
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  include/linux/slr_table.h | 270 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 270 insertions(+)
>  create mode 100644 include/linux/slr_table.h
> 
> diff --git a/include/linux/slr_table.h b/include/linux/slr_table.h

...

> +static inline void *slr_end_of_entrys(struct slr_table *table)
> +{
> +	return (((void *)table) + table->size);
> +}
> +
> +static inline struct slr_entry_hdr *
> +slr_next_entry(struct slr_table *table,
> +		struct slr_entry_hdr *curr)

nit: The indentation of the line above doesn't align with the '(' on
     the line before it.

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-05-05 16:22     ` Simon Horman
  0 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 16:22 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:13PM +0000, Ross Philipson wrote:
> Introduce the Secure Launch Resource Table which forms the formal
> interface between the pre and post launch code.
> 
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  include/linux/slr_table.h | 270 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 270 insertions(+)
>  create mode 100644 include/linux/slr_table.h
> 
> diff --git a/include/linux/slr_table.h b/include/linux/slr_table.h

...

> +static inline void *slr_end_of_entrys(struct slr_table *table)
> +{
> +	return (((void *)table) + table->size);
> +}
> +
> +static inline struct slr_entry_hdr *
> +slr_next_entry(struct slr_table *table,
> +		struct slr_entry_hdr *curr)

nit: The indentation of the line above doesn't align with the '(' on
     the line before it.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 05/14] x86: Secure Launch main header file
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-05 16:25     ` Simon Horman
  -1 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 16:25 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:14PM +0000, Ross Philipson wrote:
> Introduce the main Secure Launch header file used in the early SL stub
> and the early setup code.
> 
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  include/linux/slaunch.h | 513 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 513 insertions(+)
>  create mode 100644 include/linux/slaunch.h
> 
> diff --git a/include/linux/slaunch.h b/include/linux/slaunch.h

...

> +/* TXTCR_STS status bits */
> +#define TXT_SENTER_DONE_STS		(1<<0)
> +#define TXT_SEXIT_DONE_STS		(1<<1)

nit: Please consider using BIT()

...

> +/*
> + * External functions avalailable in mainline kernel.
> + */
> +extern void slaunch_setup_txt(void);
> +extern u32 slaunch_get_flags(void);
> +extern struct sl_ap_wake_info *slaunch_get_ap_wake_info(void);
> +extern struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar);
> +extern void __noreturn slaunch_txt_reset(void __iomem *txt,
> +					 const char *msg, u64 error);
> +extern void slaunch_finalize(int do_sexit);

I think that extern should be avoided.
Perhaps these are in a header file that can be included?

> +
> +#endif /* !__ASSEMBLY */
> +
> +#else
> +
> +#define slaunch_setup_txt()		do { } while (0)
> +#define slaunch_get_flags()		0
> +#define slaunch_get_dmar_table(d)	(d)
> +#define slaunch_finalize(d)		do { } while (0)

I think it is usual to use static functions for this purpose.
Usually they end up in header files as static inline functions.

> +
> +#endif /* !IS_ENABLED(CONFIG_SECURE_LAUNCH) */
> +
> +#endif /* _LINUX_SLAUNCH_H */

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

* Re: [PATCH v6 05/14] x86: Secure Launch main header file
@ 2023-05-05 16:25     ` Simon Horman
  0 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 16:25 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:14PM +0000, Ross Philipson wrote:
> Introduce the main Secure Launch header file used in the early SL stub
> and the early setup code.
> 
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  include/linux/slaunch.h | 513 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 513 insertions(+)
>  create mode 100644 include/linux/slaunch.h
> 
> diff --git a/include/linux/slaunch.h b/include/linux/slaunch.h

...

> +/* TXTCR_STS status bits */
> +#define TXT_SENTER_DONE_STS		(1<<0)
> +#define TXT_SEXIT_DONE_STS		(1<<1)

nit: Please consider using BIT()

...

> +/*
> + * External functions avalailable in mainline kernel.
> + */
> +extern void slaunch_setup_txt(void);
> +extern u32 slaunch_get_flags(void);
> +extern struct sl_ap_wake_info *slaunch_get_ap_wake_info(void);
> +extern struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar);
> +extern void __noreturn slaunch_txt_reset(void __iomem *txt,
> +					 const char *msg, u64 error);
> +extern void slaunch_finalize(int do_sexit);

I think that extern should be avoided.
Perhaps these are in a header file that can be included?

> +
> +#endif /* !__ASSEMBLY */
> +
> +#else
> +
> +#define slaunch_setup_txt()		do { } while (0)
> +#define slaunch_get_flags()		0
> +#define slaunch_get_dmar_table(d)	(d)
> +#define slaunch_finalize(d)		do { } while (0)

I think it is usual to use static functions for this purpose.
Usually they end up in header files as static inline functions.

> +
> +#endif /* !IS_ENABLED(CONFIG_SECURE_LAUNCH) */
> +
> +#endif /* _LINUX_SLAUNCH_H */

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-05 16:34     ` Simon Horman
  -1 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 16:34 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:15PM +0000, Ross Philipson wrote:
> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
> 
> The SHA algorithms are necessary to measure configuration information into
> the TPM as early as possible before using the values. This implementation
> uses the established approach of #including the SHA libraries directly in
> the code since the compressed kernel is not uncompressed at this point.
> 
> The SHA code here has its origins in the code from the main kernel:
> 
> commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")
> 
> That code could not be pulled directly into the setup portion of the
> compressed kernel because of other dependencies it pulls in. The result
> is this is a modified copy of that code that still leverages the core
> SHA algorithms.
> 
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  arch/x86/boot/compressed/Makefile       |  2 +
>  arch/x86/boot/compressed/early_sha1.c   | 97 +++++++++++++++++++++++++++++++++
>  arch/x86/boot/compressed/early_sha1.h   | 17 ++++++
>  arch/x86/boot/compressed/early_sha256.c |  7 +++
>  lib/crypto/sha1.c                       |  4 ++
>  lib/crypto/sha256.c                     |  8 +++
>  6 files changed, 135 insertions(+)
>  create mode 100644 arch/x86/boot/compressed/early_sha1.c
>  create mode 100644 arch/x86/boot/compressed/early_sha1.h
>  create mode 100644 arch/x86/boot/compressed/early_sha256.c
> 
> diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
> index 6b6cfe6..1d327d4 100644
> --- a/arch/x86/boot/compressed/Makefile
> +++ b/arch/x86/boot/compressed/Makefile
> @@ -112,6 +112,8 @@ vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
>  vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
>  vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
>  
> +vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/early_sha1.o $(obj)/early_sha256.o
> +
>  $(obj)/vmlinux: $(vmlinux-objs-y) FORCE
>  	$(call if_changed,ld)
>  
> diff --git a/arch/x86/boot/compressed/early_sha1.c b/arch/x86/boot/compressed/early_sha1.c
> new file mode 100644
> index 0000000..524ec23
> --- /dev/null
> +++ b/arch/x86/boot/compressed/early_sha1.c
> @@ -0,0 +1,97 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2022 Apertus Solutions, LLC.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/linkage.h>
> +#include <linux/string.h>
> +#include <asm/boot.h>
> +#include <asm/unaligned.h>
> +
> +#include "early_sha1.h"
> +
> +#define SHA1_DISABLE_EXPORT

Hi Ross,

I could be mistaken, but it seems to me that *_DISABLE_EXPORT
is a mechanism of this patch to disable exporting symbols
(use of EXPORT_SYMBOL), at compile time.

If so, this doesn't strike me as something that should be part of upstream
kernel code.  Could you consider dropping this part of the patch?

...

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-05 16:34     ` Simon Horman
  0 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 16:34 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:15PM +0000, Ross Philipson wrote:
> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
> 
> The SHA algorithms are necessary to measure configuration information into
> the TPM as early as possible before using the values. This implementation
> uses the established approach of #including the SHA libraries directly in
> the code since the compressed kernel is not uncompressed at this point.
> 
> The SHA code here has its origins in the code from the main kernel:
> 
> commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")
> 
> That code could not be pulled directly into the setup portion of the
> compressed kernel because of other dependencies it pulls in. The result
> is this is a modified copy of that code that still leverages the core
> SHA algorithms.
> 
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  arch/x86/boot/compressed/Makefile       |  2 +
>  arch/x86/boot/compressed/early_sha1.c   | 97 +++++++++++++++++++++++++++++++++
>  arch/x86/boot/compressed/early_sha1.h   | 17 ++++++
>  arch/x86/boot/compressed/early_sha256.c |  7 +++
>  lib/crypto/sha1.c                       |  4 ++
>  lib/crypto/sha256.c                     |  8 +++
>  6 files changed, 135 insertions(+)
>  create mode 100644 arch/x86/boot/compressed/early_sha1.c
>  create mode 100644 arch/x86/boot/compressed/early_sha1.h
>  create mode 100644 arch/x86/boot/compressed/early_sha256.c
> 
> diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
> index 6b6cfe6..1d327d4 100644
> --- a/arch/x86/boot/compressed/Makefile
> +++ b/arch/x86/boot/compressed/Makefile
> @@ -112,6 +112,8 @@ vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
>  vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
>  vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
>  
> +vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/early_sha1.o $(obj)/early_sha256.o
> +
>  $(obj)/vmlinux: $(vmlinux-objs-y) FORCE
>  	$(call if_changed,ld)
>  
> diff --git a/arch/x86/boot/compressed/early_sha1.c b/arch/x86/boot/compressed/early_sha1.c
> new file mode 100644
> index 0000000..524ec23
> --- /dev/null
> +++ b/arch/x86/boot/compressed/early_sha1.c
> @@ -0,0 +1,97 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2022 Apertus Solutions, LLC.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/linkage.h>
> +#include <linux/string.h>
> +#include <asm/boot.h>
> +#include <asm/unaligned.h>
> +
> +#include "early_sha1.h"
> +
> +#define SHA1_DISABLE_EXPORT

Hi Ross,

I could be mistaken, but it seems to me that *_DISABLE_EXPORT
is a mechanism of this patch to disable exporting symbols
(use of EXPORT_SYMBOL), at compile time.

If so, this doesn't strike me as something that should be part of upstream
kernel code.  Could you consider dropping this part of the patch?

...

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
  2023-05-05 16:19     ` Simon Horman
@ 2023-05-05 17:32       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 17:32 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 12:19, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
>> Introduce background, overview and configuration/ABI information
>> for the Secure Launch kernel feature.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> 
> Hi Ross and Daniel,
> 
> some minor nits from my side.

All good points. We will fix those.

Thanks
Ross

> 
>> ---
>>   Documentation/security/index.rst                   |   1 +
>>   Documentation/security/launch-integrity/index.rst  |  10 +
>>   .../security/launch-integrity/principles.rst       | 313 ++++++++++++
>>   .../launch-integrity/secure_launch_details.rst     | 564 +++++++++++++++++++++
>>   .../launch-integrity/secure_launch_overview.rst    | 220 ++++++++
>>   5 files changed, 1108 insertions(+)
>>   create mode 100644 Documentation/security/launch-integrity/index.rst
>>   create mode 100644 Documentation/security/launch-integrity/principles.rst
>>   create mode 100644 Documentation/security/launch-integrity/secure_launch_details.rst
>>   create mode 100644 Documentation/security/launch-integrity/secure_launch_overview.rst
>>
>> diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst
>> index 6ed8d2f..fade37e 100644
>> --- a/Documentation/security/index.rst
>> +++ b/Documentation/security/index.rst
>> @@ -18,3 +18,4 @@ Security Documentation
>>      digsig
>>      landlock
>>      secrets/index
>> +   launch-integrity/index
>> diff --git a/Documentation/security/launch-integrity/index.rst b/Documentation/security/launch-integrity/index.rst
>> new file mode 100644
>> index 0000000..28eed91d
>> --- /dev/null
>> +++ b/Documentation/security/launch-integrity/index.rst
>> @@ -0,0 +1,10 @@
> 
> I believe an SPDX tag should go at the top of each .rst file.
> 
>> +=====================================
>> +System Launch Integrity documentation
>> +=====================================
>> +
>> +.. toctree::
>> +
>> +   principles
>> +   secure_launch_overview
>> +   secure_launch_details
>> +
>> diff --git a/Documentation/security/launch-integrity/principles.rst b/Documentation/security/launch-integrity/principles.rst
>> new file mode 100644
>> index 0000000..73cf063
>> --- /dev/null
>> +++ b/Documentation/security/launch-integrity/principles.rst
>> @@ -0,0 +1,313 @@
>> +=======================
>> +System Launch Integrity
>> +=======================
>> +
>> +This document serves to establish a common understanding of what is system
>> +launch, the integrity concern for system launch, and why using a Root of Trust
>> +(RoT) from a Dynamic Launch may be desired. Through out this document
>> +terminology from the Trusted Computing Group (TCG) and National Institue for
> 
> s/Institue/Institute/
> 
> ...
> 
>> +Trust Chains
>> +============
>> +
>> +Bulding upon the understanding of security mechanisms to establish load-time
> 
> s/Bulding/Building/
> 
> ...
> 
>> diff --git a/Documentation/security/launch-integrity/secure_launch_details.rst b/Documentation/security/launch-integrity/secure_launch_details.rst
> 
> ...
> 
>> +Secure Launch Resource Table
>> +============================
>> +
>> +The Secure Launch Resource Table (SLRT) is a platform-agnostic, standard format
>> +for providing information for the pre-launch environment and to pass
>> +information to the post-launch environment. The table is populated by one or
>> +more bootloaders in the boot chain and used by Secure Launch on how to setup
>> +the environment during post-launch. The details for the SLRT are documented
>> +in the TrenchBoot Secure Launch Specifcation [3]_.
> 
> s/Specifcation/Specification/
> 
> ...


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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
@ 2023-05-05 17:32       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 17:32 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 12:19, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
>> Introduce background, overview and configuration/ABI information
>> for the Secure Launch kernel feature.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> 
> Hi Ross and Daniel,
> 
> some minor nits from my side.

All good points. We will fix those.

Thanks
Ross

> 
>> ---
>>   Documentation/security/index.rst                   |   1 +
>>   Documentation/security/launch-integrity/index.rst  |  10 +
>>   .../security/launch-integrity/principles.rst       | 313 ++++++++++++
>>   .../launch-integrity/secure_launch_details.rst     | 564 +++++++++++++++++++++
>>   .../launch-integrity/secure_launch_overview.rst    | 220 ++++++++
>>   5 files changed, 1108 insertions(+)
>>   create mode 100644 Documentation/security/launch-integrity/index.rst
>>   create mode 100644 Documentation/security/launch-integrity/principles.rst
>>   create mode 100644 Documentation/security/launch-integrity/secure_launch_details.rst
>>   create mode 100644 Documentation/security/launch-integrity/secure_launch_overview.rst
>>
>> diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst
>> index 6ed8d2f..fade37e 100644
>> --- a/Documentation/security/index.rst
>> +++ b/Documentation/security/index.rst
>> @@ -18,3 +18,4 @@ Security Documentation
>>      digsig
>>      landlock
>>      secrets/index
>> +   launch-integrity/index
>> diff --git a/Documentation/security/launch-integrity/index.rst b/Documentation/security/launch-integrity/index.rst
>> new file mode 100644
>> index 0000000..28eed91d
>> --- /dev/null
>> +++ b/Documentation/security/launch-integrity/index.rst
>> @@ -0,0 +1,10 @@
> 
> I believe an SPDX tag should go at the top of each .rst file.
> 
>> +=====================================
>> +System Launch Integrity documentation
>> +=====================================
>> +
>> +.. toctree::
>> +
>> +   principles
>> +   secure_launch_overview
>> +   secure_launch_details
>> +
>> diff --git a/Documentation/security/launch-integrity/principles.rst b/Documentation/security/launch-integrity/principles.rst
>> new file mode 100644
>> index 0000000..73cf063
>> --- /dev/null
>> +++ b/Documentation/security/launch-integrity/principles.rst
>> @@ -0,0 +1,313 @@
>> +=======================
>> +System Launch Integrity
>> +=======================
>> +
>> +This document serves to establish a common understanding of what is system
>> +launch, the integrity concern for system launch, and why using a Root of Trust
>> +(RoT) from a Dynamic Launch may be desired. Through out this document
>> +terminology from the Trusted Computing Group (TCG) and National Institue for
> 
> s/Institue/Institute/
> 
> ...
> 
>> +Trust Chains
>> +============
>> +
>> +Bulding upon the understanding of security mechanisms to establish load-time
> 
> s/Bulding/Building/
> 
> ...
> 
>> diff --git a/Documentation/security/launch-integrity/secure_launch_details.rst b/Documentation/security/launch-integrity/secure_launch_details.rst
> 
> ...
> 
>> +Secure Launch Resource Table
>> +============================
>> +
>> +The Secure Launch Resource Table (SLRT) is a platform-agnostic, standard format
>> +for providing information for the pre-launch environment and to pass
>> +information to the post-launch environment. The table is populated by one or
>> +more bootloaders in the boot chain and used by Secure Launch on how to setup
>> +the environment during post-launch. The details for the SLRT are documented
>> +in the TrenchBoot Secure Launch Specifcation [3]_.
> 
> s/Specifcation/Specification/
> 
> ...


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-05-05 16:22     ` Simon Horman
@ 2023-05-05 17:34       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 17:34 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 12:22, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:13PM +0000, Ross Philipson wrote:
>> Introduce the Secure Launch Resource Table which forms the formal
>> interface between the pre and post launch code.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   include/linux/slr_table.h | 270 ++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 270 insertions(+)
>>   create mode 100644 include/linux/slr_table.h
>>
>> diff --git a/include/linux/slr_table.h b/include/linux/slr_table.h
> 
> ...
> 
>> +static inline void *slr_end_of_entrys(struct slr_table *table)
>> +{
>> +	return (((void *)table) + table->size);
>> +}
>> +
>> +static inline struct slr_entry_hdr *
>> +slr_next_entry(struct slr_table *table,
>> +		struct slr_entry_hdr *curr)
> 
> nit: The indentation of the line above doesn't align with the '(' on
>       the line before it.

Yea I see there is another one above that is not aligned too. We will 
fix those.

Thanks
Ross


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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-05-05 17:34       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 17:34 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 12:22, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:13PM +0000, Ross Philipson wrote:
>> Introduce the Secure Launch Resource Table which forms the formal
>> interface between the pre and post launch code.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   include/linux/slr_table.h | 270 ++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 270 insertions(+)
>>   create mode 100644 include/linux/slr_table.h
>>
>> diff --git a/include/linux/slr_table.h b/include/linux/slr_table.h
> 
> ...
> 
>> +static inline void *slr_end_of_entrys(struct slr_table *table)
>> +{
>> +	return (((void *)table) + table->size);
>> +}
>> +
>> +static inline struct slr_entry_hdr *
>> +slr_next_entry(struct slr_table *table,
>> +		struct slr_entry_hdr *curr)
> 
> nit: The indentation of the line above doesn't align with the '(' on
>       the line before it.

Yea I see there is another one above that is not aligned too. We will 
fix those.

Thanks
Ross


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 05/14] x86: Secure Launch main header file
  2023-05-05 16:25     ` Simon Horman
@ 2023-05-05 17:37       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 17:37 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 12:25, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:14PM +0000, Ross Philipson wrote:
>> Introduce the main Secure Launch header file used in the early SL stub
>> and the early setup code.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   include/linux/slaunch.h | 513 ++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 513 insertions(+)
>>   create mode 100644 include/linux/slaunch.h
>>
>> diff --git a/include/linux/slaunch.h b/include/linux/slaunch.h
> 
> ...
> 
>> +/* TXTCR_STS status bits */
>> +#define TXT_SENTER_DONE_STS		(1<<0)
>> +#define TXT_SEXIT_DONE_STS		(1<<1)
> 
> nit: Please consider using BIT()

Ack

> 
> ...
> 
>> +/*
>> + * External functions avalailable in mainline kernel.
>> + */
>> +extern void slaunch_setup_txt(void);
>> +extern u32 slaunch_get_flags(void);
>> +extern struct sl_ap_wake_info *slaunch_get_ap_wake_info(void);
>> +extern struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar);
>> +extern void __noreturn slaunch_txt_reset(void __iomem *txt,
>> +					 const char *msg, u64 error);
>> +extern void slaunch_finalize(int do_sexit);
> 
> I think that extern should be avoided.
> Perhaps these are in a header file that can be included?

Someone in an earlier review asked me to add the externs. The function 
are not in another header, they are in a C module.

> 
>> +
>> +#endif /* !__ASSEMBLY */
>> +
>> +#else
>> +
>> +#define slaunch_setup_txt()		do { } while (0)
>> +#define slaunch_get_flags()		0
>> +#define slaunch_get_dmar_table(d)	(d)
>> +#define slaunch_finalize(d)		do { } while (0)
> 
> I think it is usual to use static functions for this purpose.
> Usually they end up in header files as static inline functions.

Yea we can switch to using static functions.

Thanks
Ross

> 
>> +
>> +#endif /* !IS_ENABLED(CONFIG_SECURE_LAUNCH) */
>> +
>> +#endif /* _LINUX_SLAUNCH_H */


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

* Re: [PATCH v6 05/14] x86: Secure Launch main header file
@ 2023-05-05 17:37       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 17:37 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 12:25, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:14PM +0000, Ross Philipson wrote:
>> Introduce the main Secure Launch header file used in the early SL stub
>> and the early setup code.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   include/linux/slaunch.h | 513 ++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 513 insertions(+)
>>   create mode 100644 include/linux/slaunch.h
>>
>> diff --git a/include/linux/slaunch.h b/include/linux/slaunch.h
> 
> ...
> 
>> +/* TXTCR_STS status bits */
>> +#define TXT_SENTER_DONE_STS		(1<<0)
>> +#define TXT_SEXIT_DONE_STS		(1<<1)
> 
> nit: Please consider using BIT()

Ack

> 
> ...
> 
>> +/*
>> + * External functions avalailable in mainline kernel.
>> + */
>> +extern void slaunch_setup_txt(void);
>> +extern u32 slaunch_get_flags(void);
>> +extern struct sl_ap_wake_info *slaunch_get_ap_wake_info(void);
>> +extern struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar);
>> +extern void __noreturn slaunch_txt_reset(void __iomem *txt,
>> +					 const char *msg, u64 error);
>> +extern void slaunch_finalize(int do_sexit);
> 
> I think that extern should be avoided.
> Perhaps these are in a header file that can be included?

Someone in an earlier review asked me to add the externs. The function 
are not in another header, they are in a C module.

> 
>> +
>> +#endif /* !__ASSEMBLY */
>> +
>> +#else
>> +
>> +#define slaunch_setup_txt()		do { } while (0)
>> +#define slaunch_get_flags()		0
>> +#define slaunch_get_dmar_table(d)	(d)
>> +#define slaunch_finalize(d)		do { } while (0)
> 
> I think it is usual to use static functions for this purpose.
> Usually they end up in header files as static inline functions.

Yea we can switch to using static functions.

Thanks
Ross

> 
>> +
>> +#endif /* !IS_ENABLED(CONFIG_SECURE_LAUNCH) */
>> +
>> +#endif /* _LINUX_SLAUNCH_H */


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-05 17:47     ` Simon Horman
  -1 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 17:47 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:16PM +0000, Ross Philipson wrote:
> The Secure Launch (SL) stub provides the entry point for Intel TXT (and
> later AMD SKINIT) to vector to during the late launch. The symbol
> sl_stub_entry is that entry point and its offset into the kernel is
> conveyed to the launching code using the MLE (Measured Launch
> Environment) header in the structure named mle_header. The offset of the
> MLE header is set in the kernel_info. The routine sl_stub contains the
> very early late launch setup code responsible for setting up the basic
> environment to allow the normal kernel startup_32 code to proceed. It is
> also responsible for properly waking and handling the APs on Intel
> platforms. The routine sl_main which runs after entering 64b mode is
> responsible for measuring configuration and module information before
> it is used like the boot params, the kernel command line, the TXT heap,
> an external initramfs, etc.
> 
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>

...

> diff --git a/arch/x86/boot/compressed/sl_main.c b/arch/x86/boot/compressed/sl_main.c

...

> +static void *evtlog_base;
> +static u32 evtlog_size;
> +static struct txt_heap_event_log_pointer2_1_element *log20_elem;
> +static u32 tpm_log_ver = SL_TPM12_LOG;
> +struct tcg_efi_specid_event_algs tpm_algs[SL_TPM20_MAX_ALGS] = {0};

tpm_algs seems to only be used in this file.
Should it be static?

> +
> +extern u32 sl_cpu_type;
> +extern u32 sl_mle_start;
> +extern struct boot_params *boot_params;
> +
> +static u64 sl_txt_read(u32 reg)

Perhaps reg should have an __iomem annotation.

> +{
> +	return readq((void *)(u64)(TXT_PRIV_CONFIG_REGS_BASE + reg));
> +}
> +
> +static void sl_txt_write(u32 reg, u64 val)

Likewise here.

...

> +static void sl_check_pmr_coverage(void *base, u32 size, bool allow_hi)
> +{
> +	struct txt_os_sinit_data *os_sinit_data;
> +	void *end = base + size;
> +	void *txt_heap;
> +
> +	if (!(sl_cpu_type & SL_CPU_INTEL))
> +		return;
> +
> +	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
> +
> +	if ((end >= (void *)0x100000000ULL) &&
> +	    (base < (void *)0x100000000ULL))
> +		sl_txt_reset(SL_ERROR_REGION_STRADDLE_4GB);
> +
> +	/*
> +	 * Note that the late stub code validates that the hi PMR covers
> +	 * all memory above 4G. At this point the code can only check that
> +	 * regions are within the hi PMR but that is sufficient.
> +	 */
> +	if ((end > (void *)0x100000000ULL) &&
> +	    (base >= (void *)0x100000000ULL)) {
> +		if (allow_hi) {
> +			if (end >= (void *)(os_sinit_data->vtd_pmr_hi_base +
> +					   os_sinit_data->vtd_pmr_hi_size))
> +				sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
> +		} else
> +			sl_txt_reset(SL_ERROR_REGION_ABOVE_4GB);

nit: if any arm of a condition has '{}' then all arms should have them.
     So:

		} else {
			sl_txt_reset(SL_ERROR_REGION_ABOVE_4GB);
		}

Also elsewhere in this patch.

> +	}
> +
> +	if (end >= (void *)os_sinit_data->vtd_pmr_lo_size)
> +		sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
> +}
> +
> +/*
> + * Some MSRs are modified by the pre-launch code including the MTRRs.
> + * The early MLE code has to restore these values. This code validates
> + * the values after they are measured.
> + */
> +static void sl_txt_validate_msrs(struct txt_os_mle_data *os_mle_data)
> +{
> +	struct slr_txt_mtrr_state *saved_bsp_mtrrs;
> +	u64 mtrr_caps, mtrr_def_type, mtrr_var;
> +	struct slr_entry_intel_info *txt_info;
> +	u64 misc_en_msr;
> +	u32 vcnt, i;
> +
> +	txt_info = (struct slr_entry_intel_info *)os_mle_data->txt_info;
> +	saved_bsp_mtrrs = &(txt_info->saved_bsp_mtrrs);

nit: unnecessary parentheses

...

> +static void sl_validate_event_log_buffer(void)
> +{
> +	struct txt_os_sinit_data *os_sinit_data;
> +	void *txt_heap, *txt_end;
> +	void *mle_base, *mle_end;
> +	void *evtlog_end;
> +
> +	if ((u64)evtlog_size > (LLONG_MAX - (u64)evtlog_base))
> +		sl_txt_reset(SL_ERROR_INTEGER_OVERFLOW);
> +	evtlog_end = evtlog_base + evtlog_size;
> +
> +	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
> +	txt_end = txt_heap + sl_txt_read(TXT_CR_HEAP_SIZE);
> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
> +
> +	mle_base = (void *)(u64)sl_mle_start;
> +	mle_end = mle_base + os_sinit_data->mle_size;
> +
> +	/*
> +	 * This check is to ensure the event log buffer does not overlap with
> +	 * the MLE image.
> +	 */
> +	if ((evtlog_base >= mle_end) &&
> +	    (evtlog_end > mle_end))
> +		goto pmr_check; /* above */

Ditto.
Also, the if condition could be one line.
Also in several other places in this patch.

> +
> +	if ((evtlog_end <= mle_base) &&
> +	    (evtlog_base < mle_base))
> +		goto pmr_check; /* below */
> +
> +	sl_txt_reset(SL_ERROR_MLE_BUFFER_OVERLAP);
> +
> +pmr_check:
> +	/*
> +	 * The TXT heap is protected by the DPR. If the TPM event log is
> +	 * inside the TXT heap, there is no need for a PMR check.
> +	 */
> +	if ((evtlog_base > txt_heap) &&
> +	    (evtlog_end < txt_end))
> +		return;
> +
> +	sl_check_pmr_coverage(evtlog_base, evtlog_size, true);
> +}

> +static void sl_process_extend_policy(struct slr_table *slrt)
> +{
> +	struct slr_entry_policy *policy;
> +	struct slr_policy_entry *entry;
> +	u16 i = 0;
> +
> +	policy =(struct slr_entry_policy *)

nit: space after '='

...

> +static void sl_process_extend_uefi_config(struct slr_table *slrt)
> +{
> +	struct slr_entry_uefi_config *uefi_config;
> +	struct slr_uefi_cfg_entry *uefi_entry;
> +	u64 i;
> +
> +	uefi_config =(struct slr_entry_uefi_config *)
> +		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_UEFI_CONFIG);
> +
> +	/* Optionally here depending on how SL kernel was booted */
> +	if (!uefi_config)
> +		return;
> +
> +	uefi_entry = (struct slr_uefi_cfg_entry *)((u8 *)uefi_config + sizeof(*uefi_config));
> +
> +	for ( ; i < uefi_config->nr_entries; i++, uefi_entry++) {

nit: i seems to be used without first being initialised.

> +		sl_tpm_extend_evtlog(uefi_entry->pcr, TXT_EVTYPE_SLAUNCH,
> +				     (void *)uefi_entry->cfg, uefi_entry->size,
> +				     uefi_entry->evt_info);
> +	}
> +}
> +
> +asmlinkage __visible void sl_check_region(void *base, u32 size)
> +{
> +	sl_check_pmr_coverage(base, size, false);
> +}

I'm a nit unsure, what to do here, but clang-16 with W=1 says the following.

arch/x86/boot/compressed/sl_main.c:533:27: warning: no previous prototype for function 'sl_main' [-Wmissing-prototypes]
asmlinkage __visible void sl_main(void *bootparams)
                          ^
arch/x86/boot/compressed/sl_main.c:533:22: note: declare 'static' if the function is not intended to be used outside of this translation unit
asmlinkage __visible void sl_main(void *bootparams)
                     ^
                     static

...

> diff --git a/arch/x86/boot/compressed/sl_stub.S b/arch/x86/boot/compressed/sl_stub.S
> new file mode 100644
> index 0000000..2d8aa3a
> --- /dev/null
> +++ b/arch/x86/boot/compressed/sl_stub.S
> @@ -0,0 +1,690 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +/*
> + * Secure Launch protected mode entry point.
> + *
> + * Copyright (c) 2022, Oracle and/or its affiliates.
> + */
> +	.code32
> +	.text
> +#include <linux/linkage.h>
> +#include <asm/segment.h>
> +#include <asm/msr.h>
> +#include <asm/processor-flags.h>
> +#include <asm/asm-offsets.h>
> +#include <asm/bootparam.h>
> +#include <asm/page_types.h>
> +#include <asm/irq_vectors.h>
> +#include <linux/slr_table.h>
> +#include <linux/slaunch.h>
> +
> +/* CPUID: leaf 1, ECX, SMX feature bit */
> +#define X86_FEATURE_BIT_SMX	(1 << 6)
> +
> +/* Can't include apiddef.h in asm */
> +#define XAPIC_ENABLE	(1 << 11)
> +#define X2APIC_ENABLE	(1 << 10)
> +
> +/* Can't include traps.h in asm */
> +#define X86_TRAP_NMI	2
> +
> +/* Can't include mtrr.h in asm */
> +#define MTRRphysBase0	0x200
> +
> +#define IDT_VECTOR_LO_BITS	0
> +#define IDT_VECTOR_HI_BITS	6
> +
> +/*
> + * See the comment in head_64.S for detailed informatoin on what this macro

nit: s/informatoin/information/

...

> diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
> index 01d19fc..74e3e7df 100644
> --- a/arch/x86/include/uapi/asm/bootparam.h
> +++ b/arch/x86/include/uapi/asm/bootparam.h
> @@ -26,6 +26,7 @@
>  /* loadflags */
>  #define LOADED_HIGH	(1<<0)
>  #define KASLR_FLAG	(1<<1)
> +#define SLAUNCH_FLAG	(1<<2)
>  #define QUIET_FLAG	(1<<5)
>  #define KEEP_SEGMENTS	(1<<6)
>  #define CAN_USE_HEAP	(1<<7)

nit: please consider using BIT()

...

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-05-05 17:47     ` Simon Horman
  0 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 17:47 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:16PM +0000, Ross Philipson wrote:
> The Secure Launch (SL) stub provides the entry point for Intel TXT (and
> later AMD SKINIT) to vector to during the late launch. The symbol
> sl_stub_entry is that entry point and its offset into the kernel is
> conveyed to the launching code using the MLE (Measured Launch
> Environment) header in the structure named mle_header. The offset of the
> MLE header is set in the kernel_info. The routine sl_stub contains the
> very early late launch setup code responsible for setting up the basic
> environment to allow the normal kernel startup_32 code to proceed. It is
> also responsible for properly waking and handling the APs on Intel
> platforms. The routine sl_main which runs after entering 64b mode is
> responsible for measuring configuration and module information before
> it is used like the boot params, the kernel command line, the TXT heap,
> an external initramfs, etc.
> 
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>

...

> diff --git a/arch/x86/boot/compressed/sl_main.c b/arch/x86/boot/compressed/sl_main.c

...

> +static void *evtlog_base;
> +static u32 evtlog_size;
> +static struct txt_heap_event_log_pointer2_1_element *log20_elem;
> +static u32 tpm_log_ver = SL_TPM12_LOG;
> +struct tcg_efi_specid_event_algs tpm_algs[SL_TPM20_MAX_ALGS] = {0};

tpm_algs seems to only be used in this file.
Should it be static?

> +
> +extern u32 sl_cpu_type;
> +extern u32 sl_mle_start;
> +extern struct boot_params *boot_params;
> +
> +static u64 sl_txt_read(u32 reg)

Perhaps reg should have an __iomem annotation.

> +{
> +	return readq((void *)(u64)(TXT_PRIV_CONFIG_REGS_BASE + reg));
> +}
> +
> +static void sl_txt_write(u32 reg, u64 val)

Likewise here.

...

> +static void sl_check_pmr_coverage(void *base, u32 size, bool allow_hi)
> +{
> +	struct txt_os_sinit_data *os_sinit_data;
> +	void *end = base + size;
> +	void *txt_heap;
> +
> +	if (!(sl_cpu_type & SL_CPU_INTEL))
> +		return;
> +
> +	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
> +
> +	if ((end >= (void *)0x100000000ULL) &&
> +	    (base < (void *)0x100000000ULL))
> +		sl_txt_reset(SL_ERROR_REGION_STRADDLE_4GB);
> +
> +	/*
> +	 * Note that the late stub code validates that the hi PMR covers
> +	 * all memory above 4G. At this point the code can only check that
> +	 * regions are within the hi PMR but that is sufficient.
> +	 */
> +	if ((end > (void *)0x100000000ULL) &&
> +	    (base >= (void *)0x100000000ULL)) {
> +		if (allow_hi) {
> +			if (end >= (void *)(os_sinit_data->vtd_pmr_hi_base +
> +					   os_sinit_data->vtd_pmr_hi_size))
> +				sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
> +		} else
> +			sl_txt_reset(SL_ERROR_REGION_ABOVE_4GB);

nit: if any arm of a condition has '{}' then all arms should have them.
     So:

		} else {
			sl_txt_reset(SL_ERROR_REGION_ABOVE_4GB);
		}

Also elsewhere in this patch.

> +	}
> +
> +	if (end >= (void *)os_sinit_data->vtd_pmr_lo_size)
> +		sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
> +}
> +
> +/*
> + * Some MSRs are modified by the pre-launch code including the MTRRs.
> + * The early MLE code has to restore these values. This code validates
> + * the values after they are measured.
> + */
> +static void sl_txt_validate_msrs(struct txt_os_mle_data *os_mle_data)
> +{
> +	struct slr_txt_mtrr_state *saved_bsp_mtrrs;
> +	u64 mtrr_caps, mtrr_def_type, mtrr_var;
> +	struct slr_entry_intel_info *txt_info;
> +	u64 misc_en_msr;
> +	u32 vcnt, i;
> +
> +	txt_info = (struct slr_entry_intel_info *)os_mle_data->txt_info;
> +	saved_bsp_mtrrs = &(txt_info->saved_bsp_mtrrs);

nit: unnecessary parentheses

...

> +static void sl_validate_event_log_buffer(void)
> +{
> +	struct txt_os_sinit_data *os_sinit_data;
> +	void *txt_heap, *txt_end;
> +	void *mle_base, *mle_end;
> +	void *evtlog_end;
> +
> +	if ((u64)evtlog_size > (LLONG_MAX - (u64)evtlog_base))
> +		sl_txt_reset(SL_ERROR_INTEGER_OVERFLOW);
> +	evtlog_end = evtlog_base + evtlog_size;
> +
> +	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
> +	txt_end = txt_heap + sl_txt_read(TXT_CR_HEAP_SIZE);
> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
> +
> +	mle_base = (void *)(u64)sl_mle_start;
> +	mle_end = mle_base + os_sinit_data->mle_size;
> +
> +	/*
> +	 * This check is to ensure the event log buffer does not overlap with
> +	 * the MLE image.
> +	 */
> +	if ((evtlog_base >= mle_end) &&
> +	    (evtlog_end > mle_end))
> +		goto pmr_check; /* above */

Ditto.
Also, the if condition could be one line.
Also in several other places in this patch.

> +
> +	if ((evtlog_end <= mle_base) &&
> +	    (evtlog_base < mle_base))
> +		goto pmr_check; /* below */
> +
> +	sl_txt_reset(SL_ERROR_MLE_BUFFER_OVERLAP);
> +
> +pmr_check:
> +	/*
> +	 * The TXT heap is protected by the DPR. If the TPM event log is
> +	 * inside the TXT heap, there is no need for a PMR check.
> +	 */
> +	if ((evtlog_base > txt_heap) &&
> +	    (evtlog_end < txt_end))
> +		return;
> +
> +	sl_check_pmr_coverage(evtlog_base, evtlog_size, true);
> +}

> +static void sl_process_extend_policy(struct slr_table *slrt)
> +{
> +	struct slr_entry_policy *policy;
> +	struct slr_policy_entry *entry;
> +	u16 i = 0;
> +
> +	policy =(struct slr_entry_policy *)

nit: space after '='

...

> +static void sl_process_extend_uefi_config(struct slr_table *slrt)
> +{
> +	struct slr_entry_uefi_config *uefi_config;
> +	struct slr_uefi_cfg_entry *uefi_entry;
> +	u64 i;
> +
> +	uefi_config =(struct slr_entry_uefi_config *)
> +		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_UEFI_CONFIG);
> +
> +	/* Optionally here depending on how SL kernel was booted */
> +	if (!uefi_config)
> +		return;
> +
> +	uefi_entry = (struct slr_uefi_cfg_entry *)((u8 *)uefi_config + sizeof(*uefi_config));
> +
> +	for ( ; i < uefi_config->nr_entries; i++, uefi_entry++) {

nit: i seems to be used without first being initialised.

> +		sl_tpm_extend_evtlog(uefi_entry->pcr, TXT_EVTYPE_SLAUNCH,
> +				     (void *)uefi_entry->cfg, uefi_entry->size,
> +				     uefi_entry->evt_info);
> +	}
> +}
> +
> +asmlinkage __visible void sl_check_region(void *base, u32 size)
> +{
> +	sl_check_pmr_coverage(base, size, false);
> +}

I'm a nit unsure, what to do here, but clang-16 with W=1 says the following.

arch/x86/boot/compressed/sl_main.c:533:27: warning: no previous prototype for function 'sl_main' [-Wmissing-prototypes]
asmlinkage __visible void sl_main(void *bootparams)
                          ^
arch/x86/boot/compressed/sl_main.c:533:22: note: declare 'static' if the function is not intended to be used outside of this translation unit
asmlinkage __visible void sl_main(void *bootparams)
                     ^
                     static

...

> diff --git a/arch/x86/boot/compressed/sl_stub.S b/arch/x86/boot/compressed/sl_stub.S
> new file mode 100644
> index 0000000..2d8aa3a
> --- /dev/null
> +++ b/arch/x86/boot/compressed/sl_stub.S
> @@ -0,0 +1,690 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +/*
> + * Secure Launch protected mode entry point.
> + *
> + * Copyright (c) 2022, Oracle and/or its affiliates.
> + */
> +	.code32
> +	.text
> +#include <linux/linkage.h>
> +#include <asm/segment.h>
> +#include <asm/msr.h>
> +#include <asm/processor-flags.h>
> +#include <asm/asm-offsets.h>
> +#include <asm/bootparam.h>
> +#include <asm/page_types.h>
> +#include <asm/irq_vectors.h>
> +#include <linux/slr_table.h>
> +#include <linux/slaunch.h>
> +
> +/* CPUID: leaf 1, ECX, SMX feature bit */
> +#define X86_FEATURE_BIT_SMX	(1 << 6)
> +
> +/* Can't include apiddef.h in asm */
> +#define XAPIC_ENABLE	(1 << 11)
> +#define X2APIC_ENABLE	(1 << 10)
> +
> +/* Can't include traps.h in asm */
> +#define X86_TRAP_NMI	2
> +
> +/* Can't include mtrr.h in asm */
> +#define MTRRphysBase0	0x200
> +
> +#define IDT_VECTOR_LO_BITS	0
> +#define IDT_VECTOR_HI_BITS	6
> +
> +/*
> + * See the comment in head_64.S for detailed informatoin on what this macro

nit: s/informatoin/information/

...

> diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
> index 01d19fc..74e3e7df 100644
> --- a/arch/x86/include/uapi/asm/bootparam.h
> +++ b/arch/x86/include/uapi/asm/bootparam.h
> @@ -26,6 +26,7 @@
>  /* loadflags */
>  #define LOADED_HIGH	(1<<0)
>  #define KASLR_FLAG	(1<<1)
> +#define SLAUNCH_FLAG	(1<<2)
>  #define QUIET_FLAG	(1<<5)
>  #define KEEP_SEGMENTS	(1<<6)
>  #define CAN_USE_HEAP	(1<<7)

nit: please consider using BIT()

...

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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-05 17:52     ` Simon Horman
  -1 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 17:52 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:17PM +0000, Ross Philipson wrote:
> The routine slaunch_setup is called out of the x86 specific setup_arch
> routine during early kernel boot. After determining what platform is
> present, various operations specific to that platform occur. This
> includes finalizing setting for the platform late launch and verifying
> that memory protections are in place.
> 
> For TXT, this code also reserves the original compressed kernel setup
> area where the APs were left looping so that this memory cannot be used.
> 
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>

Hi Ross,

a few nits from my side.

> +/*
> + * The TXT heap is too big to map all at once with early_ioremap
> + * so it is done a table at a time.
> + */
> +static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
> +					     u32 bytes)
> +{
> +	u64 base, size, offset = 0;
> +	void *heap;
> +	int i;
> +
> +	if (type > TXT_SINIT_TABLE_MAX)
> +		slaunch_txt_reset(txt,
> +			"Error invalid table type for early heap walk\n",
> +			SL_ERROR_HEAP_WALK);

nit: the indentation should align to the opening '('.

		slaunch_txt_reset(txt,
				  "Error invalid table type for early heap walk\n",
				  SL_ERROR_HEAP_WALK);

Likewise in a few other places in this patch.

...

> +static void __init slaunch_txt_reserve_range(u64 base, u64 size)
> +{
> +	int type;
> +
> +	type = e820__get_entry_type(base, base + size - 1);
> +	if (type == E820_TYPE_RAM) {
> +		pr_info("memblock reserve base: %llx size: %llx\n", base, size);
> +		memblock_reserve(base, size);
> +	}
> +}
> +
> +/*
> + * For Intel, certain regions of memory must be marked as reserved by putting
> + * them on the memblock reserved list if they are not already e820 reserved.
> + * This includes:
> + *  - The TXT HEAP
> + *  - The ACM area
> + *  - The TXT private register bank
> + *  - The MDR list sent to the MLE by the ACM (see TXT specification)
> + *  (Normally the above are properly reserved by firmware but if it was not
> + *  done, reserve them now)
> + *  - The AP wake block
> + *  - TPM log external to the TXT heap
> + *
> + * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
> + * the low PMR must be reservered too.

nit: s/reservered/reserved/

> + */
> +static void __init slaunch_txt_reserve(void __iomem *txt)
> +{
> +	struct txt_sinit_memory_descriptor_record *mdr;
> +	struct txt_sinit_mle_data *sinit_mle_data;
> +	u64 base, size, heap_base, heap_size;
> +	u32 mdrnum, mdroffset, mdrslen;
> +	u32 field_offset, i;
> +	void *mdrs;
> +
> +	base = TXT_PRIV_CONFIG_REGS_BASE;
> +	size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
> +	slaunch_txt_reserve_range(base, size);
> +
> +	memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
> +	memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
> +	slaunch_txt_reserve_range(heap_base, heap_size);
> +
> +	memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
> +	memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
> +	slaunch_txt_reserve_range(base, size);
> +
> +	field_offset = offsetof(struct txt_sinit_mle_data,
> +				sinit_vtd_dmar_table_size);
> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +						  field_offset);
> +
> +	mdrnum = sinit_mle_data->num_of_sinit_mdrs;
> +	mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
> +
> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
> +
> +	if (!mdrnum)
> +		goto nomdr;
> +
> +	mdrslen = mdrnum * sizeof(struct txt_sinit_memory_descriptor_record);
> +
> +	mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +					mdroffset + mdrslen - 8);
> +
> +	mdr = mdrs + mdroffset - 8;
> +
> +	for (i = 0; i < mdrnum; i++, mdr++) {
> +		/* Spec says some entries can have length 0, ignore them */
> +		if (mdr->type > 0 && mdr->length > 0)
> +			slaunch_txt_reserve_range(mdr->address, mdr->length);
> +	}
> +
> +	txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
> +
> +nomdr:
> +	slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
> +				  ap_wake_info.ap_wake_block_size);
> +
> +	/*
> +	 * Earlier checks ensured that the event log was properly situated
> +	 * either inside the TXT heap or outside. This is a check to see if the
> +	 * event log needs to be reserved. If it is in the TXT heap, it is
> +	 * already reserved.
> +	 */
> +	if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
> +		slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
> +
> +	for (i = 0; i < e820_table->nr_entries; i++) {
> +		base = e820_table->entries[i].addr;
> +		size = e820_table->entries[i].size;
> +		if ((base >= vtd_pmr_lo_size) && (base < 0x100000000ULL))

nit: unnecessary parentheses

> +			slaunch_txt_reserve_range(base, size);
> +		else if ((base < vtd_pmr_lo_size) &&
> +			 (base + size > vtd_pmr_lo_size))
> +			slaunch_txt_reserve_range(vtd_pmr_lo_size,
> +						  base + size - vtd_pmr_lo_size);
> +	}
> +}
> +
> +/*
> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
> + * It is stored in the TXT heap. Fetch it from there and make it available
> + * to the IOMMU driver.
> + */
> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
> +{
> +	struct txt_sinit_mle_data *sinit_mle_data;
> +	u32 field_offset, dmar_size, dmar_offset;
> +	void *dmar;
> +
> +	memset(&txt_dmar, 0, PAGE_SIZE);
> +
> +	field_offset = offsetof(struct txt_sinit_mle_data,
> +				processor_scrtm_status);
> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +						  field_offset);
> +
> +	dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
> +	dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
> +
> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
> +
> +	if (!dmar_size || !dmar_offset)
> +		slaunch_txt_reset(txt,
> +				  "Error invalid DMAR table values\n",
> +				  SL_ERROR_HEAP_INVALID_DMAR);
> +
> +	if (unlikely(dmar_size > PAGE_SIZE))
> +		slaunch_txt_reset(txt,
> +				  "Error DMAR too big to store\n",
> +				  SL_ERROR_HEAP_DMAR_SIZE);
> +
> +

nit: one blank line is enough

> +	dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +					dmar_offset + dmar_size - 8);
> +	if (!dmar)
> +		slaunch_txt_reset(txt,
> +				  "Error early_ioremap of DMAR\n",
> +				  SL_ERROR_HEAP_DMAR_MAP);
> +
> +	memcpy(&txt_dmar[0], dmar + dmar_offset - 8, dmar_size);
> +
> +	txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
> +}

...

> +/*
> + * Intel TXT specific late stub setup and validation.
> + */
> +void __init slaunch_setup_txt(void)
> +{
> +	u64 one = TXT_REGVALUE_ONE, val;
> +	void __iomem *txt;
> +
> +	if (!boot_cpu_has(X86_FEATURE_SMX))
> +		return;
> +
> +	/*
> +	 * If booted through secure launch entry point, the loadflags
> +	 * option will be set.
> +	 */
> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
> +		return;
> +
> +	/*
> +	 * See if SENTER was done by reading the status register in the
> +	 * public space. If the public register space cannot be read, TXT may
> +	 * be disabled.
> +	 */
> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +	if (!txt)
> +		return;
> +
> +	memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +
> +	/* SENTER should have been done */
> +	if (!(val & TXT_SENTER_DONE_STS))
> +		panic("Error TXT.STS SENTER_DONE not set\n");
> +
> +	/* SEXIT should have been cleared */
> +	if (val & TXT_SEXIT_DONE_STS)
> +		panic("Error TXT.STS SEXIT_DONE set\n");
> +
> +	/* Now we want to use the private register space */
> +	txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +	if (!txt) {
> +		/* This is really bad, no where to go from here */
> +		panic("Error early_ioremap of TXT priv registers\n");
> +	}
> +
> +	/*
> +	 * Try to read the Intel VID from the TXT private registers to see if
> +	 * TXT measured launch happened properly and the private space is
> +	 * available.
> +	 */
> +	memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
> +	if ((val & 0xffff) != 0x8086) {
> +		/*
> +		 * Can't do a proper TXT reset since it appears something is
> +		 * wrong even though SENTER happened and it should be in SMX
> +		 * mode.
> +		 */
> +		panic("Invalid TXT vendor ID, not in SMX mode\n");
> +	}
> +
> +	/* Set flags so subsequent code knows the status of the launch */
> +	sl_flags |= (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT);

nit: spaces around '|'

...

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
@ 2023-05-05 17:52     ` Simon Horman
  0 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 17:52 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:17PM +0000, Ross Philipson wrote:
> The routine slaunch_setup is called out of the x86 specific setup_arch
> routine during early kernel boot. After determining what platform is
> present, various operations specific to that platform occur. This
> includes finalizing setting for the platform late launch and verifying
> that memory protections are in place.
> 
> For TXT, this code also reserves the original compressed kernel setup
> area where the APs were left looping so that this memory cannot be used.
> 
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>

Hi Ross,

a few nits from my side.

> +/*
> + * The TXT heap is too big to map all at once with early_ioremap
> + * so it is done a table at a time.
> + */
> +static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
> +					     u32 bytes)
> +{
> +	u64 base, size, offset = 0;
> +	void *heap;
> +	int i;
> +
> +	if (type > TXT_SINIT_TABLE_MAX)
> +		slaunch_txt_reset(txt,
> +			"Error invalid table type for early heap walk\n",
> +			SL_ERROR_HEAP_WALK);

nit: the indentation should align to the opening '('.

		slaunch_txt_reset(txt,
				  "Error invalid table type for early heap walk\n",
				  SL_ERROR_HEAP_WALK);

Likewise in a few other places in this patch.

...

> +static void __init slaunch_txt_reserve_range(u64 base, u64 size)
> +{
> +	int type;
> +
> +	type = e820__get_entry_type(base, base + size - 1);
> +	if (type == E820_TYPE_RAM) {
> +		pr_info("memblock reserve base: %llx size: %llx\n", base, size);
> +		memblock_reserve(base, size);
> +	}
> +}
> +
> +/*
> + * For Intel, certain regions of memory must be marked as reserved by putting
> + * them on the memblock reserved list if they are not already e820 reserved.
> + * This includes:
> + *  - The TXT HEAP
> + *  - The ACM area
> + *  - The TXT private register bank
> + *  - The MDR list sent to the MLE by the ACM (see TXT specification)
> + *  (Normally the above are properly reserved by firmware but if it was not
> + *  done, reserve them now)
> + *  - The AP wake block
> + *  - TPM log external to the TXT heap
> + *
> + * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
> + * the low PMR must be reservered too.

nit: s/reservered/reserved/

> + */
> +static void __init slaunch_txt_reserve(void __iomem *txt)
> +{
> +	struct txt_sinit_memory_descriptor_record *mdr;
> +	struct txt_sinit_mle_data *sinit_mle_data;
> +	u64 base, size, heap_base, heap_size;
> +	u32 mdrnum, mdroffset, mdrslen;
> +	u32 field_offset, i;
> +	void *mdrs;
> +
> +	base = TXT_PRIV_CONFIG_REGS_BASE;
> +	size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
> +	slaunch_txt_reserve_range(base, size);
> +
> +	memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
> +	memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
> +	slaunch_txt_reserve_range(heap_base, heap_size);
> +
> +	memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
> +	memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
> +	slaunch_txt_reserve_range(base, size);
> +
> +	field_offset = offsetof(struct txt_sinit_mle_data,
> +				sinit_vtd_dmar_table_size);
> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +						  field_offset);
> +
> +	mdrnum = sinit_mle_data->num_of_sinit_mdrs;
> +	mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
> +
> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
> +
> +	if (!mdrnum)
> +		goto nomdr;
> +
> +	mdrslen = mdrnum * sizeof(struct txt_sinit_memory_descriptor_record);
> +
> +	mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +					mdroffset + mdrslen - 8);
> +
> +	mdr = mdrs + mdroffset - 8;
> +
> +	for (i = 0; i < mdrnum; i++, mdr++) {
> +		/* Spec says some entries can have length 0, ignore them */
> +		if (mdr->type > 0 && mdr->length > 0)
> +			slaunch_txt_reserve_range(mdr->address, mdr->length);
> +	}
> +
> +	txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
> +
> +nomdr:
> +	slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
> +				  ap_wake_info.ap_wake_block_size);
> +
> +	/*
> +	 * Earlier checks ensured that the event log was properly situated
> +	 * either inside the TXT heap or outside. This is a check to see if the
> +	 * event log needs to be reserved. If it is in the TXT heap, it is
> +	 * already reserved.
> +	 */
> +	if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
> +		slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
> +
> +	for (i = 0; i < e820_table->nr_entries; i++) {
> +		base = e820_table->entries[i].addr;
> +		size = e820_table->entries[i].size;
> +		if ((base >= vtd_pmr_lo_size) && (base < 0x100000000ULL))

nit: unnecessary parentheses

> +			slaunch_txt_reserve_range(base, size);
> +		else if ((base < vtd_pmr_lo_size) &&
> +			 (base + size > vtd_pmr_lo_size))
> +			slaunch_txt_reserve_range(vtd_pmr_lo_size,
> +						  base + size - vtd_pmr_lo_size);
> +	}
> +}
> +
> +/*
> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
> + * It is stored in the TXT heap. Fetch it from there and make it available
> + * to the IOMMU driver.
> + */
> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
> +{
> +	struct txt_sinit_mle_data *sinit_mle_data;
> +	u32 field_offset, dmar_size, dmar_offset;
> +	void *dmar;
> +
> +	memset(&txt_dmar, 0, PAGE_SIZE);
> +
> +	field_offset = offsetof(struct txt_sinit_mle_data,
> +				processor_scrtm_status);
> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +						  field_offset);
> +
> +	dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
> +	dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
> +
> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
> +
> +	if (!dmar_size || !dmar_offset)
> +		slaunch_txt_reset(txt,
> +				  "Error invalid DMAR table values\n",
> +				  SL_ERROR_HEAP_INVALID_DMAR);
> +
> +	if (unlikely(dmar_size > PAGE_SIZE))
> +		slaunch_txt_reset(txt,
> +				  "Error DMAR too big to store\n",
> +				  SL_ERROR_HEAP_DMAR_SIZE);
> +
> +

nit: one blank line is enough

> +	dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +					dmar_offset + dmar_size - 8);
> +	if (!dmar)
> +		slaunch_txt_reset(txt,
> +				  "Error early_ioremap of DMAR\n",
> +				  SL_ERROR_HEAP_DMAR_MAP);
> +
> +	memcpy(&txt_dmar[0], dmar + dmar_offset - 8, dmar_size);
> +
> +	txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
> +}

...

> +/*
> + * Intel TXT specific late stub setup and validation.
> + */
> +void __init slaunch_setup_txt(void)
> +{
> +	u64 one = TXT_REGVALUE_ONE, val;
> +	void __iomem *txt;
> +
> +	if (!boot_cpu_has(X86_FEATURE_SMX))
> +		return;
> +
> +	/*
> +	 * If booted through secure launch entry point, the loadflags
> +	 * option will be set.
> +	 */
> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
> +		return;
> +
> +	/*
> +	 * See if SENTER was done by reading the status register in the
> +	 * public space. If the public register space cannot be read, TXT may
> +	 * be disabled.
> +	 */
> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +	if (!txt)
> +		return;
> +
> +	memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +
> +	/* SENTER should have been done */
> +	if (!(val & TXT_SENTER_DONE_STS))
> +		panic("Error TXT.STS SENTER_DONE not set\n");
> +
> +	/* SEXIT should have been cleared */
> +	if (val & TXT_SEXIT_DONE_STS)
> +		panic("Error TXT.STS SEXIT_DONE set\n");
> +
> +	/* Now we want to use the private register space */
> +	txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +	if (!txt) {
> +		/* This is really bad, no where to go from here */
> +		panic("Error early_ioremap of TXT priv registers\n");
> +	}
> +
> +	/*
> +	 * Try to read the Intel VID from the TXT private registers to see if
> +	 * TXT measured launch happened properly and the private space is
> +	 * available.
> +	 */
> +	memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
> +	if ((val & 0xffff) != 0x8086) {
> +		/*
> +		 * Can't do a proper TXT reset since it appears something is
> +		 * wrong even though SENTER happened and it should be in SMX
> +		 * mode.
> +		 */
> +		panic("Invalid TXT vendor ID, not in SMX mode\n");
> +	}
> +
> +	/* Set flags so subsequent code knows the status of the launch */
> +	sl_flags |= (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT);

nit: spaces around '|'

...

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

* Re: [PATCH v6 09/14] x86: Secure Launch SMP bringup support
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-05 17:54     ` Simon Horman
  -1 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 17:54 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:18PM +0000, Ross Philipson wrote:
> On Intel, the APs are left in a well documented state after TXT performs
> the late launch. Specifically they cannot have #INIT asserted on them so
> a standard startup via INIT/SIPI/SIPI cannot be performed. Instead the
> early SL stub code parked the APs in a pause/jmp loop waiting for an NMI.
> The modified SMP boot code is called for the Secure Launch case. The
> jump address for the RM piggy entry point is fixed up in the jump where
> the APs are waiting and an NMI IPI is sent to the AP. The AP vectors to
> the Secure Launch entry point in the RM piggy which mimics what the real
> mode code would do then jumps to the standard RM piggy protected mode
> entry point.
> 
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>

Hi Ross,

just one minor nit on this one.

>  /*
>   * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
>   * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
> @@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>  	cpumask_clear_cpu(cpu, cpu_initialized_mask);
>  	smp_mb();
>  
> +	/* With Intel TXT, the AP startup is totally different */
> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==

nit: spaces around '|'

> +	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {
> +		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
> +		goto txt_wake;
> +	}

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 09/14] x86: Secure Launch SMP bringup support
@ 2023-05-05 17:54     ` Simon Horman
  0 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 17:54 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:18PM +0000, Ross Philipson wrote:
> On Intel, the APs are left in a well documented state after TXT performs
> the late launch. Specifically they cannot have #INIT asserted on them so
> a standard startup via INIT/SIPI/SIPI cannot be performed. Instead the
> early SL stub code parked the APs in a pause/jmp loop waiting for an NMI.
> The modified SMP boot code is called for the Secure Launch case. The
> jump address for the RM piggy entry point is fixed up in the jump where
> the APs are waiting and an NMI IPI is sent to the AP. The AP vectors to
> the Secure Launch entry point in the RM piggy which mimics what the real
> mode code would do then jumps to the standard RM piggy protected mode
> entry point.
> 
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>

Hi Ross,

just one minor nit on this one.

>  /*
>   * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
>   * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
> @@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>  	cpumask_clear_cpu(cpu, cpu_initialized_mask);
>  	smp_mb();
>  
> +	/* With Intel TXT, the AP startup is totally different */
> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==

nit: spaces around '|'

> +	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {
> +		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
> +		goto txt_wake;
> +	}

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-05 17:47     ` Simon Horman
@ 2023-05-05 18:58       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 18:58 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 13:47, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:16PM +0000, Ross Philipson wrote:
>> The Secure Launch (SL) stub provides the entry point for Intel TXT (and
>> later AMD SKINIT) to vector to during the late launch. The symbol
>> sl_stub_entry is that entry point and its offset into the kernel is
>> conveyed to the launching code using the MLE (Measured Launch
>> Environment) header in the structure named mle_header. The offset of the
>> MLE header is set in the kernel_info. The routine sl_stub contains the
>> very early late launch setup code responsible for setting up the basic
>> environment to allow the normal kernel startup_32 code to proceed. It is
>> also responsible for properly waking and handling the APs on Intel
>> platforms. The routine sl_main which runs after entering 64b mode is
>> responsible for measuring configuration and module information before
>> it is used like the boot params, the kernel command line, the TXT heap,
>> an external initramfs, etc.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> 
> ...
> 
>> diff --git a/arch/x86/boot/compressed/sl_main.c b/arch/x86/boot/compressed/sl_main.c
> 
> ...
> 
>> +static void *evtlog_base;
>> +static u32 evtlog_size;
>> +static struct txt_heap_event_log_pointer2_1_element *log20_elem;
>> +static u32 tpm_log_ver = SL_TPM12_LOG;
>> +struct tcg_efi_specid_event_algs tpm_algs[SL_TPM20_MAX_ALGS] = {0};
> 
> tpm_algs seems to only be used in this file.
> Should it be static?
> 
>> +
>> +extern u32 sl_cpu_type;
>> +extern u32 sl_mle_start;
>> +extern struct boot_params *boot_params;
>> +
>> +static u64 sl_txt_read(u32 reg)
> 
> Perhaps reg should have an __iomem annotation.
> 
>> +{
>> +	return readq((void *)(u64)(TXT_PRIV_CONFIG_REGS_BASE + reg));
>> +}
>> +
>> +static void sl_txt_write(u32 reg, u64 val)
> 
> Likewise here.
> 
> ...
> 
>> +static void sl_check_pmr_coverage(void *base, u32 size, bool allow_hi)
>> +{
>> +	struct txt_os_sinit_data *os_sinit_data;
>> +	void *end = base + size;
>> +	void *txt_heap;
>> +
>> +	if (!(sl_cpu_type & SL_CPU_INTEL))
>> +		return;
>> +
>> +	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
>> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
>> +
>> +	if ((end >= (void *)0x100000000ULL) &&
>> +	    (base < (void *)0x100000000ULL))
>> +		sl_txt_reset(SL_ERROR_REGION_STRADDLE_4GB);
>> +
>> +	/*
>> +	 * Note that the late stub code validates that the hi PMR covers
>> +	 * all memory above 4G. At this point the code can only check that
>> +	 * regions are within the hi PMR but that is sufficient.
>> +	 */
>> +	if ((end > (void *)0x100000000ULL) &&
>> +	    (base >= (void *)0x100000000ULL)) {
>> +		if (allow_hi) {
>> +			if (end >= (void *)(os_sinit_data->vtd_pmr_hi_base +
>> +					   os_sinit_data->vtd_pmr_hi_size))
>> +				sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
>> +		} else
>> +			sl_txt_reset(SL_ERROR_REGION_ABOVE_4GB);
> 
> nit: if any arm of a condition has '{}' then all arms should have them.
>       So:
> 
> 		} else {
> 			sl_txt_reset(SL_ERROR_REGION_ABOVE_4GB);
> 		}
> 
> Also elsewhere in this patch.
> 
>> +	}
>> +
>> +	if (end >= (void *)os_sinit_data->vtd_pmr_lo_size)
>> +		sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
>> +}
>> +
>> +/*
>> + * Some MSRs are modified by the pre-launch code including the MTRRs.
>> + * The early MLE code has to restore these values. This code validates
>> + * the values after they are measured.
>> + */
>> +static void sl_txt_validate_msrs(struct txt_os_mle_data *os_mle_data)
>> +{
>> +	struct slr_txt_mtrr_state *saved_bsp_mtrrs;
>> +	u64 mtrr_caps, mtrr_def_type, mtrr_var;
>> +	struct slr_entry_intel_info *txt_info;
>> +	u64 misc_en_msr;
>> +	u32 vcnt, i;
>> +
>> +	txt_info = (struct slr_entry_intel_info *)os_mle_data->txt_info;
>> +	saved_bsp_mtrrs = &(txt_info->saved_bsp_mtrrs);
> 
> nit: unnecessary parentheses
> 
> ...
> 
>> +static void sl_validate_event_log_buffer(void)
>> +{
>> +	struct txt_os_sinit_data *os_sinit_data;
>> +	void *txt_heap, *txt_end;
>> +	void *mle_base, *mle_end;
>> +	void *evtlog_end;
>> +
>> +	if ((u64)evtlog_size > (LLONG_MAX - (u64)evtlog_base))
>> +		sl_txt_reset(SL_ERROR_INTEGER_OVERFLOW);
>> +	evtlog_end = evtlog_base + evtlog_size;
>> +
>> +	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
>> +	txt_end = txt_heap + sl_txt_read(TXT_CR_HEAP_SIZE);
>> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
>> +
>> +	mle_base = (void *)(u64)sl_mle_start;
>> +	mle_end = mle_base + os_sinit_data->mle_size;
>> +
>> +	/*
>> +	 * This check is to ensure the event log buffer does not overlap with
>> +	 * the MLE image.
>> +	 */
>> +	if ((evtlog_base >= mle_end) &&
>> +	    (evtlog_end > mle_end))
>> +		goto pmr_check; /* above */
> 
> Ditto.
> Also, the if condition could be one line.
> Also in several other places in this patch.
> 
>> +
>> +	if ((evtlog_end <= mle_base) &&
>> +	    (evtlog_base < mle_base))
>> +		goto pmr_check; /* below */
>> +
>> +	sl_txt_reset(SL_ERROR_MLE_BUFFER_OVERLAP);
>> +
>> +pmr_check:
>> +	/*
>> +	 * The TXT heap is protected by the DPR. If the TPM event log is
>> +	 * inside the TXT heap, there is no need for a PMR check.
>> +	 */
>> +	if ((evtlog_base > txt_heap) &&
>> +	    (evtlog_end < txt_end))
>> +		return;
>> +
>> +	sl_check_pmr_coverage(evtlog_base, evtlog_size, true);
>> +}
> 
>> +static void sl_process_extend_policy(struct slr_table *slrt)
>> +{
>> +	struct slr_entry_policy *policy;
>> +	struct slr_policy_entry *entry;
>> +	u16 i = 0;
>> +
>> +	policy =(struct slr_entry_policy *)
> 
> nit: space after '='
> 
> ...
> 
>> +static void sl_process_extend_uefi_config(struct slr_table *slrt)
>> +{
>> +	struct slr_entry_uefi_config *uefi_config;
>> +	struct slr_uefi_cfg_entry *uefi_entry;
>> +	u64 i;
>> +
>> +	uefi_config =(struct slr_entry_uefi_config *)
>> +		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_UEFI_CONFIG);
>> +
>> +	/* Optionally here depending on how SL kernel was booted */
>> +	if (!uefi_config)
>> +		return;
>> +
>> +	uefi_entry = (struct slr_uefi_cfg_entry *)((u8 *)uefi_config + sizeof(*uefi_config));
>> +
>> +	for ( ; i < uefi_config->nr_entries; i++, uefi_entry++) {
> 
> nit: i seems to be used without first being initialised.

All the ones prior to this we will fix.

> 
>> +		sl_tpm_extend_evtlog(uefi_entry->pcr, TXT_EVTYPE_SLAUNCH,
>> +				     (void *)uefi_entry->cfg, uefi_entry->size,
>> +				     uefi_entry->evt_info);
>> +	}
>> +}
>> +
>> +asmlinkage __visible void sl_check_region(void *base, u32 size)
>> +{
>> +	sl_check_pmr_coverage(base, size, false);
>> +}
> 
> I'm a nit unsure, what to do here, but clang-16 with W=1 says the following.
> 
> arch/x86/boot/compressed/sl_main.c:533:27: warning: no previous prototype for function 'sl_main' [-Wmissing-prototypes]
> asmlinkage __visible void sl_main(void *bootparams)
>                            ^
> arch/x86/boot/compressed/sl_main.c:533:22: note: declare 'static' if the function is not intended to be used outside of this translation unit
> asmlinkage __visible void sl_main(void *bootparams)
>                       ^
>                       static

Yea we will have to look into why this is. This function is only ever 
called from asm code so that might have something to do with this.

> 
> ...
> 
>> diff --git a/arch/x86/boot/compressed/sl_stub.S b/arch/x86/boot/compressed/sl_stub.S
>> new file mode 100644
>> index 0000000..2d8aa3a
>> --- /dev/null
>> +++ b/arch/x86/boot/compressed/sl_stub.S
>> @@ -0,0 +1,690 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +
>> +/*
>> + * Secure Launch protected mode entry point.
>> + *
>> + * Copyright (c) 2022, Oracle and/or its affiliates.
>> + */
>> +	.code32
>> +	.text
>> +#include <linux/linkage.h>
>> +#include <asm/segment.h>
>> +#include <asm/msr.h>
>> +#include <asm/processor-flags.h>
>> +#include <asm/asm-offsets.h>
>> +#include <asm/bootparam.h>
>> +#include <asm/page_types.h>
>> +#include <asm/irq_vectors.h>
>> +#include <linux/slr_table.h>
>> +#include <linux/slaunch.h>
>> +
>> +/* CPUID: leaf 1, ECX, SMX feature bit */
>> +#define X86_FEATURE_BIT_SMX	(1 << 6)
>> +
>> +/* Can't include apiddef.h in asm */
>> +#define XAPIC_ENABLE	(1 << 11)
>> +#define X2APIC_ENABLE	(1 << 10)
>> +
>> +/* Can't include traps.h in asm */
>> +#define X86_TRAP_NMI	2
>> +
>> +/* Can't include mtrr.h in asm */
>> +#define MTRRphysBase0	0x200
>> +
>> +#define IDT_VECTOR_LO_BITS	0
>> +#define IDT_VECTOR_HI_BITS	6
>> +
>> +/*
>> + * See the comment in head_64.S for detailed informatoin on what this macro
> 
> nit: s/informatoin/information/
> 
> ...
> 
>> diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
>> index 01d19fc..74e3e7df 100644
>> --- a/arch/x86/include/uapi/asm/bootparam.h
>> +++ b/arch/x86/include/uapi/asm/bootparam.h
>> @@ -26,6 +26,7 @@
>>   /* loadflags */
>>   #define LOADED_HIGH	(1<<0)
>>   #define KASLR_FLAG	(1<<1)
>> +#define SLAUNCH_FLAG	(1<<2)
>>   #define QUIET_FLAG	(1<<5)
>>   #define KEEP_SEGMENTS	(1<<6)
>>   #define CAN_USE_HEAP	(1<<7)
> 
> nit: please consider using BIT()

I am a little reluctant to change something like this in an existing 
header. It seems a bit out of scope for the patch set.

Thanks
Ross

> 
> ...


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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-05-05 18:58       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 18:58 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 13:47, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:16PM +0000, Ross Philipson wrote:
>> The Secure Launch (SL) stub provides the entry point for Intel TXT (and
>> later AMD SKINIT) to vector to during the late launch. The symbol
>> sl_stub_entry is that entry point and its offset into the kernel is
>> conveyed to the launching code using the MLE (Measured Launch
>> Environment) header in the structure named mle_header. The offset of the
>> MLE header is set in the kernel_info. The routine sl_stub contains the
>> very early late launch setup code responsible for setting up the basic
>> environment to allow the normal kernel startup_32 code to proceed. It is
>> also responsible for properly waking and handling the APs on Intel
>> platforms. The routine sl_main which runs after entering 64b mode is
>> responsible for measuring configuration and module information before
>> it is used like the boot params, the kernel command line, the TXT heap,
>> an external initramfs, etc.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> 
> ...
> 
>> diff --git a/arch/x86/boot/compressed/sl_main.c b/arch/x86/boot/compressed/sl_main.c
> 
> ...
> 
>> +static void *evtlog_base;
>> +static u32 evtlog_size;
>> +static struct txt_heap_event_log_pointer2_1_element *log20_elem;
>> +static u32 tpm_log_ver = SL_TPM12_LOG;
>> +struct tcg_efi_specid_event_algs tpm_algs[SL_TPM20_MAX_ALGS] = {0};
> 
> tpm_algs seems to only be used in this file.
> Should it be static?
> 
>> +
>> +extern u32 sl_cpu_type;
>> +extern u32 sl_mle_start;
>> +extern struct boot_params *boot_params;
>> +
>> +static u64 sl_txt_read(u32 reg)
> 
> Perhaps reg should have an __iomem annotation.
> 
>> +{
>> +	return readq((void *)(u64)(TXT_PRIV_CONFIG_REGS_BASE + reg));
>> +}
>> +
>> +static void sl_txt_write(u32 reg, u64 val)
> 
> Likewise here.
> 
> ...
> 
>> +static void sl_check_pmr_coverage(void *base, u32 size, bool allow_hi)
>> +{
>> +	struct txt_os_sinit_data *os_sinit_data;
>> +	void *end = base + size;
>> +	void *txt_heap;
>> +
>> +	if (!(sl_cpu_type & SL_CPU_INTEL))
>> +		return;
>> +
>> +	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
>> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
>> +
>> +	if ((end >= (void *)0x100000000ULL) &&
>> +	    (base < (void *)0x100000000ULL))
>> +		sl_txt_reset(SL_ERROR_REGION_STRADDLE_4GB);
>> +
>> +	/*
>> +	 * Note that the late stub code validates that the hi PMR covers
>> +	 * all memory above 4G. At this point the code can only check that
>> +	 * regions are within the hi PMR but that is sufficient.
>> +	 */
>> +	if ((end > (void *)0x100000000ULL) &&
>> +	    (base >= (void *)0x100000000ULL)) {
>> +		if (allow_hi) {
>> +			if (end >= (void *)(os_sinit_data->vtd_pmr_hi_base +
>> +					   os_sinit_data->vtd_pmr_hi_size))
>> +				sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
>> +		} else
>> +			sl_txt_reset(SL_ERROR_REGION_ABOVE_4GB);
> 
> nit: if any arm of a condition has '{}' then all arms should have them.
>       So:
> 
> 		} else {
> 			sl_txt_reset(SL_ERROR_REGION_ABOVE_4GB);
> 		}
> 
> Also elsewhere in this patch.
> 
>> +	}
>> +
>> +	if (end >= (void *)os_sinit_data->vtd_pmr_lo_size)
>> +		sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
>> +}
>> +
>> +/*
>> + * Some MSRs are modified by the pre-launch code including the MTRRs.
>> + * The early MLE code has to restore these values. This code validates
>> + * the values after they are measured.
>> + */
>> +static void sl_txt_validate_msrs(struct txt_os_mle_data *os_mle_data)
>> +{
>> +	struct slr_txt_mtrr_state *saved_bsp_mtrrs;
>> +	u64 mtrr_caps, mtrr_def_type, mtrr_var;
>> +	struct slr_entry_intel_info *txt_info;
>> +	u64 misc_en_msr;
>> +	u32 vcnt, i;
>> +
>> +	txt_info = (struct slr_entry_intel_info *)os_mle_data->txt_info;
>> +	saved_bsp_mtrrs = &(txt_info->saved_bsp_mtrrs);
> 
> nit: unnecessary parentheses
> 
> ...
> 
>> +static void sl_validate_event_log_buffer(void)
>> +{
>> +	struct txt_os_sinit_data *os_sinit_data;
>> +	void *txt_heap, *txt_end;
>> +	void *mle_base, *mle_end;
>> +	void *evtlog_end;
>> +
>> +	if ((u64)evtlog_size > (LLONG_MAX - (u64)evtlog_base))
>> +		sl_txt_reset(SL_ERROR_INTEGER_OVERFLOW);
>> +	evtlog_end = evtlog_base + evtlog_size;
>> +
>> +	txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
>> +	txt_end = txt_heap + sl_txt_read(TXT_CR_HEAP_SIZE);
>> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
>> +
>> +	mle_base = (void *)(u64)sl_mle_start;
>> +	mle_end = mle_base + os_sinit_data->mle_size;
>> +
>> +	/*
>> +	 * This check is to ensure the event log buffer does not overlap with
>> +	 * the MLE image.
>> +	 */
>> +	if ((evtlog_base >= mle_end) &&
>> +	    (evtlog_end > mle_end))
>> +		goto pmr_check; /* above */
> 
> Ditto.
> Also, the if condition could be one line.
> Also in several other places in this patch.
> 
>> +
>> +	if ((evtlog_end <= mle_base) &&
>> +	    (evtlog_base < mle_base))
>> +		goto pmr_check; /* below */
>> +
>> +	sl_txt_reset(SL_ERROR_MLE_BUFFER_OVERLAP);
>> +
>> +pmr_check:
>> +	/*
>> +	 * The TXT heap is protected by the DPR. If the TPM event log is
>> +	 * inside the TXT heap, there is no need for a PMR check.
>> +	 */
>> +	if ((evtlog_base > txt_heap) &&
>> +	    (evtlog_end < txt_end))
>> +		return;
>> +
>> +	sl_check_pmr_coverage(evtlog_base, evtlog_size, true);
>> +}
> 
>> +static void sl_process_extend_policy(struct slr_table *slrt)
>> +{
>> +	struct slr_entry_policy *policy;
>> +	struct slr_policy_entry *entry;
>> +	u16 i = 0;
>> +
>> +	policy =(struct slr_entry_policy *)
> 
> nit: space after '='
> 
> ...
> 
>> +static void sl_process_extend_uefi_config(struct slr_table *slrt)
>> +{
>> +	struct slr_entry_uefi_config *uefi_config;
>> +	struct slr_uefi_cfg_entry *uefi_entry;
>> +	u64 i;
>> +
>> +	uefi_config =(struct slr_entry_uefi_config *)
>> +		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_UEFI_CONFIG);
>> +
>> +	/* Optionally here depending on how SL kernel was booted */
>> +	if (!uefi_config)
>> +		return;
>> +
>> +	uefi_entry = (struct slr_uefi_cfg_entry *)((u8 *)uefi_config + sizeof(*uefi_config));
>> +
>> +	for ( ; i < uefi_config->nr_entries; i++, uefi_entry++) {
> 
> nit: i seems to be used without first being initialised.

All the ones prior to this we will fix.

> 
>> +		sl_tpm_extend_evtlog(uefi_entry->pcr, TXT_EVTYPE_SLAUNCH,
>> +				     (void *)uefi_entry->cfg, uefi_entry->size,
>> +				     uefi_entry->evt_info);
>> +	}
>> +}
>> +
>> +asmlinkage __visible void sl_check_region(void *base, u32 size)
>> +{
>> +	sl_check_pmr_coverage(base, size, false);
>> +}
> 
> I'm a nit unsure, what to do here, but clang-16 with W=1 says the following.
> 
> arch/x86/boot/compressed/sl_main.c:533:27: warning: no previous prototype for function 'sl_main' [-Wmissing-prototypes]
> asmlinkage __visible void sl_main(void *bootparams)
>                            ^
> arch/x86/boot/compressed/sl_main.c:533:22: note: declare 'static' if the function is not intended to be used outside of this translation unit
> asmlinkage __visible void sl_main(void *bootparams)
>                       ^
>                       static

Yea we will have to look into why this is. This function is only ever 
called from asm code so that might have something to do with this.

> 
> ...
> 
>> diff --git a/arch/x86/boot/compressed/sl_stub.S b/arch/x86/boot/compressed/sl_stub.S
>> new file mode 100644
>> index 0000000..2d8aa3a
>> --- /dev/null
>> +++ b/arch/x86/boot/compressed/sl_stub.S
>> @@ -0,0 +1,690 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +
>> +/*
>> + * Secure Launch protected mode entry point.
>> + *
>> + * Copyright (c) 2022, Oracle and/or its affiliates.
>> + */
>> +	.code32
>> +	.text
>> +#include <linux/linkage.h>
>> +#include <asm/segment.h>
>> +#include <asm/msr.h>
>> +#include <asm/processor-flags.h>
>> +#include <asm/asm-offsets.h>
>> +#include <asm/bootparam.h>
>> +#include <asm/page_types.h>
>> +#include <asm/irq_vectors.h>
>> +#include <linux/slr_table.h>
>> +#include <linux/slaunch.h>
>> +
>> +/* CPUID: leaf 1, ECX, SMX feature bit */
>> +#define X86_FEATURE_BIT_SMX	(1 << 6)
>> +
>> +/* Can't include apiddef.h in asm */
>> +#define XAPIC_ENABLE	(1 << 11)
>> +#define X2APIC_ENABLE	(1 << 10)
>> +
>> +/* Can't include traps.h in asm */
>> +#define X86_TRAP_NMI	2
>> +
>> +/* Can't include mtrr.h in asm */
>> +#define MTRRphysBase0	0x200
>> +
>> +#define IDT_VECTOR_LO_BITS	0
>> +#define IDT_VECTOR_HI_BITS	6
>> +
>> +/*
>> + * See the comment in head_64.S for detailed informatoin on what this macro
> 
> nit: s/informatoin/information/
> 
> ...
> 
>> diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
>> index 01d19fc..74e3e7df 100644
>> --- a/arch/x86/include/uapi/asm/bootparam.h
>> +++ b/arch/x86/include/uapi/asm/bootparam.h
>> @@ -26,6 +26,7 @@
>>   /* loadflags */
>>   #define LOADED_HIGH	(1<<0)
>>   #define KASLR_FLAG	(1<<1)
>> +#define SLAUNCH_FLAG	(1<<2)
>>   #define QUIET_FLAG	(1<<5)
>>   #define KEEP_SEGMENTS	(1<<6)
>>   #define CAN_USE_HEAP	(1<<7)
> 
> nit: please consider using BIT()

I am a little reluctant to change something like this in an existing 
header. It seems a bit out of scope for the patch set.

Thanks
Ross

> 
> ...


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
  2023-05-05 17:52     ` Simon Horman
@ 2023-05-05 18:59       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 18:59 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 13:52, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:17PM +0000, Ross Philipson wrote:
>> The routine slaunch_setup is called out of the x86 specific setup_arch
>> routine during early kernel boot. After determining what platform is
>> present, various operations specific to that platform occur. This
>> includes finalizing setting for the platform late launch and verifying
>> that memory protections are in place.
>>
>> For TXT, this code also reserves the original compressed kernel setup
>> area where the APs were left looping so that this memory cannot be used.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> 
> Hi Ross,
> 
> a few nits from my side.

Yup we will fix all of those.

Thanks
Ross

> 
>> +/*
>> + * The TXT heap is too big to map all at once with early_ioremap
>> + * so it is done a table at a time.
>> + */
>> +static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
>> +					     u32 bytes)
>> +{
>> +	u64 base, size, offset = 0;
>> +	void *heap;
>> +	int i;
>> +
>> +	if (type > TXT_SINIT_TABLE_MAX)
>> +		slaunch_txt_reset(txt,
>> +			"Error invalid table type for early heap walk\n",
>> +			SL_ERROR_HEAP_WALK);
> 
> nit: the indentation should align to the opening '('.
> 
> 		slaunch_txt_reset(txt,
> 				  "Error invalid table type for early heap walk\n",
> 				  SL_ERROR_HEAP_WALK);
> 
> Likewise in a few other places in this patch.
> 
> ...
> 
>> +static void __init slaunch_txt_reserve_range(u64 base, u64 size)
>> +{
>> +	int type;
>> +
>> +	type = e820__get_entry_type(base, base + size - 1);
>> +	if (type == E820_TYPE_RAM) {
>> +		pr_info("memblock reserve base: %llx size: %llx\n", base, size);
>> +		memblock_reserve(base, size);
>> +	}
>> +}
>> +
>> +/*
>> + * For Intel, certain regions of memory must be marked as reserved by putting
>> + * them on the memblock reserved list if they are not already e820 reserved.
>> + * This includes:
>> + *  - The TXT HEAP
>> + *  - The ACM area
>> + *  - The TXT private register bank
>> + *  - The MDR list sent to the MLE by the ACM (see TXT specification)
>> + *  (Normally the above are properly reserved by firmware but if it was not
>> + *  done, reserve them now)
>> + *  - The AP wake block
>> + *  - TPM log external to the TXT heap
>> + *
>> + * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
>> + * the low PMR must be reservered too.
> 
> nit: s/reservered/reserved/
> 
>> + */
>> +static void __init slaunch_txt_reserve(void __iomem *txt)
>> +{
>> +	struct txt_sinit_memory_descriptor_record *mdr;
>> +	struct txt_sinit_mle_data *sinit_mle_data;
>> +	u64 base, size, heap_base, heap_size;
>> +	u32 mdrnum, mdroffset, mdrslen;
>> +	u32 field_offset, i;
>> +	void *mdrs;
>> +
>> +	base = TXT_PRIV_CONFIG_REGS_BASE;
>> +	size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
>> +	slaunch_txt_reserve_range(base, size);
>> +
>> +	memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
>> +	memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
>> +	slaunch_txt_reserve_range(heap_base, heap_size);
>> +
>> +	memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
>> +	memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
>> +	slaunch_txt_reserve_range(base, size);
>> +
>> +	field_offset = offsetof(struct txt_sinit_mle_data,
>> +				sinit_vtd_dmar_table_size);
>> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +						  field_offset);
>> +
>> +	mdrnum = sinit_mle_data->num_of_sinit_mdrs;
>> +	mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
>> +
>> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
>> +
>> +	if (!mdrnum)
>> +		goto nomdr;
>> +
>> +	mdrslen = mdrnum * sizeof(struct txt_sinit_memory_descriptor_record);
>> +
>> +	mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +					mdroffset + mdrslen - 8);
>> +
>> +	mdr = mdrs + mdroffset - 8;
>> +
>> +	for (i = 0; i < mdrnum; i++, mdr++) {
>> +		/* Spec says some entries can have length 0, ignore them */
>> +		if (mdr->type > 0 && mdr->length > 0)
>> +			slaunch_txt_reserve_range(mdr->address, mdr->length);
>> +	}
>> +
>> +	txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
>> +
>> +nomdr:
>> +	slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
>> +				  ap_wake_info.ap_wake_block_size);
>> +
>> +	/*
>> +	 * Earlier checks ensured that the event log was properly situated
>> +	 * either inside the TXT heap or outside. This is a check to see if the
>> +	 * event log needs to be reserved. If it is in the TXT heap, it is
>> +	 * already reserved.
>> +	 */
>> +	if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
>> +		slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
>> +
>> +	for (i = 0; i < e820_table->nr_entries; i++) {
>> +		base = e820_table->entries[i].addr;
>> +		size = e820_table->entries[i].size;
>> +		if ((base >= vtd_pmr_lo_size) && (base < 0x100000000ULL))
> 
> nit: unnecessary parentheses
> 
>> +			slaunch_txt_reserve_range(base, size);
>> +		else if ((base < vtd_pmr_lo_size) &&
>> +			 (base + size > vtd_pmr_lo_size))
>> +			slaunch_txt_reserve_range(vtd_pmr_lo_size,
>> +						  base + size - vtd_pmr_lo_size);
>> +	}
>> +}
>> +
>> +/*
>> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
>> + * It is stored in the TXT heap. Fetch it from there and make it available
>> + * to the IOMMU driver.
>> + */
>> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
>> +{
>> +	struct txt_sinit_mle_data *sinit_mle_data;
>> +	u32 field_offset, dmar_size, dmar_offset;
>> +	void *dmar;
>> +
>> +	memset(&txt_dmar, 0, PAGE_SIZE);
>> +
>> +	field_offset = offsetof(struct txt_sinit_mle_data,
>> +				processor_scrtm_status);
>> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +						  field_offset);
>> +
>> +	dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
>> +	dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
>> +
>> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
>> +
>> +	if (!dmar_size || !dmar_offset)
>> +		slaunch_txt_reset(txt,
>> +				  "Error invalid DMAR table values\n",
>> +				  SL_ERROR_HEAP_INVALID_DMAR);
>> +
>> +	if (unlikely(dmar_size > PAGE_SIZE))
>> +		slaunch_txt_reset(txt,
>> +				  "Error DMAR too big to store\n",
>> +				  SL_ERROR_HEAP_DMAR_SIZE);
>> +
>> +
> 
> nit: one blank line is enough
> 
>> +	dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +					dmar_offset + dmar_size - 8);
>> +	if (!dmar)
>> +		slaunch_txt_reset(txt,
>> +				  "Error early_ioremap of DMAR\n",
>> +				  SL_ERROR_HEAP_DMAR_MAP);
>> +
>> +	memcpy(&txt_dmar[0], dmar + dmar_offset - 8, dmar_size);
>> +
>> +	txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
>> +}
> 
> ...
> 
>> +/*
>> + * Intel TXT specific late stub setup and validation.
>> + */
>> +void __init slaunch_setup_txt(void)
>> +{
>> +	u64 one = TXT_REGVALUE_ONE, val;
>> +	void __iomem *txt;
>> +
>> +	if (!boot_cpu_has(X86_FEATURE_SMX))
>> +		return;
>> +
>> +	/*
>> +	 * If booted through secure launch entry point, the loadflags
>> +	 * option will be set.
>> +	 */
>> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
>> +		return;
>> +
>> +	/*
>> +	 * See if SENTER was done by reading the status register in the
>> +	 * public space. If the public register space cannot be read, TXT may
>> +	 * be disabled.
>> +	 */
>> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
>> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +	if (!txt)
>> +		return;
>> +
>> +	memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
>> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +
>> +	/* SENTER should have been done */
>> +	if (!(val & TXT_SENTER_DONE_STS))
>> +		panic("Error TXT.STS SENTER_DONE not set\n");
>> +
>> +	/* SEXIT should have been cleared */
>> +	if (val & TXT_SEXIT_DONE_STS)
>> +		panic("Error TXT.STS SEXIT_DONE set\n");
>> +
>> +	/* Now we want to use the private register space */
>> +	txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
>> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +	if (!txt) {
>> +		/* This is really bad, no where to go from here */
>> +		panic("Error early_ioremap of TXT priv registers\n");
>> +	}
>> +
>> +	/*
>> +	 * Try to read the Intel VID from the TXT private registers to see if
>> +	 * TXT measured launch happened properly and the private space is
>> +	 * available.
>> +	 */
>> +	memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
>> +	if ((val & 0xffff) != 0x8086) {
>> +		/*
>> +		 * Can't do a proper TXT reset since it appears something is
>> +		 * wrong even though SENTER happened and it should be in SMX
>> +		 * mode.
>> +		 */
>> +		panic("Invalid TXT vendor ID, not in SMX mode\n");
>> +	}
>> +
>> +	/* Set flags so subsequent code knows the status of the launch */
>> +	sl_flags |= (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT);
> 
> nit: spaces around '|'
> 
> ...
> 


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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
@ 2023-05-05 18:59       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 18:59 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 13:52, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:17PM +0000, Ross Philipson wrote:
>> The routine slaunch_setup is called out of the x86 specific setup_arch
>> routine during early kernel boot. After determining what platform is
>> present, various operations specific to that platform occur. This
>> includes finalizing setting for the platform late launch and verifying
>> that memory protections are in place.
>>
>> For TXT, this code also reserves the original compressed kernel setup
>> area where the APs were left looping so that this memory cannot be used.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> 
> Hi Ross,
> 
> a few nits from my side.

Yup we will fix all of those.

Thanks
Ross

> 
>> +/*
>> + * The TXT heap is too big to map all at once with early_ioremap
>> + * so it is done a table at a time.
>> + */
>> +static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
>> +					     u32 bytes)
>> +{
>> +	u64 base, size, offset = 0;
>> +	void *heap;
>> +	int i;
>> +
>> +	if (type > TXT_SINIT_TABLE_MAX)
>> +		slaunch_txt_reset(txt,
>> +			"Error invalid table type for early heap walk\n",
>> +			SL_ERROR_HEAP_WALK);
> 
> nit: the indentation should align to the opening '('.
> 
> 		slaunch_txt_reset(txt,
> 				  "Error invalid table type for early heap walk\n",
> 				  SL_ERROR_HEAP_WALK);
> 
> Likewise in a few other places in this patch.
> 
> ...
> 
>> +static void __init slaunch_txt_reserve_range(u64 base, u64 size)
>> +{
>> +	int type;
>> +
>> +	type = e820__get_entry_type(base, base + size - 1);
>> +	if (type == E820_TYPE_RAM) {
>> +		pr_info("memblock reserve base: %llx size: %llx\n", base, size);
>> +		memblock_reserve(base, size);
>> +	}
>> +}
>> +
>> +/*
>> + * For Intel, certain regions of memory must be marked as reserved by putting
>> + * them on the memblock reserved list if they are not already e820 reserved.
>> + * This includes:
>> + *  - The TXT HEAP
>> + *  - The ACM area
>> + *  - The TXT private register bank
>> + *  - The MDR list sent to the MLE by the ACM (see TXT specification)
>> + *  (Normally the above are properly reserved by firmware but if it was not
>> + *  done, reserve them now)
>> + *  - The AP wake block
>> + *  - TPM log external to the TXT heap
>> + *
>> + * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
>> + * the low PMR must be reservered too.
> 
> nit: s/reservered/reserved/
> 
>> + */
>> +static void __init slaunch_txt_reserve(void __iomem *txt)
>> +{
>> +	struct txt_sinit_memory_descriptor_record *mdr;
>> +	struct txt_sinit_mle_data *sinit_mle_data;
>> +	u64 base, size, heap_base, heap_size;
>> +	u32 mdrnum, mdroffset, mdrslen;
>> +	u32 field_offset, i;
>> +	void *mdrs;
>> +
>> +	base = TXT_PRIV_CONFIG_REGS_BASE;
>> +	size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
>> +	slaunch_txt_reserve_range(base, size);
>> +
>> +	memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
>> +	memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
>> +	slaunch_txt_reserve_range(heap_base, heap_size);
>> +
>> +	memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
>> +	memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
>> +	slaunch_txt_reserve_range(base, size);
>> +
>> +	field_offset = offsetof(struct txt_sinit_mle_data,
>> +				sinit_vtd_dmar_table_size);
>> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +						  field_offset);
>> +
>> +	mdrnum = sinit_mle_data->num_of_sinit_mdrs;
>> +	mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
>> +
>> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
>> +
>> +	if (!mdrnum)
>> +		goto nomdr;
>> +
>> +	mdrslen = mdrnum * sizeof(struct txt_sinit_memory_descriptor_record);
>> +
>> +	mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +					mdroffset + mdrslen - 8);
>> +
>> +	mdr = mdrs + mdroffset - 8;
>> +
>> +	for (i = 0; i < mdrnum; i++, mdr++) {
>> +		/* Spec says some entries can have length 0, ignore them */
>> +		if (mdr->type > 0 && mdr->length > 0)
>> +			slaunch_txt_reserve_range(mdr->address, mdr->length);
>> +	}
>> +
>> +	txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
>> +
>> +nomdr:
>> +	slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
>> +				  ap_wake_info.ap_wake_block_size);
>> +
>> +	/*
>> +	 * Earlier checks ensured that the event log was properly situated
>> +	 * either inside the TXT heap or outside. This is a check to see if the
>> +	 * event log needs to be reserved. If it is in the TXT heap, it is
>> +	 * already reserved.
>> +	 */
>> +	if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
>> +		slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
>> +
>> +	for (i = 0; i < e820_table->nr_entries; i++) {
>> +		base = e820_table->entries[i].addr;
>> +		size = e820_table->entries[i].size;
>> +		if ((base >= vtd_pmr_lo_size) && (base < 0x100000000ULL))
> 
> nit: unnecessary parentheses
> 
>> +			slaunch_txt_reserve_range(base, size);
>> +		else if ((base < vtd_pmr_lo_size) &&
>> +			 (base + size > vtd_pmr_lo_size))
>> +			slaunch_txt_reserve_range(vtd_pmr_lo_size,
>> +						  base + size - vtd_pmr_lo_size);
>> +	}
>> +}
>> +
>> +/*
>> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
>> + * It is stored in the TXT heap. Fetch it from there and make it available
>> + * to the IOMMU driver.
>> + */
>> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
>> +{
>> +	struct txt_sinit_mle_data *sinit_mle_data;
>> +	u32 field_offset, dmar_size, dmar_offset;
>> +	void *dmar;
>> +
>> +	memset(&txt_dmar, 0, PAGE_SIZE);
>> +
>> +	field_offset = offsetof(struct txt_sinit_mle_data,
>> +				processor_scrtm_status);
>> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +						  field_offset);
>> +
>> +	dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
>> +	dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
>> +
>> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
>> +
>> +	if (!dmar_size || !dmar_offset)
>> +		slaunch_txt_reset(txt,
>> +				  "Error invalid DMAR table values\n",
>> +				  SL_ERROR_HEAP_INVALID_DMAR);
>> +
>> +	if (unlikely(dmar_size > PAGE_SIZE))
>> +		slaunch_txt_reset(txt,
>> +				  "Error DMAR too big to store\n",
>> +				  SL_ERROR_HEAP_DMAR_SIZE);
>> +
>> +
> 
> nit: one blank line is enough
> 
>> +	dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +					dmar_offset + dmar_size - 8);
>> +	if (!dmar)
>> +		slaunch_txt_reset(txt,
>> +				  "Error early_ioremap of DMAR\n",
>> +				  SL_ERROR_HEAP_DMAR_MAP);
>> +
>> +	memcpy(&txt_dmar[0], dmar + dmar_offset - 8, dmar_size);
>> +
>> +	txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
>> +}
> 
> ...
> 
>> +/*
>> + * Intel TXT specific late stub setup and validation.
>> + */
>> +void __init slaunch_setup_txt(void)
>> +{
>> +	u64 one = TXT_REGVALUE_ONE, val;
>> +	void __iomem *txt;
>> +
>> +	if (!boot_cpu_has(X86_FEATURE_SMX))
>> +		return;
>> +
>> +	/*
>> +	 * If booted through secure launch entry point, the loadflags
>> +	 * option will be set.
>> +	 */
>> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
>> +		return;
>> +
>> +	/*
>> +	 * See if SENTER was done by reading the status register in the
>> +	 * public space. If the public register space cannot be read, TXT may
>> +	 * be disabled.
>> +	 */
>> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
>> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +	if (!txt)
>> +		return;
>> +
>> +	memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
>> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +
>> +	/* SENTER should have been done */
>> +	if (!(val & TXT_SENTER_DONE_STS))
>> +		panic("Error TXT.STS SENTER_DONE not set\n");
>> +
>> +	/* SEXIT should have been cleared */
>> +	if (val & TXT_SEXIT_DONE_STS)
>> +		panic("Error TXT.STS SEXIT_DONE set\n");
>> +
>> +	/* Now we want to use the private register space */
>> +	txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
>> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +	if (!txt) {
>> +		/* This is really bad, no where to go from here */
>> +		panic("Error early_ioremap of TXT priv registers\n");
>> +	}
>> +
>> +	/*
>> +	 * Try to read the Intel VID from the TXT private registers to see if
>> +	 * TXT measured launch happened properly and the private space is
>> +	 * available.
>> +	 */
>> +	memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
>> +	if ((val & 0xffff) != 0x8086) {
>> +		/*
>> +		 * Can't do a proper TXT reset since it appears something is
>> +		 * wrong even though SENTER happened and it should be in SMX
>> +		 * mode.
>> +		 */
>> +		panic("Invalid TXT vendor ID, not in SMX mode\n");
>> +	}
>> +
>> +	/* Set flags so subsequent code knows the status of the launch */
>> +	sl_flags |= (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT);
> 
> nit: spaces around '|'
> 
> ...
> 


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 09/14] x86: Secure Launch SMP bringup support
  2023-05-05 17:54     ` Simon Horman
@ 2023-05-05 18:59       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 18:59 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 13:54, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:18PM +0000, Ross Philipson wrote:
>> On Intel, the APs are left in a well documented state after TXT performs
>> the late launch. Specifically they cannot have #INIT asserted on them so
>> a standard startup via INIT/SIPI/SIPI cannot be performed. Instead the
>> early SL stub code parked the APs in a pause/jmp loop waiting for an NMI.
>> The modified SMP boot code is called for the Secure Launch case. The
>> jump address for the RM piggy entry point is fixed up in the jump where
>> the APs are waiting and an NMI IPI is sent to the AP. The AP vectors to
>> the Secure Launch entry point in the RM piggy which mimics what the real
>> mode code would do then jumps to the standard RM piggy protected mode
>> entry point.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> 
> Hi Ross,
> 
> just one minor nit on this one.

Will fix, thanks.
Ross

> 
>>   /*
>>    * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
>>    * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
>> @@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>>   	cpumask_clear_cpu(cpu, cpu_initialized_mask);
>>   	smp_mb();
>>   
>> +	/* With Intel TXT, the AP startup is totally different */
>> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==
> 
> nit: spaces around '|'
> 
>> +	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {
>> +		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
>> +		goto txt_wake;
>> +	}


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

* Re: [PATCH v6 09/14] x86: Secure Launch SMP bringup support
@ 2023-05-05 18:59       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-05 18:59 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 13:54, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:18PM +0000, Ross Philipson wrote:
>> On Intel, the APs are left in a well documented state after TXT performs
>> the late launch. Specifically they cannot have #INIT asserted on them so
>> a standard startup via INIT/SIPI/SIPI cannot be performed. Instead the
>> early SL stub code parked the APs in a pause/jmp loop waiting for an NMI.
>> The modified SMP boot code is called for the Secure Launch case. The
>> jump address for the RM piggy entry point is fixed up in the jump where
>> the APs are waiting and an NMI IPI is sent to the AP. The AP vectors to
>> the Secure Launch entry point in the RM piggy which mimics what the real
>> mode code would do then jumps to the standard RM piggy protected mode
>> entry point.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> 
> Hi Ross,
> 
> just one minor nit on this one.

Will fix, thanks.
Ross

> 
>>   /*
>>    * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
>>    * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
>> @@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>>   	cpumask_clear_cpu(cpu, cpu_initialized_mask);
>>   	smp_mb();
>>   
>> +	/* With Intel TXT, the AP startup is totally different */
>> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==
> 
> nit: spaces around '|'
> 
>> +	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {
>> +		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
>> +		goto txt_wake;
>> +	}


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 12/14] x86: Secure Launch late initcall platform module
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-05 19:42     ` Simon Horman
  -1 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 19:42 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:21PM +0000, Ross Philipson wrote:
> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
> 
> The Secure Launch platform module is a late init module. During the
> init call, the TPM event log is read and measurements taken in the
> early boot stub code are located. These measurements are extended
> into the TPM PCRs using the mainline TPM kernel driver.
> 
> The platform module also registers the securityfs nodes to allow
> access to TXT register fields on Intel along with the fetching of
> and writing events to the late launch TPM log.
> 
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>

Hi Ross,

a few more items from my side.

...

> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c

...

> +/*
> + * Securityfs exposure
> + */
> +struct memfile {
> +	char *name;
> +	void *addr;
> +	size_t size;
> +};
> +
> +static struct memfile sl_evtlog = {"eventlog", 0, 0};

I don't think the 0 fields are necessary above, memset will zero
any fields not explicitly set. But if you want to go that way, then
I think the first one should be NULL, as the addr field is a pointer.

> +static void *txt_heap;
> +static struct txt_heap_event_log_pointer2_1_element __iomem *evtlog20;
> +static DEFINE_MUTEX(sl_evt_log_mutex);

> +static ssize_t sl_evtlog_read(struct file *file, char __user *buf,
> +			      size_t count, loff_t *pos)
> +{
> +	ssize_t size;
> +
> +	if (!sl_evtlog.addr)
> +		return 0;
> +
> +	mutex_lock(&sl_evt_log_mutex);
> +	size = simple_read_from_buffer(buf, count, pos, sl_evtlog.addr,
> +				       sl_evtlog.size);
> +	mutex_unlock(&sl_evt_log_mutex);
> +
> +	return size;
> +}
> +
> +static ssize_t sl_evtlog_write(struct file *file, const char __user *buf,
> +				size_t datalen, loff_t *ppos)

nit: the line above doesn't align to the '(' on the line before that.

> +{
> +	ssize_t result;
> +	char *data;
> +
> +	if (!sl_evtlog.addr)
> +		return 0;
> +
> +	/* No partial writes. */
> +	result = -EINVAL;
> +	if (*ppos != 0)
> +		goto out;
> +
> +	data = memdup_user(buf, datalen);
> +	if (IS_ERR(data)) {
> +		result = PTR_ERR(data);
> +		goto out;
> +	}
> +
> +	mutex_lock(&sl_evt_log_mutex);
> +	if (evtlog20)
> +		result = tpm20_log_event(evtlog20, sl_evtlog.addr,
> +					 sl_evtlog.size, datalen, data);

Sparse says that the type of the first argument of tmp20_log_event is:

	struct txt_heap_event_log_pointer2_1_element *

However, the type of evtlog20 is:

	struct txt_heap_event_log_pointer2_1_element __iomem *

> +	else
> +		result = tpm12_log_event(sl_evtlog.addr, sl_evtlog.size,
> +					 datalen, data);
> +	mutex_unlock(&sl_evt_log_mutex);
> +
> +	kfree(data);
> +out:
> +	return result;
> +}

...

> +static long slaunch_expose_securityfs(void)
> +{
> +	long ret = 0;
> +	int i;
> +
> +	slaunch_dir = securityfs_create_dir("slaunch", NULL);
> +	if (IS_ERR(slaunch_dir))
> +		return PTR_ERR(slaunch_dir);
> +
> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> +		txt_dir = securityfs_create_dir("txt", slaunch_dir);
> +		if (IS_ERR(txt_dir)) {
> +			ret = PTR_ERR(txt_dir);
> +			goto remove_slaunch;
> +		}
> +
> +		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++) {
> +			txt_entries[i] = securityfs_create_file(
> +						sl_txt_files[i].name, 0440,
> +						txt_dir, NULL,
> +						sl_txt_files[i].fops);
> +			if (IS_ERR(txt_entries[i])) {
> +				ret = PTR_ERR(txt_entries[i]);
> +				goto remove_files;
> +			}
> +		}
> +

nit: no blank line here.

> +	}
> +
> +	if (sl_evtlog.addr > 0) {

addr is a pointer. So perhaps:

	if (sl_evtlog.addr) {

> +		event_file = securityfs_create_file(
> +					sl_evtlog.name, 0440,
> +					slaunch_dir, NULL,
> +					&sl_evtlog_ops);
> +		if (IS_ERR(event_file)) {
> +			ret = PTR_ERR(event_file);
> +			goto remove_files;
> +		}
> +	}
> +
> +	return 0;
> +
> +remove_files:
> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> +		while (--i >= 0)
> +			securityfs_remove(txt_entries[i]);
> +		securityfs_remove(txt_dir);
> +	}
> +remove_slaunch:
> +	securityfs_remove(slaunch_dir);
> +
> +	return ret;
> +}

...

> +static void slaunch_intel_evtlog(void __iomem *txt)
> +{
> +	struct slr_entry_log_info *log_info;
> +	struct txt_os_mle_data *params;
> +	struct slr_table *slrt;
> +	void *os_sinit_data;
> +	u64 base, size;
> +
> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
> +
> +	/* now map TXT heap */
> +	txt_heap = memremap(base, size, MEMREMAP_WB);
> +	if (!txt_heap)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap TXT heap\n",
> +			SL_ERROR_HEAP_MAP);

nit: These lines are not aligned to the opening '('

> +
> +	params = (struct txt_os_mle_data *)txt_os_mle_data_start(txt_heap);
> +
> +	/* Get the SLRT and remap it */
> +	slrt = memremap(params->slrt, sizeof(*slrt), MEMREMAP_WB);
> +	if (!slrt)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap SLR Table\n",
> +			SL_ERROR_SLRT_MAP);
> +	size = slrt->size;
> +	memunmap(slrt);
> +
> +	slrt = memremap(params->slrt, size, MEMREMAP_WB);
> +	if (!slrt)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap SLR Table\n",
> +			SL_ERROR_SLRT_MAP);
> +
> +	log_info = (struct slr_entry_log_info *)
> +			slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
> +	if (!log_info)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap SLR Table\n",
> +			SL_ERROR_SLRT_MISSING_ENTRY);
> +
> +	sl_evtlog.size = log_info->size;
> +	sl_evtlog.addr = memremap(log_info->addr, log_info->size,
> +				  MEMREMAP_WB);
> +	if (!sl_evtlog.addr)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap TPM event log\n",
> +			SL_ERROR_EVENTLOG_MAP);
> +
> +	memunmap(slrt);
> +
> +	/* Determine if this is TPM 1.2 or 2.0 event log */
> +	if (memcmp(sl_evtlog.addr + sizeof(struct tcg_pcr_event),
> +		    TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
> +		return; /* looks like it is not 2.0 */
> +
> +	/* For TPM 2.0 logs, the extended heap element must be located */
> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
> +

The return type of tmp20_find_lot2_1_element() is:

	struct txt_heap_event_log_pointer2_1_element *

However, the type of evtlog20 is:

	struct txt_heap_event_log_pointer2_1_element __iomem *

> +	evtlog20 = tpm20_find_log2_1_element(os_sinit_data);
> +
> +	/*
> +	 * If this fails, things are in really bad shape. Any attempt to write
> +	 * events to the log will fail.
> +	 */
> +	if (!evtlog20)
> +		slaunch_txt_reset(txt,
> +			"Error failed to find TPM20 event log element\n",
> +			SL_ERROR_TPM_INVALID_LOG20);
> +}
> +
> +static void slaunch_tpm20_extend_event(struct tpm_chip *tpm, void __iomem *txt,
> +				       struct tcg_pcr_event2_head *event)
> +{
> +	u16 *alg_id_field = (u16 *)((u8 *)event +
> +				    sizeof(struct tcg_pcr_event2_head));
> +	struct tpm_digest *digests;
> +	u8 *dptr;
> +	int ret;
> +	u32 i, j;
> +
> +	digests = kcalloc(tpm->nr_allocated_banks, sizeof(*digests),
> +			  GFP_KERNEL);
> +	if (!digests)
> +		slaunch_txt_reset(txt,
> +			"Failed to allocate array of digests\n",
> +			SL_ERROR_GENERIC);
> +
> +	for (i = 0; i < tpm->nr_allocated_banks; i++)
> +		digests[i].alg_id = tpm->allocated_banks[i].alg_id;
> +
> +

nit: one blank line is enough.

> +	/* Early SL code ensured there was a max count of 2 digests */
> +	for (i = 0; i < event->count; i++) {
> +		dptr = (u8 *)alg_id_field + sizeof(u16);
> +
> +		for (j = 0; j < tpm->nr_allocated_banks; j++) {
> +			if (digests[j].alg_id != *alg_id_field)
> +				continue;
> +
> +			switch (digests[j].alg_id) {
> +			case TPM_ALG_SHA256:
> +				memcpy(&digests[j].digest[0], dptr,
> +				       SHA256_DIGEST_SIZE);
> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
> +					SHA256_DIGEST_SIZE + sizeof(u16));
> +				break;
> +			case TPM_ALG_SHA1:
> +				memcpy(&digests[j].digest[0], dptr,
> +				       SHA1_DIGEST_SIZE);
> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
> +					SHA1_DIGEST_SIZE + sizeof(u16));
> +			default:
> +				break;
> +			}
> +		}
> +	}
> +
> +	ret = tpm_pcr_extend(tpm, event->pcr_idx, digests);
> +	if (ret) {
> +		pr_err("Error extending TPM20 PCR, result: %d\n", ret);
> +		slaunch_txt_reset(txt,
> +			"Failed to extend TPM20 PCR\n",
> +			SL_ERROR_TPM_EXTEND);
> +	}
> +
> +	kfree(digests);
> +}
> +
> +static void slaunch_tpm20_extend(struct tpm_chip *tpm, void __iomem *txt)
> +{
> +	struct tcg_pcr_event *event_header;
> +	struct tcg_pcr_event2_head *event;
> +	int start = 0, end = 0, size;
> +
> +	event_header = (struct tcg_pcr_event *)(sl_evtlog.addr +
> +						evtlog20->first_record_offset);

Sparse says that evtlog20 shouldn't be dereferenced because it
has a __iomem attribute.

> +
> +	/* Skip first TPM 1.2 event to get to first TPM 2.0 event */
> +	event = (struct tcg_pcr_event2_head *)((u8 *)event_header +
> +						sizeof(struct tcg_pcr_event) +
> +						event_header->event_size);
> +
> +	while ((void  *)event < sl_evtlog.addr + evtlog20->next_record_offset) {

Ditto.

> +		size = __calc_tpm2_event_size(event, event_header, false);
> +		if (!size)
> +			slaunch_txt_reset(txt,
> +				"TPM20 invalid event in event log\n",
> +				SL_ERROR_TPM_INVALID_EVENT);
> +
> +		/*
> +		 * Marker events indicate where the Secure Launch early stub
> +		 * started and ended adding post launch events.
> +		 */
> +		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
> +			end = 1;
> +			break;
> +		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
> +			start = 1;
> +			goto next;
> +		}
> +
> +		if (start)
> +			slaunch_tpm20_extend_event(tpm, txt, event);
> +
> +next:
> +		event = (struct tcg_pcr_event2_head *)((u8 *)event + size);
> +	}
> +
> +	if (!start || !end)
> +		slaunch_txt_reset(txt,
> +			"Missing start or end events for extending TPM20 PCRs\n",
> +			SL_ERROR_TPM_EXTEND);
> +}

...

> +static void slaunch_pcr_extend(void __iomem *txt)
> +{
> +	struct tpm_chip *tpm;
> +
> +	tpm = tpm_default_chip();
> +	if (!tpm)
> +		slaunch_txt_reset(txt,
> +			"Could not get default TPM chip\n",
> +			SL_ERROR_TPM_INIT);
> +	if (evtlog20)
> +		slaunch_tpm20_extend(tpm, txt);
> +	else
> +		slaunch_tpm12_extend(tpm, txt);
> +}
> +
> +static int __init slaunch_module_init(void)
> +{
> +	void __iomem *txt;
> +
> +	/* Check to see if Secure Launch happened */
> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
> +	    (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT))

nit: spaces around '|'
     Likewise elsewhere in this patch.


> +		return 0;
> +
> +	txt = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
> +		      PAGE_SIZE);
> +	if (!txt)
> +		panic("Error ioremap of TXT priv registers\n");
> +
> +	/* Only Intel TXT is supported at this point */
> +	slaunch_intel_evtlog(txt);
> +
> +	slaunch_pcr_extend(txt);
> +
> +	iounmap(txt);
> +
> +	return slaunch_expose_securityfs();
> +}

...

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

* Re: [PATCH v6 12/14] x86: Secure Launch late initcall platform module
@ 2023-05-05 19:42     ` Simon Horman
  0 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 19:42 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:21PM +0000, Ross Philipson wrote:
> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
> 
> The Secure Launch platform module is a late init module. During the
> init call, the TPM event log is read and measurements taken in the
> early boot stub code are located. These measurements are extended
> into the TPM PCRs using the mainline TPM kernel driver.
> 
> The platform module also registers the securityfs nodes to allow
> access to TXT register fields on Intel along with the fetching of
> and writing events to the late launch TPM log.
> 
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>

Hi Ross,

a few more items from my side.

...

> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c

...

> +/*
> + * Securityfs exposure
> + */
> +struct memfile {
> +	char *name;
> +	void *addr;
> +	size_t size;
> +};
> +
> +static struct memfile sl_evtlog = {"eventlog", 0, 0};

I don't think the 0 fields are necessary above, memset will zero
any fields not explicitly set. But if you want to go that way, then
I think the first one should be NULL, as the addr field is a pointer.

> +static void *txt_heap;
> +static struct txt_heap_event_log_pointer2_1_element __iomem *evtlog20;
> +static DEFINE_MUTEX(sl_evt_log_mutex);

> +static ssize_t sl_evtlog_read(struct file *file, char __user *buf,
> +			      size_t count, loff_t *pos)
> +{
> +	ssize_t size;
> +
> +	if (!sl_evtlog.addr)
> +		return 0;
> +
> +	mutex_lock(&sl_evt_log_mutex);
> +	size = simple_read_from_buffer(buf, count, pos, sl_evtlog.addr,
> +				       sl_evtlog.size);
> +	mutex_unlock(&sl_evt_log_mutex);
> +
> +	return size;
> +}
> +
> +static ssize_t sl_evtlog_write(struct file *file, const char __user *buf,
> +				size_t datalen, loff_t *ppos)

nit: the line above doesn't align to the '(' on the line before that.

> +{
> +	ssize_t result;
> +	char *data;
> +
> +	if (!sl_evtlog.addr)
> +		return 0;
> +
> +	/* No partial writes. */
> +	result = -EINVAL;
> +	if (*ppos != 0)
> +		goto out;
> +
> +	data = memdup_user(buf, datalen);
> +	if (IS_ERR(data)) {
> +		result = PTR_ERR(data);
> +		goto out;
> +	}
> +
> +	mutex_lock(&sl_evt_log_mutex);
> +	if (evtlog20)
> +		result = tpm20_log_event(evtlog20, sl_evtlog.addr,
> +					 sl_evtlog.size, datalen, data);

Sparse says that the type of the first argument of tmp20_log_event is:

	struct txt_heap_event_log_pointer2_1_element *

However, the type of evtlog20 is:

	struct txt_heap_event_log_pointer2_1_element __iomem *

> +	else
> +		result = tpm12_log_event(sl_evtlog.addr, sl_evtlog.size,
> +					 datalen, data);
> +	mutex_unlock(&sl_evt_log_mutex);
> +
> +	kfree(data);
> +out:
> +	return result;
> +}

...

> +static long slaunch_expose_securityfs(void)
> +{
> +	long ret = 0;
> +	int i;
> +
> +	slaunch_dir = securityfs_create_dir("slaunch", NULL);
> +	if (IS_ERR(slaunch_dir))
> +		return PTR_ERR(slaunch_dir);
> +
> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> +		txt_dir = securityfs_create_dir("txt", slaunch_dir);
> +		if (IS_ERR(txt_dir)) {
> +			ret = PTR_ERR(txt_dir);
> +			goto remove_slaunch;
> +		}
> +
> +		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++) {
> +			txt_entries[i] = securityfs_create_file(
> +						sl_txt_files[i].name, 0440,
> +						txt_dir, NULL,
> +						sl_txt_files[i].fops);
> +			if (IS_ERR(txt_entries[i])) {
> +				ret = PTR_ERR(txt_entries[i]);
> +				goto remove_files;
> +			}
> +		}
> +

nit: no blank line here.

> +	}
> +
> +	if (sl_evtlog.addr > 0) {

addr is a pointer. So perhaps:

	if (sl_evtlog.addr) {

> +		event_file = securityfs_create_file(
> +					sl_evtlog.name, 0440,
> +					slaunch_dir, NULL,
> +					&sl_evtlog_ops);
> +		if (IS_ERR(event_file)) {
> +			ret = PTR_ERR(event_file);
> +			goto remove_files;
> +		}
> +	}
> +
> +	return 0;
> +
> +remove_files:
> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> +		while (--i >= 0)
> +			securityfs_remove(txt_entries[i]);
> +		securityfs_remove(txt_dir);
> +	}
> +remove_slaunch:
> +	securityfs_remove(slaunch_dir);
> +
> +	return ret;
> +}

...

> +static void slaunch_intel_evtlog(void __iomem *txt)
> +{
> +	struct slr_entry_log_info *log_info;
> +	struct txt_os_mle_data *params;
> +	struct slr_table *slrt;
> +	void *os_sinit_data;
> +	u64 base, size;
> +
> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
> +
> +	/* now map TXT heap */
> +	txt_heap = memremap(base, size, MEMREMAP_WB);
> +	if (!txt_heap)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap TXT heap\n",
> +			SL_ERROR_HEAP_MAP);

nit: These lines are not aligned to the opening '('

> +
> +	params = (struct txt_os_mle_data *)txt_os_mle_data_start(txt_heap);
> +
> +	/* Get the SLRT and remap it */
> +	slrt = memremap(params->slrt, sizeof(*slrt), MEMREMAP_WB);
> +	if (!slrt)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap SLR Table\n",
> +			SL_ERROR_SLRT_MAP);
> +	size = slrt->size;
> +	memunmap(slrt);
> +
> +	slrt = memremap(params->slrt, size, MEMREMAP_WB);
> +	if (!slrt)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap SLR Table\n",
> +			SL_ERROR_SLRT_MAP);
> +
> +	log_info = (struct slr_entry_log_info *)
> +			slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
> +	if (!log_info)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap SLR Table\n",
> +			SL_ERROR_SLRT_MISSING_ENTRY);
> +
> +	sl_evtlog.size = log_info->size;
> +	sl_evtlog.addr = memremap(log_info->addr, log_info->size,
> +				  MEMREMAP_WB);
> +	if (!sl_evtlog.addr)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap TPM event log\n",
> +			SL_ERROR_EVENTLOG_MAP);
> +
> +	memunmap(slrt);
> +
> +	/* Determine if this is TPM 1.2 or 2.0 event log */
> +	if (memcmp(sl_evtlog.addr + sizeof(struct tcg_pcr_event),
> +		    TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
> +		return; /* looks like it is not 2.0 */
> +
> +	/* For TPM 2.0 logs, the extended heap element must be located */
> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
> +

The return type of tmp20_find_lot2_1_element() is:

	struct txt_heap_event_log_pointer2_1_element *

However, the type of evtlog20 is:

	struct txt_heap_event_log_pointer2_1_element __iomem *

> +	evtlog20 = tpm20_find_log2_1_element(os_sinit_data);
> +
> +	/*
> +	 * If this fails, things are in really bad shape. Any attempt to write
> +	 * events to the log will fail.
> +	 */
> +	if (!evtlog20)
> +		slaunch_txt_reset(txt,
> +			"Error failed to find TPM20 event log element\n",
> +			SL_ERROR_TPM_INVALID_LOG20);
> +}
> +
> +static void slaunch_tpm20_extend_event(struct tpm_chip *tpm, void __iomem *txt,
> +				       struct tcg_pcr_event2_head *event)
> +{
> +	u16 *alg_id_field = (u16 *)((u8 *)event +
> +				    sizeof(struct tcg_pcr_event2_head));
> +	struct tpm_digest *digests;
> +	u8 *dptr;
> +	int ret;
> +	u32 i, j;
> +
> +	digests = kcalloc(tpm->nr_allocated_banks, sizeof(*digests),
> +			  GFP_KERNEL);
> +	if (!digests)
> +		slaunch_txt_reset(txt,
> +			"Failed to allocate array of digests\n",
> +			SL_ERROR_GENERIC);
> +
> +	for (i = 0; i < tpm->nr_allocated_banks; i++)
> +		digests[i].alg_id = tpm->allocated_banks[i].alg_id;
> +
> +

nit: one blank line is enough.

> +	/* Early SL code ensured there was a max count of 2 digests */
> +	for (i = 0; i < event->count; i++) {
> +		dptr = (u8 *)alg_id_field + sizeof(u16);
> +
> +		for (j = 0; j < tpm->nr_allocated_banks; j++) {
> +			if (digests[j].alg_id != *alg_id_field)
> +				continue;
> +
> +			switch (digests[j].alg_id) {
> +			case TPM_ALG_SHA256:
> +				memcpy(&digests[j].digest[0], dptr,
> +				       SHA256_DIGEST_SIZE);
> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
> +					SHA256_DIGEST_SIZE + sizeof(u16));
> +				break;
> +			case TPM_ALG_SHA1:
> +				memcpy(&digests[j].digest[0], dptr,
> +				       SHA1_DIGEST_SIZE);
> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
> +					SHA1_DIGEST_SIZE + sizeof(u16));
> +			default:
> +				break;
> +			}
> +		}
> +	}
> +
> +	ret = tpm_pcr_extend(tpm, event->pcr_idx, digests);
> +	if (ret) {
> +		pr_err("Error extending TPM20 PCR, result: %d\n", ret);
> +		slaunch_txt_reset(txt,
> +			"Failed to extend TPM20 PCR\n",
> +			SL_ERROR_TPM_EXTEND);
> +	}
> +
> +	kfree(digests);
> +}
> +
> +static void slaunch_tpm20_extend(struct tpm_chip *tpm, void __iomem *txt)
> +{
> +	struct tcg_pcr_event *event_header;
> +	struct tcg_pcr_event2_head *event;
> +	int start = 0, end = 0, size;
> +
> +	event_header = (struct tcg_pcr_event *)(sl_evtlog.addr +
> +						evtlog20->first_record_offset);

Sparse says that evtlog20 shouldn't be dereferenced because it
has a __iomem attribute.

> +
> +	/* Skip first TPM 1.2 event to get to first TPM 2.0 event */
> +	event = (struct tcg_pcr_event2_head *)((u8 *)event_header +
> +						sizeof(struct tcg_pcr_event) +
> +						event_header->event_size);
> +
> +	while ((void  *)event < sl_evtlog.addr + evtlog20->next_record_offset) {

Ditto.

> +		size = __calc_tpm2_event_size(event, event_header, false);
> +		if (!size)
> +			slaunch_txt_reset(txt,
> +				"TPM20 invalid event in event log\n",
> +				SL_ERROR_TPM_INVALID_EVENT);
> +
> +		/*
> +		 * Marker events indicate where the Secure Launch early stub
> +		 * started and ended adding post launch events.
> +		 */
> +		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
> +			end = 1;
> +			break;
> +		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
> +			start = 1;
> +			goto next;
> +		}
> +
> +		if (start)
> +			slaunch_tpm20_extend_event(tpm, txt, event);
> +
> +next:
> +		event = (struct tcg_pcr_event2_head *)((u8 *)event + size);
> +	}
> +
> +	if (!start || !end)
> +		slaunch_txt_reset(txt,
> +			"Missing start or end events for extending TPM20 PCRs\n",
> +			SL_ERROR_TPM_EXTEND);
> +}

...

> +static void slaunch_pcr_extend(void __iomem *txt)
> +{
> +	struct tpm_chip *tpm;
> +
> +	tpm = tpm_default_chip();
> +	if (!tpm)
> +		slaunch_txt_reset(txt,
> +			"Could not get default TPM chip\n",
> +			SL_ERROR_TPM_INIT);
> +	if (evtlog20)
> +		slaunch_tpm20_extend(tpm, txt);
> +	else
> +		slaunch_tpm12_extend(tpm, txt);
> +}
> +
> +static int __init slaunch_module_init(void)
> +{
> +	void __iomem *txt;
> +
> +	/* Check to see if Secure Launch happened */
> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
> +	    (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT))

nit: spaces around '|'
     Likewise elsewhere in this patch.


> +		return 0;
> +
> +	txt = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
> +		      PAGE_SIZE);
> +	if (!txt)
> +		panic("Error ioremap of TXT priv registers\n");
> +
> +	/* Only Intel TXT is supported at this point */
> +	slaunch_intel_evtlog(txt);
> +
> +	slaunch_pcr_extend(txt);
> +
> +	iounmap(txt);
> +
> +	return slaunch_expose_securityfs();
> +}

...

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-05 18:58       ` Ross Philipson
@ 2023-05-05 19:46         ` Simon Horman
  -1 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 19:46 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, May 05, 2023 at 02:58:28PM -0400, Ross Philipson wrote:
> On 5/5/23 13:47, Simon Horman wrote:
> > On Thu, May 04, 2023 at 02:50:16PM +0000, Ross Philipson wrote:

...

> > > +asmlinkage __visible void sl_check_region(void *base, u32 size)
> > > +{
> > > +	sl_check_pmr_coverage(base, size, false);
> > > +}
> > 
> > I'm a nit unsure, what to do here, but clang-16 with W=1 says the following.
> > 
> > arch/x86/boot/compressed/sl_main.c:533:27: warning: no previous prototype for function 'sl_main' [-Wmissing-prototypes]
> > asmlinkage __visible void sl_main(void *bootparams)
> >                            ^
> > arch/x86/boot/compressed/sl_main.c:533:22: note: declare 'static' if the function is not intended to be used outside of this translation unit
> > asmlinkage __visible void sl_main(void *bootparams)
> >                       ^
> >                       static
> 
> Yea we will have to look into why this is. This function is only ever called
> from asm code so that might have something to do with this.

Thanks.

...

> > > diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
> > > index 01d19fc..74e3e7df 100644
> > > --- a/arch/x86/include/uapi/asm/bootparam.h
> > > +++ b/arch/x86/include/uapi/asm/bootparam.h
> > > @@ -26,6 +26,7 @@
> > >   /* loadflags */
> > >   #define LOADED_HIGH	(1<<0)
> > >   #define KASLR_FLAG	(1<<1)
> > > +#define SLAUNCH_FLAG	(1<<2)
> > >   #define QUIET_FLAG	(1<<5)
> > >   #define KEEP_SEGMENTS	(1<<6)
> > >   #define CAN_USE_HEAP	(1<<7)
> > 
> > nit: please consider using BIT()
> 
> I am a little reluctant to change something like this in an existing header.
> It seems a bit out of scope for the patch set.

Yes, sorry for the noise on this one.
I agree that what you have is the best approach here.

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-05-05 19:46         ` Simon Horman
  0 siblings, 0 replies; 200+ messages in thread
From: Simon Horman @ 2023-05-05 19:46 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, May 05, 2023 at 02:58:28PM -0400, Ross Philipson wrote:
> On 5/5/23 13:47, Simon Horman wrote:
> > On Thu, May 04, 2023 at 02:50:16PM +0000, Ross Philipson wrote:

...

> > > +asmlinkage __visible void sl_check_region(void *base, u32 size)
> > > +{
> > > +	sl_check_pmr_coverage(base, size, false);
> > > +}
> > 
> > I'm a nit unsure, what to do here, but clang-16 with W=1 says the following.
> > 
> > arch/x86/boot/compressed/sl_main.c:533:27: warning: no previous prototype for function 'sl_main' [-Wmissing-prototypes]
> > asmlinkage __visible void sl_main(void *bootparams)
> >                            ^
> > arch/x86/boot/compressed/sl_main.c:533:22: note: declare 'static' if the function is not intended to be used outside of this translation unit
> > asmlinkage __visible void sl_main(void *bootparams)
> >                       ^
> >                       static
> 
> Yea we will have to look into why this is. This function is only ever called
> from asm code so that might have something to do with this.

Thanks.

...

> > > diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
> > > index 01d19fc..74e3e7df 100644
> > > --- a/arch/x86/include/uapi/asm/bootparam.h
> > > +++ b/arch/x86/include/uapi/asm/bootparam.h
> > > @@ -26,6 +26,7 @@
> > >   /* loadflags */
> > >   #define LOADED_HIGH	(1<<0)
> > >   #define KASLR_FLAG	(1<<1)
> > > +#define SLAUNCH_FLAG	(1<<2)
> > >   #define QUIET_FLAG	(1<<5)
> > >   #define KEEP_SEGMENTS	(1<<6)
> > >   #define CAN_USE_HEAP	(1<<7)
> > 
> > nit: please consider using BIT()
> 
> I am a little reluctant to change something like this in an existing header.
> It seems a bit out of scope for the patch set.

Yes, sorry for the noise on this one.
I agree that what you have is the best approach here.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 00/14] x86: Trenchboot secure dynamic launch Linux kernel support
  2023-05-05 15:45     ` Ross Philipson
@ 2023-05-06  7:56       ` Bagas Sanjaya
  -1 siblings, 0 replies; 200+ messages in thread
From: Bagas Sanjaya @ 2023-05-06  7:56 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On 5/5/23 22:45, Ross Philipson wrote:
> Sorry about that. In the future I will include a base-commit field. It is based off of torvolds/master as of 5/1/2023. The branch where the patches came from is now pushed to the TrenchBoot repository here:
> 
> https://github.com/TrenchBoot/linux/tree/linux-sl-master-5-1-23-v6
> 

Pulled, thanks!

-- 
An old man doll... just what I always wanted! - Clara


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

* Re: [PATCH v6 00/14] x86: Trenchboot secure dynamic launch Linux kernel support
@ 2023-05-06  7:56       ` Bagas Sanjaya
  0 siblings, 0 replies; 200+ messages in thread
From: Bagas Sanjaya @ 2023-05-06  7:56 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On 5/5/23 22:45, Ross Philipson wrote:
> Sorry about that. In the future I will include a base-commit field. It is based off of torvolds/master as of 5/1/2023. The branch where the patches came from is now pushed to the TrenchBoot repository here:
> 
> https://github.com/TrenchBoot/linux/tree/linux-sl-master-5-1-23-v6
> 

Pulled, thanks!

-- 
An old man doll... just what I always wanted! - Clara


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-06  8:48     ` Bagas Sanjaya
  -1 siblings, 0 replies; 200+ messages in thread
From: Bagas Sanjaya @ 2023-05-06  8:48 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

[-- Attachment #1: Type: text/plain, Size: 51233 bytes --]

On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
> +=====================================
> +System Launch Integrity documentation
> +=====================================
> +
> +.. toctree::

By convention, doc toctree have 2-level depth (only page title and
first-level headings are visible). You may consider adding
`:maxdepth: 2` option.

> diff --git a/Documentation/security/launch-integrity/principles.rst b/Documentation/security/launch-integrity/principles.rst
> new file mode 100644
> index 0000000..73cf063
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/principles.rst
> @@ -0,0 +1,313 @@
> +=======================
> +System Launch Integrity
> +=======================
> +
> +This document serves to establish a common understanding of what is system
> +launch, the integrity concern for system launch, and why using a Root of Trust
> +(RoT) from a Dynamic Launch may be desired. Through out this document
> +terminology from the Trusted Computing Group (TCG) and National Institue for
> +Science and Technology (NIST) is used to ensure a vendor nutrual language is
> +used to describe and reference security-related concepts.
> +
> +System Launch
> +=============
> +
> +There is a tendency to only consider the classical power-on boot as the only
> +means to launch an Operating System (OS) on a computer system, but in fact most
> +modern processors support two methods to launch the system. To provide clarity a
> +common definition of a system launch should be established. This definition is
> +that a during a single power life cycle of a system, a System Launch consists
> +of an initialization event, typically in hardware, that is followed by an
> +executing software payload that takes the system from the initialized state to
> +a running state. Driven by the Trusted Computing Group (TCG) architecture,
> +modern processors are able to support two methods to launch a system, these two
> +types of system launch are known as Static Launch and Dynamic Launch.
> +
> +Static Launch
> +-------------
> +
> +Static launch is the system launch associated with the power cycle of the CPU.
> +Thus static launch refers to the classical power-on boot where the
> +initialization event is the release of the CPU from reset and the system
> +firmware is the software payload that brings the system up to a running state.
> +Since static launch is the system launch associated with the beginning of the
> +power lifecycle of a system, it is therefore a fixed, one-time system launch.
> +It is because of this that static launch is referred to and thought of as being
> +"static".
> +
> +Dynamic Launch
> +--------------
> +
> +Modern CPUs architectures provides a mechanism to re-initialize the system to a
> +"known good" state without requiring a power event. This re-initialization
> +event is the event for a dynamic launch and is referred to as the Dynamic
> +Launch Event (DLE). The DLE functions by accepting a software payload, referred
> +to as the Dynamic Configuration Environment (DCE), that execution is handed to
> +after the DLE is invoked. The DCE is responsible for bringing the system back
> +to a running state. Since the dynamic launch is not tied to a power event like
> +the static launch, this enables a dynamic launch to be initiated at any time
> +and multiple times during a single power life cycle. This dynamism is the
> +reasoning behind referring to this system launch as being dynamic.
> +
> +Because a dynamic launch can be conducted at any time during a single power
> +life cycle, they are classified into one of two types, an early launch or a
> +late launch.
> +
> +:Early Launch: When a dynamic launch is used as a transition from a static
> +   launch chain to the final Operating System.
> +
> +:Late Launch: The usage of a dynamic launch by an executing Operating System to
> +   transition to a “known good” state to perform one or more operations, e.g. to
> +   launch into a new Operating System.
> +
> +System Integrity
> +================
> +
> +A computer system can be considered a collection of mechanisms that work
> +together to produce a result. The assurance that the mechanisms are functioning
> +correctly and producing the expected result is the integrity of the system. To
> +ensure a system's integrity there are a subset of these mechanisms, commonly
> +referred to as security mechanisms, that are present to help ensure the system
> +produces the expected result or at least detect the potential of an unexpected
> +result may have happened. Since the security mechanisms are relied upon to
> +ensue the integrity of the system, these mechanisms are trusted. Upon
> +inspection these security mechanisms each have a set of properties and these
> +properties can be evaluated to determine how susceptible a mechanism might be
> +to failure. This assessment is referred to as the Strength of Mechanism and for
> +trusted mechanism enables for the trustworthiness of that mechanism to be
> +quantified.
> +
> +For software systems there are two system states for which the integrity is
> +critical, when the software is loaded into memory and when the software is
> +executing on the hardware. Ensuring that the expected software is load into
> +memory is referred to as load-time integrity while ensuring that the software
> +executing is the expected software is the runtime integrity of that software.
> +
> +Load-time Integrity
> +-------------------
> +
> +It is critical to understand what load-time integrity establishes about a
> +system and what is assumed, i.e. what is being trusted. Load-time integrity is
> +when a trusted entity, i.e. an entity with an assumed integrity, takes an
> +action to assess an entity being loaded into memory before it is used. A
> +variety of mechanisms may be used to conduct the assessment, each with
> +different properties. A particular property is whether the mechanism creates an
> +evidence of the assessment. Often either cryptographic signature checking or
> +hashing are the common assessment operations used.
> +
> +A signature checking assessment functions by requiring a representation of the
> +accepted authorities and uses those representations to assess if the entity has
> +been signed by an accepted authority. The benefit to this process is that
> +assessment process includes an adjudication of the assessment. The drawbacks
> +are that 1) the adjudication is susceptible to tampering by the Trusted
> +Computing Base (TCB), 2) there is no evidence to assert that an untampered
> +adjudication was completed, and 3) the system must be an active participant in
> +the key management infrastructure.
> +
> +A cryptographic hashing assessment does not adjudicate the assessment but
> +instead generates evidence of the assessment to be adjudicated independently.
> +The benefits to this approach is that the assessment may be simple such that it
> +is able to be implemented as an immutable mechanism, e.g. in hardware.
> +Additionally it is possible for the adjudication to be conducted where it
> +cannot be tampered with by the TCB. The drawback is that a compromised
> +environment will be allowed to execute until an adjudication can be completed.
> +
> +Ultimately load-time integrity provides confidence that the correct entity was
> +loaded and in the absence of a run-time integrity mechanism assumes, i.e
> +trusts, that the entity will never become corrupted.
> +
> +Runtime Integrity
> +-----------------
> +
> +Runtime integrity in the general sense is when a trusted entity makes an
> +assessment of an entity at any point in time during the assessed entity's
> +execution. A more concrete explanation is the taking of an integrity assessment
> +of an active process executing on the system at any point during the process'
> +execution. Often the load-time integrity of an operating system's user-space,
> +i.e. the operating environment, is confused to be the runtime integrity of the
> +system since it is an integrity assessment of the "runtime" software. The
> +reality is that actual runtime integrity is a very difficult problem and thus
> +not very many solutions are public and/or available. One example of a runtime
> +integrity solution would be John Hopkins Advanced Physics Labratory's (APL)
> +Linux Kernel Integrity Module (LKIM).
> +
> +Trust Chains
> +============
> +
> +Bulding upon the understanding of security mechanisms to establish load-time
> +integrity of an entity, it is possible to chain together load-time integrity
> +assessments to establish the integrity of the whole system. This process is
> +known as transitive trust and provides the concept of building a chain of
> +load-time integrity assessments, commonly referred to as a trust chain. These
> +assessments may be used to adjudicate the load-time integrity of the whole
> +system. This trust chain is started by a trusted entity that does the first
> +assessment. This first entity is referred to as the Root of Trust(RoT) with the
> +entities name being derived from the mechanism used for the assessment, i.e.
> +RoT for Verification (RTV) and RoT for Measurement (RTM).
> +
> +A trust chain is itself a mechanism, specifically a mechanism of mechanisms,
> +and therefore it too has a Strength of Mechanism. The factors that contribute
> +to a trust chain's strength are,
> +
> +  - The strength of the chain's RoT
> +  - The strength of each member of the trust chain
> +  - The length, i.e. the number of members, of the chain
> +
> +Therefore to provide the strongest trust chains, they should start with a
> +strong RoT and should consist of members being of low complexity and minimizing
> +the number of members participating as is possible. In a more colloquial sense,
> +a trust chain is only as strong as it weakests link and more links increase
> +the probability of a weak link.
> +
> +Dynamic Launch Components
> +=========================
> +
> +The TCG architecture for dynamic launch is composed of a component series that
> +are used to setup and then carry out the launch. These components work together
> +to construct a RTM trust chain that is rooted in the dynamic launch and thus
> +commonly referred to as the Dynamic Root of Trust for Measurement (DRTM) chain.
> +
> +What follows is a brief explanation of each component in execution order. A
> +subset of these components are what establishes the dynamic launch's trust
> +chain.
> +
> +Dynamic Configuration Environment Preamble
> +------------------------------------------
> +
> +The Dynamic Configuration Environment (DCE) Preamble is responsible for setting
> +up the system environment in preparation for a dynamic launch. The DCE Preamble
> +is not a part of the DRTM trust chain.
> +
> +Dynamic Launch Event
> +--------------------
> +
> +The dynamic launch event is the event, typically a CPU instruction, that triggers
> +the system's dynamic launch mechanism to begin the launch. The dynamic launch
> +mechanism is also the RoT for the DRTM trust chain.
> +
> +Dynamic Configuration Environment
> +---------------------------------
> +
> +The dynamic launch mechanism may have resulted in a reset of a portion of the
> +system. To bring the system back to an adequate state for system software the
> +dynamic launch will hand over control to the DCE. Prior to handing over this
> +control, the dynamic launch will measure the DCE. Once the DCE is complete it
> +will proceed to measure and then execute the Dynamic Launch Measured
> +Environment (DLME).
> +
> +Dynamic Launch Measured Environment
> +-----------------------------------
> +
> +The DLME is the first system kernel to have control of the system but may not
> +be the last. Depending on the usage and configuration, the DLME may be the
> +final/target operating system or it may be a boot loader that will load the
> +final/target operating system.
> +
> +Why DRTM
> +========
> +
> +It is a fact that DRTM increases the load-time integrity of the system by
> +providing a trust chain that has an immutable hardware RoT, uses a limited
> +number of small, special purpose code to establish the trust chain that starts
> +the target operating system. As mentioned in the Trust Chain section, these are
> +the main three factors in driving up the strength of a trust chain. As can been
> +seen by the BootHole exploit, which in fact did not effect the integrity of
> +DRTM solutions, the sophistication of attacks targeting system launch is at an
> +all time high. There is no reason a system should not employ every integrity
> +measure hardware makes available. This is the crux of a defense-in-depth
> +approach to system security. In the past the now closed SMI gap was often
> +pointed to as invalidating DRTM, which in fact was nothing but a strawman
> +argument. As has continued to be demonstrated, if/when SMM is corrupted it can
> +always circumvent all load-time integrity, SRTM and DRTM, because it is a
> +run-time integrity problem. Regardless, Intel and AMD have both deployed
> +runtime integrity for SMI and SMM which is tied directly to DRTM such that this
> +perceived deficiency is now non-existent and the world is moving forward with
> +an expectation that DRTM must be present.
> +
> +Glossary
> +========
> +
> +.. glossary::
> +  integrity
> +    Guarding against improper information modification or destruction, and
> +    includes ensuring information non-repudiation and authenticity.
> +
> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> +  mechanism
> +    A process or system that is used to produce a particular result.
> +
> +    - NIST Special Publication 800-160 (VOLUME 1 ) - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-160v1.pdf
> +
> +  risk
> +    A measure of the extent to which an entity is threatened by a potential
> +    circumstance or event, and typically a function of: (i) the adverse impacts
> +    that would arise if the circumstance or event occurs; and (ii) the
> +    likelihood of occurrence.
> +
> +    - NIST SP 800-30 Rev. 1 - https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-30r1.pdf
> +
> +  security mechanism
> +    A device or function designed to provide one or more security services
> +    usually rated in terms of strength of service and assurance of the design.
> +
> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> +  Strength of Mechanism
> +    A scale for measuring the relative strength of a security mechanism
> +
> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> +  transitive trust
> +    Also known as "Inductive Trust", in this process a Root of Trust gives a
> +    trustworthy description of a second group of functions. Based on this
> +    description, an interested entity can determine the trust it is to place in
> +    this second group of functions. If the interested entity determines that
> +    the trust level of the second group of functions is acceptable, the trust
> +    boundary is extended from the Root of Trust to include the second group of
> +    functions. In this case, the process can be iterated. The second group of
> +    functions can give a trustworthy description of the third group of
> +    functions, etc. Transitive trust is used to provide a trustworthy
> +    description of platform characteristics, and also to prove that
> +    non-migratable keys are non-migratable
> +
> +    - TCG Glossary - https://trustedcomputinggroup.org/wp-content/uploads/TCG-Glossary-V1.1-Rev-1.0.pdf
> +
> +  trust
> +    The confidence one element has in another that the second element will
> +    behave as expected`
> +
> +    - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
> +
> +  trust anchor
> +    An authoritative entity for which trust is assumed.
> +
> +    - NIST SP 800-57 Part 1 Rev. 5 - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf
> +
> +  trusted
> +    An element that another element relies upon to fulfill critical
> +    requirements on its behalf.
> +
> +    - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
> +
> +  trusted computing base (TCB)
> +    Totality of protection mechanisms within a computer system, including
> +    hardware, firmware, and software, the combination responsible for enforcing
> +    a security policy.
> +
> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> +  trusted computer system
> +    A system that has the necessary security functions and assurance that the
> +    security policy will be enforced and that can process a range of
> +    information sensitivities (i.e. classified, controlled unclassified
> +    information (CUI), or unclassified public information) simultaneously.
> +
> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> +  trustworthiness
> +    The attribute of a person or enterprise that provides confidence to others
> +    of the qualifications, capabilities, and reliability of that entity to
> +    perform specific tasks and fulfill assigned responsibilities.
> +
> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> diff --git a/Documentation/security/launch-integrity/secure_launch_details.rst b/Documentation/security/launch-integrity/secure_launch_details.rst
> new file mode 100644
> index 0000000..2e71543
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/secure_launch_details.rst
> @@ -0,0 +1,564 @@
> +===================================
> +Secure Launch Config and Interfaces
> +===================================
> +
> +Configuration
> +=============
> +
> +The settings to enable Secure Launch using Kconfig are under::
> +
> +  "Processor type and features" --> "Secure Launch support"
> +
> +A kernel with this option enabled can still be booted using other supported
> +methods.
> +
> +To reduce the Trusted Computing Base (TCB) of the MLE [1]_, the build
> +configuration should be pared down as narrowly as one's use case allows.
> +The fewer drivers (less active hardware) and features reduces the attack
> +surface. E.g. in the extreme, the MLE could only have local disk access
> +and no other hardware support. Or only network access for remote attestation.
> +
> +It is also desirable if possible to embed the initrd used with the MLE kernel
> +image to reduce complexity.
> +
> +The following are a few important configuration necessities to always consider:
> +
> +KASLR Configuration
> +-------------------
> +
> +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
> +built with KASLR disabled::
> +
> +  "Processor type and features" -->
> +      "Build a relocatable kernel" -->
> +          "Randomize the address of the kernel image (KASLR) [ ]"
> +
> +This unsets the Kconfig value CONFIG_RANDOMIZE_BASE.
> +
> +If not possible, KASLR must be disabled on the kernel command line when doing
> +a Secure Launch as follows::
> +
> +  nokaslr
> +
> +IOMMU Configuration
> +-------------------
> +
> +When doing a Secure Launch, the IOMMU should always be enabled and the drivers
> +loaded. However, IOMMU passthrough mode should never be used. This leaves the
> +MLE completely exposed to DMA after the PMR's [2]_ are disabled. The current default
> +mode is to use IOMMU in lazy translated mode but strict translated mode is the preferred
> +IOMMU mode and this should be selected in the build configuration::
> +
> +  "Device Drivers" -->
> +      "IOMMU Hardware Support" -->
> +          "IOMMU default domain type" -->
> +              "(X) Translated - Strict"
> +
> +In addition, the Intel IOMMU should be on by default. The following sets this as the
> +default in the build configuration::
> +
> +  "Device Drivers" -->
> +      "IOMMU Hardware Support" -->
> +          "Support for Intel IOMMU using DMA Remapping Devices [*]"
> +
> +and::
> +
> +  "Device Drivers" -->
> +      "IOMMU Hardware Support" -->
> +          "Support for Intel IOMMU using DMA Remapping Devices [*]" -->
> +              "Enable Intel DMA Remapping Devices by default  [*]"
> +
> +It is recommended that no other command line options should be set to override
> +the defaults above.
> +
> +Secure Launch Resource Table
> +============================
> +
> +The Secure Launch Resource Table (SLRT) is a platform-agnostic, standard format
> +for providing information for the pre-launch environment and to pass
> +information to the post-launch environment. The table is populated by one or
> +more bootloaders in the boot chain and used by Secure Launch on how to setup
> +the environment during post-launch. The details for the SLRT are documented
> +in the TrenchBoot Secure Launch Specifcation [3]_.
> +
> +Intel TXT Interface
> +===================
> +
> +The primary interfaces between the various components in TXT are the TXT MMIO
> +registers and the TXT heap. The MMIO register banks are described in Appendix B
> +of the TXT MLE [1]_ Development Guide.
> +
> +The TXT heap is described in Appendix C of the TXT MLE [1]_ Development
> +Guide. Most of the TXT heap is predefined in the specification. The heap is
> +initialized by firmware and the pre-launch environment and is subsequently used
> +by the SINIT ACM. One section, called the OS to MLE Data Table, is reserved for
> +software to define. This table is set up per the recommendation detailed in
> +Appendix B of the TrenchBoot Secure Launch Specification::
> +
> +        /*
> +         * Secure Launch defined OS/MLE TXT Heap table
> +         */
> +        struct txt_os_mle_data {
> +                u32 version;
> +                u32 boot_params_addr;
> +                struct slr_table *slrt;
> +                u64 txt_info;
> +                u32 ap_wake_block;
> +                u32 ap_wake_block_size;
> +                u8 mle_scratch[64];
> +        } __packed;
> +
> +Description of structure:
> +
> +=====================  ========================================================================
> +Field                  Use
> +=====================  ========================================================================
> +version                Structure version, current value 1
> +boot_params_addr       Physical base address of the Linux boot parameters
> +slrt                   Physical address of the Secure Launch Resource Table
> +txt_info               Pointer into the SLRT for easily locating TXT specific table
> +ap_wake_block          Physical address of the block of memory for parking APs after a launch
> +ap_wake_block_size     Size of the AP wake block
> +mle_scratch            Scratch area used post-launch by the MLE kernel. Fields:
> + 
> +                        - SL_SCRATCH_AP_EBX area to share %ebx base pointer among CPUs
> +                        - SL_SCRATCH_AP_JMP_OFFSET offset to abs. ljmp fixup location for APs
> +=====================  ========================================================================
> +
> +Error Codes
> +-----------
> +
> +The TXT specification defines the layout for TXT 32 bit error code values.
> +The bit encodings indicate where the error originated (e.g. with the CPU,
> +in the SINIT ACM, in software). The error is written to a sticky TXT
> +register that persists across resets called TXT.ERRORCODE (see the TXT
> +MLE Development Guide). The errors defined by the Secure Launch feature are
> +those generated in the MLE software. They have the format::
> +
> +  0xc0008XXX
> +
> +The low 12 bits are free for defining the following Secure Launch specific
> +error codes.
> +
> +======  ================
> +Name:   SL_ERROR_GENERIC
> +Value:  0xc0008001
> +======  ================
> +
> +Description:
> +
> +Generic catch all error. Currently unused.
> +
> +======  =================
> +Name:   SL_ERROR_TPM_INIT
> +Value:  0xc0008002
> +======  =================
> +
> +Description:
> +
> +The Secure Launch code failed to get an access to the TPM hardware interface.
> +This is most likely to due to misconfigured hardware or kernel. Ensure the
> +TPM chip is enabled and the kernel TPM support is built in (it should not be
> +built as a module).
> +
> +======  ==========================
> +Name:   SL_ERROR_TPM_INVALID_LOG20
> +Value:  0xc0008003
> +======  ==========================
> +
> +Description:
> +
> +The Secure Launch code failed to find a valid event log descriptor for TPM
> +version 2.0 or the event log descriptor is malformed. Usually this indicates
> +that incompatible versions of the pre-launch environment and the MLE kernel.
> +The pre-launch environment and the kernel share a structure in the TXT heap and
> +if this structure (the OS-MLE table) is mismatched, this error is often seen.
> +This TXT heap area is setup by the pre-launch environment so the issue may
> +originate there. It could be the sign of an attempted attack.
> +
> +======  ===========================
> +Name:   SL_ERROR_TPM_LOGGING_FAILED
> +Value:  0xc0008004
> +======  ===========================
> +
> +Description:
> +
> +There was a failed attempt to write a TPM event to the event log early in the
> +Secure Launch process. This is likely the result of a malformed TPM event log
> +buffer. Formatting of the event log buffer information is done by the
> +pre-launch environment so the issue most likely originates there.
> +
> +======  ============================
> +Name:   SL_ERROR_REGION_STRADDLE_4GB
> +Value:  0xc0008005
> +======  ============================
> +
> +Description:
> +
> +During early validation a buffer or region was found to straddle the 4GB
> +boundary. Because of the way TXT does DMA memory protection, this is an
> +unsafe configuration and is flagged as an error. This is most likely a
> +configuration issue in the pre-launch environment. It could also be the sign of
> +an attempted attack.
> +
> +======  ===================
> +Name:   SL_ERROR_TPM_EXTEND
> +Value:  0xc0008006
> +======  ===================
> +
> +Description:
> +
> +There was a failed attempt to extend a TPM PCR in the Secure Launch platform
> +module. This is most likely to due to misconfigured hardware or kernel. Ensure
> +the TPM chip is enabled and the kernel TPM support is built in (it should not
> +be built as a module).
> +
> +======  ======================
> +Name:   SL_ERROR_MTRR_INV_VCNT
> +Value:  0xc0008007
> +======  ======================
> +
> +Description:
> +
> +During early Secure Launch validation an invalid variable MTRR count was found.
> +The pre-launch environment passes a number of MSR values to the MLE to restore
> +including the MTRRs. The values are restored by the Secure Launch early entry
> +point code. After measuring the values supplied by the pre-launch environment,
> +a discrepancy was found validating the values. It could be the sign of an
> +attempted attack.
> +
> +======  ==========================
> +Name:   SL_ERROR_MTRR_INV_DEF_TYPE
> +Value:  0xc0008008
> +======  ==========================
> +
> +Description:
> +
> +During early Secure Launch validation an invalid default MTRR type was found.
> +See SL_ERROR_MTRR_INV_VCNT for more details.
> +
> +======  ======================
> +Name:   SL_ERROR_MTRR_INV_BASE
> +Value:  0xc0008009
> +======  ======================
> +
> +Description:
> +
> +During early Secure Launch validation an invalid variable MTRR base value was
> +found. See SL_ERROR_MTRR_INV_VCNT for more details.
> +
> +======  ======================
> +Name:   SL_ERROR_MTRR_INV_MASK
> +Value:  0xc000800a
> +======  ======================
> +
> +Description:
> +
> +During early Secure Launch validation an invalid variable MTRR mask value was
> +found. See SL_ERROR_MTRR_INV_VCNT for more details.
> +
> +======  ========================
> +Name:   SL_ERROR_MSR_INV_MISC_EN
> +Value:  0xc000800b
> +======  ========================
> +
> +Description:
> +
> +During early Secure Launch validation an invalid miscellaneous enable MSR value
> +was found. See SL_ERROR_MTRR_INV_VCNT for more details.
> +
> +======  =========================
> +Name:   SL_ERROR_INV_AP_INTERRUPT
> +Value:  0xc000800c
> +======  =========================
> +
> +Description:
> +
> +The application processors (APs) wait to be woken up by the SMP initialization
> +code. The only interrupt that they expect is an NMI; all other interrupts
> +should be masked. If an AP gets some other interrupt other than an NMI it will
> +cause this error. This error is very unlikely to occur.
> +
> +======  =========================
> +Name:   SL_ERROR_INTEGER_OVERFLOW
> +Value:  0xc000800d
> +======  =========================
> +
> +Description:
> +
> +A buffer base and size passed to the MLE caused an integer overflow when
> +added together. This is most likely a configuration issue in the pre-launch
> +environment. It could also be the sign of an attempted attack.
> +
> +======  ==================
> +Name:   SL_ERROR_HEAP_WALK
> +Value:  0xc000800e
> +======  ==================
> +
> +Description:
> +
> +An error occurred in TXT heap walking code. The underlying issue is a failure to
> +early_memremap() portions of the heap, most likely due to a resource shortage.
> +
> +======  =================
> +Name:   SL_ERROR_HEAP_MAP
> +Value:  0xc000800f
> +======  =================
> +
> +Description:
> +
> +This error is essentially the same as SL_ERROR_HEAP_WALK but occurred during the
> +actual early_memremap() operation.
> +
> +======  =========================
> +Name:   SL_ERROR_REGION_ABOVE_4GB
> +Value:  0xc0008010
> +======  =========================
> +
> +Description:
> +
> +A memory region used by the MLE is above 4GB. In general this is not a problem
> +because memory > 4Gb can be protected from DMA. There are certain buffers that
> +should never be above 4Gb though and one of these caused the violation. This is
> +most likely a configuration issue in the pre-launch environment. It could also
> +be the sign of an attempted attack.
> +
> +======  ==========================
> +Name:   SL_ERROR_HEAP_INVALID_DMAR
> +Value:  0xc0008011
> +======  ==========================
> +
> +Description:
> +
> +The backup copy of the ACPI DMAR table which is supposed to be located in the
> +TXT heap could not be found. This is due to a bug in the platform's ACM module
> +or in firmware.
> +
> +======  =======================
> +Name:   SL_ERROR_HEAP_DMAR_SIZE
> +Value:  0xc0008012
> +======  =======================
> +
> +Description:
> +
> +The backup copy of the ACPI DMAR table in the TXT heap is to large to be stored
> +for later usage. This error is very unlikely to occur since the area reserved
> +for the copy is far larger than the DMAR should be.
> +
> +======  ======================
> +Name:   SL_ERROR_HEAP_DMAR_MAP
> +Value:  0xc0008013
> +======  ======================
> +
> +Description:
> +
> +The backup copy of the ACPI DMAR table in the TXT heap could not be mapped. The
> +underlying issue is a failure to early_memremap() the DMAR table, most likely
> +due to a resource shortage.
> +
> +======  ====================
> +Name:   SL_ERROR_HI_PMR_BASE
> +Value:  0xc0008014
> +======  ====================
> +
> +Description:
> +
> +On a system with more than 4G of RAM, the high PMR [2]_ base address should be set
> +to 4G. This error is due to that not being the case. This PMR value is set by
> +the pre-launch environment so the issue most likely originates there. It could also
> +be the sign of an attempted attack.
> +
> +======  ====================
> +Name:   SL_ERROR_HI_PMR_SIZE
> +Value:  0xc0008015
> +======  ====================
> +
> +Description:
> +
> +On a system with more than 4G of RAM, the high PMR [2]_ size should be set to cover
> +all RAM > 4G. This error is due to that not being the case. This PMR value is
> +set by the pre-launch environment so the issue most likely originates there. It
> +could also be the sign of an attempted attack.
> +
> +======  ====================
> +Name:   SL_ERROR_LO_PMR_BASE
> +Value:  0xc0008016
> +======  ====================
> +
> +Description:
> +
> +The low PMR [2]_ base should always be set to address zero. This error is due to
> +that not being the case. This PMR value is set by the pre-launch environment
> +so the issue most likely originates there. It could also be the sign of an attempted
> +attack.
> +
> +======  ====================
> +Name:   SL_ERROR_LO_PMR_MLE
> +Value:  0xc0008017
> +======  ====================
> +
> +Description:
> +
> +This error indicates the MLE image is not covered by the low PMR [2]_ range. The
> +PMR values are set by the pre-launch environment so the issue most likely originates
> +there. It could also be the sign of an attempted attack.
> +
> +======  =======================
> +Name:   SL_ERROR_INITRD_TOO_BIG
> +Value:  0xc0008018
> +======  =======================
> +
> +Description:
> +
> +The external initrd provided is larger than 4Gb. This is not a valid
> +configuration for a Secure Launch due to managing DMA protection.
> +
> +======  =========================
> +Name:   SL_ERROR_HEAP_ZERO_OFFSET
> +Value:  0xc0008019
> +======  =========================
> +
> +Description:
> +
> +During a TXT heap walk an invalid/zero next table offset value was found. This
> +indicates the TXT heap is malformed. The TXT heap is initialized by the
> +pre-launch environment so the issue most likely originates there. It could also
> +be a sign of an attempted attack. In addition, ACM is also responsible for
> +manipulating parts of the TXT heap so the issue could be due to a bug in the
> +platform's ACM module.
> +
> +======  =============================
> +Name:   SL_ERROR_WAKE_BLOCK_TOO_SMALL
> +Value:  0xc000801a
> +======  =============================
> +
> +Description:
> +
> +The AP wake block buffer passed to the MLE via the OS-MLE TXT heap table is not
> +large enough. This value is set by the pre-launch environment so the issue most
> +likely originates there. It also could be the sign of an attempted attack.
> +
> +======  ===========================
> +Name:   SL_ERROR_MLE_BUFFER_OVERLAP
> +Value:  0xc000801b
> +======  ===========================
> +
> +Description:
> +
> +One of the buffers passed to the MLE via the OS-MLE TXT heap table overlaps
> +with the MLE image in memory. This value is set by the pre-launch environment
> +so the issue most likely originates there. It could also be the sign of an attempted
> +attack.
> +
> +======  ==========================
> +Name:   SL_ERROR_BUFFER_BEYOND_PMR
> +Value:  0xc000801c
> +======  ==========================
> +
> +Description:
> +
> +One of the buffers passed to the MLE via the OS-MLE TXT heap table is not
> +protected by a PMR. This value is set by the pre-launch environment so the
> +issue most likey  originates there. It could also be the sign of an attempted
> +attack.
> +
> +======  =============================
> +Name:   SL_ERROR_OS_SINIT_BAD_VERSION
> +Value:  0xc000801d
> +======  =============================
> +
> +Description:
> +
> +The version of the OS-SINIT TXT heap table is bad. It must be 6 or greater.
> +This value is set by the pre-launch environment so the issue most likely
> +originates there. It could also be the sign of an attempted attack. It is also
> +possible though very unlikely that the platform is so old that the ACM being
> +used requires an unsupported version.
> +
> +======  =====================
> +Name:   SL_ERROR_EVENTLOG_MAP
> +Value:  0xc000801e
> +======  =====================
> +
> +Description:
> +
> +An error occurred in the Secure Launch module while mapping the TPM event log.
> +The underlying issue is memremap() failure, most likely due to a resource
> +shortage.
> +
> +======  ========================
> +Name:   SL_ERROR_TPM_NUMBER_ALGS
> +Value:  0xc000801f
> +======  ========================
> +
> +Description:
> +
> +The TPM 2.0 event log reports an unsupported number of hashing algorithms.
> +Secure launch currently only supports a maximum of two: SHA1 and SHA256.
> +
> +======  ===========================
> +Name:   SL_ERROR_TPM_UNKNOWN_DIGEST
> +Value:  0xc0008020
> +======  ===========================
> +
> +Description:
> +
> +The TPM 2.0 event log reports an unsupported hashing algorithm. Secure launch
> +currently only supports two algorithms: SHA1 and SHA256.
> +
> +======  ==========================
> +Name:   SL_ERROR_TPM_INVALID_EVENT
> +Value:  0xc0008021
> +======  ==========================
> +
> +Description:
> +
> +An invalid/malformed event was found in the TPM event log while reading it.
> +Since only trusted entities are supposed to be writing the event log, this
> +would indicate either a bug or a possible attack.
> +
> +======  =====================
> +Name:   SL_ERROR_INVALID_SLRT
> +Value:  0xc0008022
> +======  =====================
> +
> +Description:
> +
> +The Secure Launch Resource Table is invalid or malformed and is unusable.
> +This implies the pre-launch code did not properly setup the SLRT.
> +
> +======  ===========================
> +Name:   SL_ERROR_SLRT_MISSING_ENTRY
> +Value:  0xc0008023
> +======  ===========================
> +
> +Description:
> +
> +The Secure Launch Resource Table is missing a required entry within it.
> +This implies the pre-launch code did not properly setup the SLRT.
> +
> +======  =================
> +Name:   SL_ERROR_SLRT_MAP
> +Value:  0xc0008024
> +======  =================
> +
> +Description:
> +
> +An error occurred in the Secure Launch module while mapping the Secure Launch
> +Resource table. The underlying issue is memremap() failure, most likely due to
> +a resource shortage.
> +
> +.. [1]
> +    MLE: Measured Launch Environment is the binary runtime that is measured and
> +    then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
> +    requirements for the MLE in detail.
> +
> +.. [2]
> +    PMR: Intel VTd has a feature in the IOMMU called Protected Memory Registers.
> +    There are two of these registers and they allow all DMA to be blocked
> +    to large areas of memory. The low PMR can cover all memory below 4Gb on 2Mb
> +    boundaries. The high PMR can cover all RAM on the system, again on 2Mb
> +    boundaries. This feature is used during a Secure Launch by TXT.
> +
> +.. [3]
> +    Secure Launch Specification: https://trenchboot.org/specifications/Secure_Launch/
> diff --git a/Documentation/security/launch-integrity/secure_launch_overview.rst b/Documentation/security/launch-integrity/secure_launch_overview.rst
> new file mode 100644
> index 0000000..ba91d73
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/secure_launch_overview.rst
> @@ -0,0 +1,220 @@
> +======================
> +Secure Launch Overview
> +======================
> +
> +Overview
> +========
> +
> +Prior to the start of the TrenchBoot project, the only active Open Source
> +project supporting dynamic launch was Intel's tboot project to support their
> +implementation of dynamic launch known as Intel Trusted eXecution Technology
> +(TXT). The approach taken by tboot was to provide an exokernel that could
> +handle the launch protocol implemented by Intel's special loader, the SINIT
> +Authenticated Code Module (ACM [2]_) and remained in memory to manage the SMX
> +CPU mode that a dynamic launch would put a system. While it is not precluded
> +from being used for doing a late launch, tboot's primary use case was to be
> +used as an early launch solution. As a result the TrenchBoot project started
> +the development of Secure Launch kernel feature to provide a more generalized
> +approach. The focus of the effort is twofold, the first is to make the Linux
> +kernel directly aware of the launch protocol used by Intel, AMD/Hygon, Arm, and
> +potentially OpenPOWER. The second is to make the Linux kernel be able to
> +initiate a dynamic launch. It is through this approach that the Secure Launch
> +kernel feature creates a basis for the Linux kernel to be used in a variety of
> +dynamic launch use cases.
> +
> +.. note::
> +    A quick note on terminology. The larger open source project itself is
> +    called TrenchBoot, which is hosted on GitHub (links below). The kernel
> +    feature enabling the use of the x86 technology is referred to as "Secure
> +    Launch" within the kernel code.
> +
> +Goals
> +=====
> +
> +The first use case that the TrenchBoot project focused on was the ability for
> +the Linux kernel to be started by a dynamic launch, in particular as part of an
> +early launch sequence. In this case the dynamic launch will be initiated by any
> +boot loader with associated support added to it, for example the first targeted
> +boot loader in this case was GRUB2. An integral part of establishing a
> +measurement-based launch integrity involves measuring everything that is
> +intended to be executed (kernel image, initrd, etc) and everything that will
> +configure that kernel to execute (command line, boot params, etc). Then storing
> +those measurements in a protected manner. Both the Intel and AMD dynamic launch
> +implementations leverage the Trusted Platform Module (TPM) to store those
> +measurements. The TPM itself has been designed such that a dynamic launch
> +unlocks a specific set of Platform Configuration Registers (PCR) for holding
> +measurement taken during the dynamic launch.  These are referred to as the DRTM
> +PCRs, PCRs 17-22. Further details on this process can be found in the
> +documentation for the GETSEC instruction provided by Intel's TXT and the SKINIT
> +instruction provided by AMD's AMD-V. The documentation on these technologies
> +can be readily found online; see the `Resources`_ section below for references.
> +
> +.. note::
> +    Currently only Intel TXT is supported in this first release of the Secure
> +    Launch feature. AMD/Hygon SKINIT and Arm support will be added in a
> +    subsequent release.
> +
> +To enable the kernel to be launched by GETSEC a stub, the Secure Launch stub,
> +must be built into the setup section of the compressed kernel to handle the
> +specific state that the dynamic launch process leaves the BSP. Also the Secure
> +Launch stub must measure everything that is going to be used as early as
> +possible. This stub code and subsequent code must also deal with the specific
> +state that the dynamic launch leaves the APs as well.
> +
> +Design Decisions
> +================
> +
> +A number of design decisions were made during the development of the Secure
> +Launch feature. The two primary guiding decisions were:
> +
> + - Keeping the Secure Launch code as separate from the rest of the kernel
> +   as possible.
> + - Modifying the existing boot path of the kernel as little as possible.
> +
> +The following illustrate how the implementation followed these design
> +decisions:
> +
> + - All the entry point code necessary to properly configure the system post
> +   launch is found in st_stub.S in the compressed kernel image. This code
> +   validates the state of the system, restores necessary system operating
> +   configurations and properly handles post launch CPU states.
> + - After the sl_stub.S is complete, it jumps directly to the unmodified
> +   startup_32 kernel entry point.
> + - A single call is made to a function sl_main() prior to the main kernel
> +   decompression step. This code performs further validation and takes the
> +   needed DRTM measurements.
> + - After the call to sl_main(), the main kernel is decompressed and boots as
> +   it normally would.
> + - Final setup for the Secure Launch kernel is done in a separate Secure
> +   Launch module that is loaded via a late initcall. This code is responsible
> +   for extending the measurements taken earlier into the TPM DRTM PCRs and
> +   setting up the securityfs interface to allow access the TPM event log and
> +   public TXT registers.
> + - On the reboot and kexec paths, calls are made to a function to finalize the
> +   state of the Secure Launch kernel.
> +
> +The one place where Secure Launch code is mixed directly in with kernel code is
> +in the SMP boot code. This is due to the unique state that the dynamic launch
> +leaves the APs in. On Intel this involves using a method other than the
> +standard INIT-SIPI sequence.
> +
> +A final note is that originally the extending of the PCRs was completed in the
> +Secure Launch stub when the measurements were taken. An alternative solution
> +had to be implemented due to the TPM maintainers objecting to the PCR
> +extensions being done with a minimal interface to the TPM that was an
> +independent implementation of the mainline kernel driver. Since the mainline
> +driver relies heavily on kernel interfaces not available in the compressed
> +kernel, it was not possible to reuse the mainline TPM driver. This resulted in
> +the decision to move the extension operations to the Secure Launch module in
> +the mainline kernel where the TPM driver would be available.
> +
> +Basic Boot Flow
> +===============
> +
> +Outlined here is summary of the boot flow for Secure Launch. A more detailed
> +review of Secure Launch process can be found in the Secure Launch
> +Specification, a link is located in the `Resources`_ section.
> +
> +Pre-launch: *Phase where the environment is prepared and configured to initiate the
> +secure launch by the boot chain.*
> +
> + - The SLRT is initialized and dl_stub is placed in memory.
> + - Load the kernel, initrd and ACM [2]_ into memory.
> + - Setup the TXT heap and page tables describing the MLE [1]_ per the
> +   specification.
> + - If non-UEFI platform, dl_stub is called.
> + - If UEFI platforms, SLRT registered with UEFI and efi-stub called.
> + - Upon completion, efi-stub will call EBS followed by dl_stub.
> + - The dl_stub will prepare the CPU and the TPM for the launch.
> + - The secure launch is then initiated with the GETSET[SENTER] instruction.
> +
> +Post-launch: *Phase where control is passed from the ACM to the MLE and the secure
> +kernel begins execution.*
> +
> + - Entry from the dynamic launch jumps to the SL stub.
> + - SL stub fixes up the world on the BSP.
> + - For TXT, SL stub wakes the APs, fixes up their worlds.
> + - For TXT, APs are left halted waiting for an NMI to wake them.
> + - SL stub jumps to startup_32.
> + - SL main does validation of buffers and memory locations. It sets
> +   the boot parameter loadflag value SLAUNCH_FLAG to inform the main
> +   kernel that a Secure Launch was done.
> + - SL main locates the TPM event log and writes the measurements of
> +   configuration and module information into it.
> + - Kernel boot proceeds normally from this point.
> + - During early setup, slaunch_setup() runs to finish some validation
> +   and setup tasks.
> + - The SMP bring up code is modified to wake the waiting APs. APs vector
> +   to rmpiggy and start up normally from that point.
> + - SL platform module is registered as a late initcall module. It reads
> +   the TPM event log and extends the measurements taken into the TPM PCRs.
> + - SL platform module initializes the securityfs interface to allow
> +   access to the TPM event log and TXT public registers.
> + - Kernel boot finishes booting normally
> + - SEXIT support to leave SMX mode is present on the kexec path and
> +   the various reboot paths (poweroff, reset, halt).
> +
> +PCR Usage
> +=========
> +
> +The TCG DRTM architecture there are three PCRs defined for usage, PCR.Details
> +(PCR17), PCR.Authorities (PCR18), and PCR.DLME_Authority (PCR19). For a deeper
> +understanding of Detail and Authorities it is recommended to review the TCG
> +DRTM architecture.
> +
> +To determine PCR usage, Linux Secure Launch follows the TrenchBoot Secure
> +Launch Specification of using a measurement policy stored in the SLRT. The
> +policy details what should be measured and the PCR in which to store the
> +measurement. The measurement policy provides the ability to select the
> +PCR.DLME_Detail (PCR20) PCR as the location for the DRTM components measured by
> +the kernel, e.g. external initrd image. This can then be combined with storing
> +the user authority in the PCR.DLME_Authority PCR to seal/attest to different
> +variations of platform details/authorities and user details/authorities. An
> +example of how this can be achieved was presented in the FOSDEM - 2021 talk
> +"Secure Upgrades with DRTM".
> +
> +Resources
> +=========
> +
> +The TrenchBoot project:
> +
> +https://trenchboot.org
> +
> +Secure Launch Specification:
> +
> +https://trenchboot.org/specifications/Secure_Launch/
> +
> +Trusted Computing Group's D-RTM Architecture:
> +
> +https://trustedcomputinggroup.org/wp-content/uploads/TCG_D-RTM_Architecture_v1-0_Published_06172013.pdf
> +
> +TXT documentation in the Intel TXT MLE Development Guide:
> +
> +https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
> +
> +TXT instructions documentation in the Intel SDM Instruction Set volume:
> +
> +https://software.intel.com/en-us/articles/intel-sdm
> +
> +AMD SKINIT documentation in the System Programming manual:
> +
> +https://www.amd.com/system/files/TechDocs/24593.pdf
> +
> +GRUB Secure Launch support:
> +
> +https://github.com/TrenchBoot/grub/tree/grub-sl-fc-38-dlstub
> +
> +FOSDEM 2021: Secure Upgrades with DRTM
> +
> +https://archive.fosdem.org/2021/schedule/event/firmware_suwd/
> +
> +.. [1]
> +    MLE: Measured Launch Environment is the binary runtime that is measured and
> +    then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
> +    requirements for the MLE in detail.
> +
> +.. [2]
> +    ACM: Intel's Authenticated Code Module. This is the 32b bit binary blob that
> +    is run securely by the GETSEC[SENTER] during a measured launch. It is described
> +    in the Intel documentation on TXT and versions for various chipsets are
> +    signed and distributed by Intel.
 
The formatting LGTM, thanks!

Regardless,

Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com>

-- 
An old man doll... just what I always wanted! - Clara

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
@ 2023-05-06  8:48     ` Bagas Sanjaya
  0 siblings, 0 replies; 200+ messages in thread
From: Bagas Sanjaya @ 2023-05-06  8:48 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel


[-- Attachment #1.1: Type: text/plain, Size: 51233 bytes --]

On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
> +=====================================
> +System Launch Integrity documentation
> +=====================================
> +
> +.. toctree::

By convention, doc toctree have 2-level depth (only page title and
first-level headings are visible). You may consider adding
`:maxdepth: 2` option.

> diff --git a/Documentation/security/launch-integrity/principles.rst b/Documentation/security/launch-integrity/principles.rst
> new file mode 100644
> index 0000000..73cf063
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/principles.rst
> @@ -0,0 +1,313 @@
> +=======================
> +System Launch Integrity
> +=======================
> +
> +This document serves to establish a common understanding of what is system
> +launch, the integrity concern for system launch, and why using a Root of Trust
> +(RoT) from a Dynamic Launch may be desired. Through out this document
> +terminology from the Trusted Computing Group (TCG) and National Institue for
> +Science and Technology (NIST) is used to ensure a vendor nutrual language is
> +used to describe and reference security-related concepts.
> +
> +System Launch
> +=============
> +
> +There is a tendency to only consider the classical power-on boot as the only
> +means to launch an Operating System (OS) on a computer system, but in fact most
> +modern processors support two methods to launch the system. To provide clarity a
> +common definition of a system launch should be established. This definition is
> +that a during a single power life cycle of a system, a System Launch consists
> +of an initialization event, typically in hardware, that is followed by an
> +executing software payload that takes the system from the initialized state to
> +a running state. Driven by the Trusted Computing Group (TCG) architecture,
> +modern processors are able to support two methods to launch a system, these two
> +types of system launch are known as Static Launch and Dynamic Launch.
> +
> +Static Launch
> +-------------
> +
> +Static launch is the system launch associated with the power cycle of the CPU.
> +Thus static launch refers to the classical power-on boot where the
> +initialization event is the release of the CPU from reset and the system
> +firmware is the software payload that brings the system up to a running state.
> +Since static launch is the system launch associated with the beginning of the
> +power lifecycle of a system, it is therefore a fixed, one-time system launch.
> +It is because of this that static launch is referred to and thought of as being
> +"static".
> +
> +Dynamic Launch
> +--------------
> +
> +Modern CPUs architectures provides a mechanism to re-initialize the system to a
> +"known good" state without requiring a power event. This re-initialization
> +event is the event for a dynamic launch and is referred to as the Dynamic
> +Launch Event (DLE). The DLE functions by accepting a software payload, referred
> +to as the Dynamic Configuration Environment (DCE), that execution is handed to
> +after the DLE is invoked. The DCE is responsible for bringing the system back
> +to a running state. Since the dynamic launch is not tied to a power event like
> +the static launch, this enables a dynamic launch to be initiated at any time
> +and multiple times during a single power life cycle. This dynamism is the
> +reasoning behind referring to this system launch as being dynamic.
> +
> +Because a dynamic launch can be conducted at any time during a single power
> +life cycle, they are classified into one of two types, an early launch or a
> +late launch.
> +
> +:Early Launch: When a dynamic launch is used as a transition from a static
> +   launch chain to the final Operating System.
> +
> +:Late Launch: The usage of a dynamic launch by an executing Operating System to
> +   transition to a “known good” state to perform one or more operations, e.g. to
> +   launch into a new Operating System.
> +
> +System Integrity
> +================
> +
> +A computer system can be considered a collection of mechanisms that work
> +together to produce a result. The assurance that the mechanisms are functioning
> +correctly and producing the expected result is the integrity of the system. To
> +ensure a system's integrity there are a subset of these mechanisms, commonly
> +referred to as security mechanisms, that are present to help ensure the system
> +produces the expected result or at least detect the potential of an unexpected
> +result may have happened. Since the security mechanisms are relied upon to
> +ensue the integrity of the system, these mechanisms are trusted. Upon
> +inspection these security mechanisms each have a set of properties and these
> +properties can be evaluated to determine how susceptible a mechanism might be
> +to failure. This assessment is referred to as the Strength of Mechanism and for
> +trusted mechanism enables for the trustworthiness of that mechanism to be
> +quantified.
> +
> +For software systems there are two system states for which the integrity is
> +critical, when the software is loaded into memory and when the software is
> +executing on the hardware. Ensuring that the expected software is load into
> +memory is referred to as load-time integrity while ensuring that the software
> +executing is the expected software is the runtime integrity of that software.
> +
> +Load-time Integrity
> +-------------------
> +
> +It is critical to understand what load-time integrity establishes about a
> +system and what is assumed, i.e. what is being trusted. Load-time integrity is
> +when a trusted entity, i.e. an entity with an assumed integrity, takes an
> +action to assess an entity being loaded into memory before it is used. A
> +variety of mechanisms may be used to conduct the assessment, each with
> +different properties. A particular property is whether the mechanism creates an
> +evidence of the assessment. Often either cryptographic signature checking or
> +hashing are the common assessment operations used.
> +
> +A signature checking assessment functions by requiring a representation of the
> +accepted authorities and uses those representations to assess if the entity has
> +been signed by an accepted authority. The benefit to this process is that
> +assessment process includes an adjudication of the assessment. The drawbacks
> +are that 1) the adjudication is susceptible to tampering by the Trusted
> +Computing Base (TCB), 2) there is no evidence to assert that an untampered
> +adjudication was completed, and 3) the system must be an active participant in
> +the key management infrastructure.
> +
> +A cryptographic hashing assessment does not adjudicate the assessment but
> +instead generates evidence of the assessment to be adjudicated independently.
> +The benefits to this approach is that the assessment may be simple such that it
> +is able to be implemented as an immutable mechanism, e.g. in hardware.
> +Additionally it is possible for the adjudication to be conducted where it
> +cannot be tampered with by the TCB. The drawback is that a compromised
> +environment will be allowed to execute until an adjudication can be completed.
> +
> +Ultimately load-time integrity provides confidence that the correct entity was
> +loaded and in the absence of a run-time integrity mechanism assumes, i.e
> +trusts, that the entity will never become corrupted.
> +
> +Runtime Integrity
> +-----------------
> +
> +Runtime integrity in the general sense is when a trusted entity makes an
> +assessment of an entity at any point in time during the assessed entity's
> +execution. A more concrete explanation is the taking of an integrity assessment
> +of an active process executing on the system at any point during the process'
> +execution. Often the load-time integrity of an operating system's user-space,
> +i.e. the operating environment, is confused to be the runtime integrity of the
> +system since it is an integrity assessment of the "runtime" software. The
> +reality is that actual runtime integrity is a very difficult problem and thus
> +not very many solutions are public and/or available. One example of a runtime
> +integrity solution would be John Hopkins Advanced Physics Labratory's (APL)
> +Linux Kernel Integrity Module (LKIM).
> +
> +Trust Chains
> +============
> +
> +Bulding upon the understanding of security mechanisms to establish load-time
> +integrity of an entity, it is possible to chain together load-time integrity
> +assessments to establish the integrity of the whole system. This process is
> +known as transitive trust and provides the concept of building a chain of
> +load-time integrity assessments, commonly referred to as a trust chain. These
> +assessments may be used to adjudicate the load-time integrity of the whole
> +system. This trust chain is started by a trusted entity that does the first
> +assessment. This first entity is referred to as the Root of Trust(RoT) with the
> +entities name being derived from the mechanism used for the assessment, i.e.
> +RoT for Verification (RTV) and RoT for Measurement (RTM).
> +
> +A trust chain is itself a mechanism, specifically a mechanism of mechanisms,
> +and therefore it too has a Strength of Mechanism. The factors that contribute
> +to a trust chain's strength are,
> +
> +  - The strength of the chain's RoT
> +  - The strength of each member of the trust chain
> +  - The length, i.e. the number of members, of the chain
> +
> +Therefore to provide the strongest trust chains, they should start with a
> +strong RoT and should consist of members being of low complexity and minimizing
> +the number of members participating as is possible. In a more colloquial sense,
> +a trust chain is only as strong as it weakests link and more links increase
> +the probability of a weak link.
> +
> +Dynamic Launch Components
> +=========================
> +
> +The TCG architecture for dynamic launch is composed of a component series that
> +are used to setup and then carry out the launch. These components work together
> +to construct a RTM trust chain that is rooted in the dynamic launch and thus
> +commonly referred to as the Dynamic Root of Trust for Measurement (DRTM) chain.
> +
> +What follows is a brief explanation of each component in execution order. A
> +subset of these components are what establishes the dynamic launch's trust
> +chain.
> +
> +Dynamic Configuration Environment Preamble
> +------------------------------------------
> +
> +The Dynamic Configuration Environment (DCE) Preamble is responsible for setting
> +up the system environment in preparation for a dynamic launch. The DCE Preamble
> +is not a part of the DRTM trust chain.
> +
> +Dynamic Launch Event
> +--------------------
> +
> +The dynamic launch event is the event, typically a CPU instruction, that triggers
> +the system's dynamic launch mechanism to begin the launch. The dynamic launch
> +mechanism is also the RoT for the DRTM trust chain.
> +
> +Dynamic Configuration Environment
> +---------------------------------
> +
> +The dynamic launch mechanism may have resulted in a reset of a portion of the
> +system. To bring the system back to an adequate state for system software the
> +dynamic launch will hand over control to the DCE. Prior to handing over this
> +control, the dynamic launch will measure the DCE. Once the DCE is complete it
> +will proceed to measure and then execute the Dynamic Launch Measured
> +Environment (DLME).
> +
> +Dynamic Launch Measured Environment
> +-----------------------------------
> +
> +The DLME is the first system kernel to have control of the system but may not
> +be the last. Depending on the usage and configuration, the DLME may be the
> +final/target operating system or it may be a boot loader that will load the
> +final/target operating system.
> +
> +Why DRTM
> +========
> +
> +It is a fact that DRTM increases the load-time integrity of the system by
> +providing a trust chain that has an immutable hardware RoT, uses a limited
> +number of small, special purpose code to establish the trust chain that starts
> +the target operating system. As mentioned in the Trust Chain section, these are
> +the main three factors in driving up the strength of a trust chain. As can been
> +seen by the BootHole exploit, which in fact did not effect the integrity of
> +DRTM solutions, the sophistication of attacks targeting system launch is at an
> +all time high. There is no reason a system should not employ every integrity
> +measure hardware makes available. This is the crux of a defense-in-depth
> +approach to system security. In the past the now closed SMI gap was often
> +pointed to as invalidating DRTM, which in fact was nothing but a strawman
> +argument. As has continued to be demonstrated, if/when SMM is corrupted it can
> +always circumvent all load-time integrity, SRTM and DRTM, because it is a
> +run-time integrity problem. Regardless, Intel and AMD have both deployed
> +runtime integrity for SMI and SMM which is tied directly to DRTM such that this
> +perceived deficiency is now non-existent and the world is moving forward with
> +an expectation that DRTM must be present.
> +
> +Glossary
> +========
> +
> +.. glossary::
> +  integrity
> +    Guarding against improper information modification or destruction, and
> +    includes ensuring information non-repudiation and authenticity.
> +
> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> +  mechanism
> +    A process or system that is used to produce a particular result.
> +
> +    - NIST Special Publication 800-160 (VOLUME 1 ) - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-160v1.pdf
> +
> +  risk
> +    A measure of the extent to which an entity is threatened by a potential
> +    circumstance or event, and typically a function of: (i) the adverse impacts
> +    that would arise if the circumstance or event occurs; and (ii) the
> +    likelihood of occurrence.
> +
> +    - NIST SP 800-30 Rev. 1 - https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-30r1.pdf
> +
> +  security mechanism
> +    A device or function designed to provide one or more security services
> +    usually rated in terms of strength of service and assurance of the design.
> +
> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> +  Strength of Mechanism
> +    A scale for measuring the relative strength of a security mechanism
> +
> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> +  transitive trust
> +    Also known as "Inductive Trust", in this process a Root of Trust gives a
> +    trustworthy description of a second group of functions. Based on this
> +    description, an interested entity can determine the trust it is to place in
> +    this second group of functions. If the interested entity determines that
> +    the trust level of the second group of functions is acceptable, the trust
> +    boundary is extended from the Root of Trust to include the second group of
> +    functions. In this case, the process can be iterated. The second group of
> +    functions can give a trustworthy description of the third group of
> +    functions, etc. Transitive trust is used to provide a trustworthy
> +    description of platform characteristics, and also to prove that
> +    non-migratable keys are non-migratable
> +
> +    - TCG Glossary - https://trustedcomputinggroup.org/wp-content/uploads/TCG-Glossary-V1.1-Rev-1.0.pdf
> +
> +  trust
> +    The confidence one element has in another that the second element will
> +    behave as expected`
> +
> +    - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
> +
> +  trust anchor
> +    An authoritative entity for which trust is assumed.
> +
> +    - NIST SP 800-57 Part 1 Rev. 5 - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf
> +
> +  trusted
> +    An element that another element relies upon to fulfill critical
> +    requirements on its behalf.
> +
> +    - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
> +
> +  trusted computing base (TCB)
> +    Totality of protection mechanisms within a computer system, including
> +    hardware, firmware, and software, the combination responsible for enforcing
> +    a security policy.
> +
> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> +  trusted computer system
> +    A system that has the necessary security functions and assurance that the
> +    security policy will be enforced and that can process a range of
> +    information sensitivities (i.e. classified, controlled unclassified
> +    information (CUI), or unclassified public information) simultaneously.
> +
> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> +  trustworthiness
> +    The attribute of a person or enterprise that provides confidence to others
> +    of the qualifications, capabilities, and reliability of that entity to
> +    perform specific tasks and fulfill assigned responsibilities.
> +
> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> diff --git a/Documentation/security/launch-integrity/secure_launch_details.rst b/Documentation/security/launch-integrity/secure_launch_details.rst
> new file mode 100644
> index 0000000..2e71543
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/secure_launch_details.rst
> @@ -0,0 +1,564 @@
> +===================================
> +Secure Launch Config and Interfaces
> +===================================
> +
> +Configuration
> +=============
> +
> +The settings to enable Secure Launch using Kconfig are under::
> +
> +  "Processor type and features" --> "Secure Launch support"
> +
> +A kernel with this option enabled can still be booted using other supported
> +methods.
> +
> +To reduce the Trusted Computing Base (TCB) of the MLE [1]_, the build
> +configuration should be pared down as narrowly as one's use case allows.
> +The fewer drivers (less active hardware) and features reduces the attack
> +surface. E.g. in the extreme, the MLE could only have local disk access
> +and no other hardware support. Or only network access for remote attestation.
> +
> +It is also desirable if possible to embed the initrd used with the MLE kernel
> +image to reduce complexity.
> +
> +The following are a few important configuration necessities to always consider:
> +
> +KASLR Configuration
> +-------------------
> +
> +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
> +built with KASLR disabled::
> +
> +  "Processor type and features" -->
> +      "Build a relocatable kernel" -->
> +          "Randomize the address of the kernel image (KASLR) [ ]"
> +
> +This unsets the Kconfig value CONFIG_RANDOMIZE_BASE.
> +
> +If not possible, KASLR must be disabled on the kernel command line when doing
> +a Secure Launch as follows::
> +
> +  nokaslr
> +
> +IOMMU Configuration
> +-------------------
> +
> +When doing a Secure Launch, the IOMMU should always be enabled and the drivers
> +loaded. However, IOMMU passthrough mode should never be used. This leaves the
> +MLE completely exposed to DMA after the PMR's [2]_ are disabled. The current default
> +mode is to use IOMMU in lazy translated mode but strict translated mode is the preferred
> +IOMMU mode and this should be selected in the build configuration::
> +
> +  "Device Drivers" -->
> +      "IOMMU Hardware Support" -->
> +          "IOMMU default domain type" -->
> +              "(X) Translated - Strict"
> +
> +In addition, the Intel IOMMU should be on by default. The following sets this as the
> +default in the build configuration::
> +
> +  "Device Drivers" -->
> +      "IOMMU Hardware Support" -->
> +          "Support for Intel IOMMU using DMA Remapping Devices [*]"
> +
> +and::
> +
> +  "Device Drivers" -->
> +      "IOMMU Hardware Support" -->
> +          "Support for Intel IOMMU using DMA Remapping Devices [*]" -->
> +              "Enable Intel DMA Remapping Devices by default  [*]"
> +
> +It is recommended that no other command line options should be set to override
> +the defaults above.
> +
> +Secure Launch Resource Table
> +============================
> +
> +The Secure Launch Resource Table (SLRT) is a platform-agnostic, standard format
> +for providing information for the pre-launch environment and to pass
> +information to the post-launch environment. The table is populated by one or
> +more bootloaders in the boot chain and used by Secure Launch on how to setup
> +the environment during post-launch. The details for the SLRT are documented
> +in the TrenchBoot Secure Launch Specifcation [3]_.
> +
> +Intel TXT Interface
> +===================
> +
> +The primary interfaces between the various components in TXT are the TXT MMIO
> +registers and the TXT heap. The MMIO register banks are described in Appendix B
> +of the TXT MLE [1]_ Development Guide.
> +
> +The TXT heap is described in Appendix C of the TXT MLE [1]_ Development
> +Guide. Most of the TXT heap is predefined in the specification. The heap is
> +initialized by firmware and the pre-launch environment and is subsequently used
> +by the SINIT ACM. One section, called the OS to MLE Data Table, is reserved for
> +software to define. This table is set up per the recommendation detailed in
> +Appendix B of the TrenchBoot Secure Launch Specification::
> +
> +        /*
> +         * Secure Launch defined OS/MLE TXT Heap table
> +         */
> +        struct txt_os_mle_data {
> +                u32 version;
> +                u32 boot_params_addr;
> +                struct slr_table *slrt;
> +                u64 txt_info;
> +                u32 ap_wake_block;
> +                u32 ap_wake_block_size;
> +                u8 mle_scratch[64];
> +        } __packed;
> +
> +Description of structure:
> +
> +=====================  ========================================================================
> +Field                  Use
> +=====================  ========================================================================
> +version                Structure version, current value 1
> +boot_params_addr       Physical base address of the Linux boot parameters
> +slrt                   Physical address of the Secure Launch Resource Table
> +txt_info               Pointer into the SLRT for easily locating TXT specific table
> +ap_wake_block          Physical address of the block of memory for parking APs after a launch
> +ap_wake_block_size     Size of the AP wake block
> +mle_scratch            Scratch area used post-launch by the MLE kernel. Fields:
> + 
> +                        - SL_SCRATCH_AP_EBX area to share %ebx base pointer among CPUs
> +                        - SL_SCRATCH_AP_JMP_OFFSET offset to abs. ljmp fixup location for APs
> +=====================  ========================================================================
> +
> +Error Codes
> +-----------
> +
> +The TXT specification defines the layout for TXT 32 bit error code values.
> +The bit encodings indicate where the error originated (e.g. with the CPU,
> +in the SINIT ACM, in software). The error is written to a sticky TXT
> +register that persists across resets called TXT.ERRORCODE (see the TXT
> +MLE Development Guide). The errors defined by the Secure Launch feature are
> +those generated in the MLE software. They have the format::
> +
> +  0xc0008XXX
> +
> +The low 12 bits are free for defining the following Secure Launch specific
> +error codes.
> +
> +======  ================
> +Name:   SL_ERROR_GENERIC
> +Value:  0xc0008001
> +======  ================
> +
> +Description:
> +
> +Generic catch all error. Currently unused.
> +
> +======  =================
> +Name:   SL_ERROR_TPM_INIT
> +Value:  0xc0008002
> +======  =================
> +
> +Description:
> +
> +The Secure Launch code failed to get an access to the TPM hardware interface.
> +This is most likely to due to misconfigured hardware or kernel. Ensure the
> +TPM chip is enabled and the kernel TPM support is built in (it should not be
> +built as a module).
> +
> +======  ==========================
> +Name:   SL_ERROR_TPM_INVALID_LOG20
> +Value:  0xc0008003
> +======  ==========================
> +
> +Description:
> +
> +The Secure Launch code failed to find a valid event log descriptor for TPM
> +version 2.0 or the event log descriptor is malformed. Usually this indicates
> +that incompatible versions of the pre-launch environment and the MLE kernel.
> +The pre-launch environment and the kernel share a structure in the TXT heap and
> +if this structure (the OS-MLE table) is mismatched, this error is often seen.
> +This TXT heap area is setup by the pre-launch environment so the issue may
> +originate there. It could be the sign of an attempted attack.
> +
> +======  ===========================
> +Name:   SL_ERROR_TPM_LOGGING_FAILED
> +Value:  0xc0008004
> +======  ===========================
> +
> +Description:
> +
> +There was a failed attempt to write a TPM event to the event log early in the
> +Secure Launch process. This is likely the result of a malformed TPM event log
> +buffer. Formatting of the event log buffer information is done by the
> +pre-launch environment so the issue most likely originates there.
> +
> +======  ============================
> +Name:   SL_ERROR_REGION_STRADDLE_4GB
> +Value:  0xc0008005
> +======  ============================
> +
> +Description:
> +
> +During early validation a buffer or region was found to straddle the 4GB
> +boundary. Because of the way TXT does DMA memory protection, this is an
> +unsafe configuration and is flagged as an error. This is most likely a
> +configuration issue in the pre-launch environment. It could also be the sign of
> +an attempted attack.
> +
> +======  ===================
> +Name:   SL_ERROR_TPM_EXTEND
> +Value:  0xc0008006
> +======  ===================
> +
> +Description:
> +
> +There was a failed attempt to extend a TPM PCR in the Secure Launch platform
> +module. This is most likely to due to misconfigured hardware or kernel. Ensure
> +the TPM chip is enabled and the kernel TPM support is built in (it should not
> +be built as a module).
> +
> +======  ======================
> +Name:   SL_ERROR_MTRR_INV_VCNT
> +Value:  0xc0008007
> +======  ======================
> +
> +Description:
> +
> +During early Secure Launch validation an invalid variable MTRR count was found.
> +The pre-launch environment passes a number of MSR values to the MLE to restore
> +including the MTRRs. The values are restored by the Secure Launch early entry
> +point code. After measuring the values supplied by the pre-launch environment,
> +a discrepancy was found validating the values. It could be the sign of an
> +attempted attack.
> +
> +======  ==========================
> +Name:   SL_ERROR_MTRR_INV_DEF_TYPE
> +Value:  0xc0008008
> +======  ==========================
> +
> +Description:
> +
> +During early Secure Launch validation an invalid default MTRR type was found.
> +See SL_ERROR_MTRR_INV_VCNT for more details.
> +
> +======  ======================
> +Name:   SL_ERROR_MTRR_INV_BASE
> +Value:  0xc0008009
> +======  ======================
> +
> +Description:
> +
> +During early Secure Launch validation an invalid variable MTRR base value was
> +found. See SL_ERROR_MTRR_INV_VCNT for more details.
> +
> +======  ======================
> +Name:   SL_ERROR_MTRR_INV_MASK
> +Value:  0xc000800a
> +======  ======================
> +
> +Description:
> +
> +During early Secure Launch validation an invalid variable MTRR mask value was
> +found. See SL_ERROR_MTRR_INV_VCNT for more details.
> +
> +======  ========================
> +Name:   SL_ERROR_MSR_INV_MISC_EN
> +Value:  0xc000800b
> +======  ========================
> +
> +Description:
> +
> +During early Secure Launch validation an invalid miscellaneous enable MSR value
> +was found. See SL_ERROR_MTRR_INV_VCNT for more details.
> +
> +======  =========================
> +Name:   SL_ERROR_INV_AP_INTERRUPT
> +Value:  0xc000800c
> +======  =========================
> +
> +Description:
> +
> +The application processors (APs) wait to be woken up by the SMP initialization
> +code. The only interrupt that they expect is an NMI; all other interrupts
> +should be masked. If an AP gets some other interrupt other than an NMI it will
> +cause this error. This error is very unlikely to occur.
> +
> +======  =========================
> +Name:   SL_ERROR_INTEGER_OVERFLOW
> +Value:  0xc000800d
> +======  =========================
> +
> +Description:
> +
> +A buffer base and size passed to the MLE caused an integer overflow when
> +added together. This is most likely a configuration issue in the pre-launch
> +environment. It could also be the sign of an attempted attack.
> +
> +======  ==================
> +Name:   SL_ERROR_HEAP_WALK
> +Value:  0xc000800e
> +======  ==================
> +
> +Description:
> +
> +An error occurred in TXT heap walking code. The underlying issue is a failure to
> +early_memremap() portions of the heap, most likely due to a resource shortage.
> +
> +======  =================
> +Name:   SL_ERROR_HEAP_MAP
> +Value:  0xc000800f
> +======  =================
> +
> +Description:
> +
> +This error is essentially the same as SL_ERROR_HEAP_WALK but occurred during the
> +actual early_memremap() operation.
> +
> +======  =========================
> +Name:   SL_ERROR_REGION_ABOVE_4GB
> +Value:  0xc0008010
> +======  =========================
> +
> +Description:
> +
> +A memory region used by the MLE is above 4GB. In general this is not a problem
> +because memory > 4Gb can be protected from DMA. There are certain buffers that
> +should never be above 4Gb though and one of these caused the violation. This is
> +most likely a configuration issue in the pre-launch environment. It could also
> +be the sign of an attempted attack.
> +
> +======  ==========================
> +Name:   SL_ERROR_HEAP_INVALID_DMAR
> +Value:  0xc0008011
> +======  ==========================
> +
> +Description:
> +
> +The backup copy of the ACPI DMAR table which is supposed to be located in the
> +TXT heap could not be found. This is due to a bug in the platform's ACM module
> +or in firmware.
> +
> +======  =======================
> +Name:   SL_ERROR_HEAP_DMAR_SIZE
> +Value:  0xc0008012
> +======  =======================
> +
> +Description:
> +
> +The backup copy of the ACPI DMAR table in the TXT heap is to large to be stored
> +for later usage. This error is very unlikely to occur since the area reserved
> +for the copy is far larger than the DMAR should be.
> +
> +======  ======================
> +Name:   SL_ERROR_HEAP_DMAR_MAP
> +Value:  0xc0008013
> +======  ======================
> +
> +Description:
> +
> +The backup copy of the ACPI DMAR table in the TXT heap could not be mapped. The
> +underlying issue is a failure to early_memremap() the DMAR table, most likely
> +due to a resource shortage.
> +
> +======  ====================
> +Name:   SL_ERROR_HI_PMR_BASE
> +Value:  0xc0008014
> +======  ====================
> +
> +Description:
> +
> +On a system with more than 4G of RAM, the high PMR [2]_ base address should be set
> +to 4G. This error is due to that not being the case. This PMR value is set by
> +the pre-launch environment so the issue most likely originates there. It could also
> +be the sign of an attempted attack.
> +
> +======  ====================
> +Name:   SL_ERROR_HI_PMR_SIZE
> +Value:  0xc0008015
> +======  ====================
> +
> +Description:
> +
> +On a system with more than 4G of RAM, the high PMR [2]_ size should be set to cover
> +all RAM > 4G. This error is due to that not being the case. This PMR value is
> +set by the pre-launch environment so the issue most likely originates there. It
> +could also be the sign of an attempted attack.
> +
> +======  ====================
> +Name:   SL_ERROR_LO_PMR_BASE
> +Value:  0xc0008016
> +======  ====================
> +
> +Description:
> +
> +The low PMR [2]_ base should always be set to address zero. This error is due to
> +that not being the case. This PMR value is set by the pre-launch environment
> +so the issue most likely originates there. It could also be the sign of an attempted
> +attack.
> +
> +======  ====================
> +Name:   SL_ERROR_LO_PMR_MLE
> +Value:  0xc0008017
> +======  ====================
> +
> +Description:
> +
> +This error indicates the MLE image is not covered by the low PMR [2]_ range. The
> +PMR values are set by the pre-launch environment so the issue most likely originates
> +there. It could also be the sign of an attempted attack.
> +
> +======  =======================
> +Name:   SL_ERROR_INITRD_TOO_BIG
> +Value:  0xc0008018
> +======  =======================
> +
> +Description:
> +
> +The external initrd provided is larger than 4Gb. This is not a valid
> +configuration for a Secure Launch due to managing DMA protection.
> +
> +======  =========================
> +Name:   SL_ERROR_HEAP_ZERO_OFFSET
> +Value:  0xc0008019
> +======  =========================
> +
> +Description:
> +
> +During a TXT heap walk an invalid/zero next table offset value was found. This
> +indicates the TXT heap is malformed. The TXT heap is initialized by the
> +pre-launch environment so the issue most likely originates there. It could also
> +be a sign of an attempted attack. In addition, ACM is also responsible for
> +manipulating parts of the TXT heap so the issue could be due to a bug in the
> +platform's ACM module.
> +
> +======  =============================
> +Name:   SL_ERROR_WAKE_BLOCK_TOO_SMALL
> +Value:  0xc000801a
> +======  =============================
> +
> +Description:
> +
> +The AP wake block buffer passed to the MLE via the OS-MLE TXT heap table is not
> +large enough. This value is set by the pre-launch environment so the issue most
> +likely originates there. It also could be the sign of an attempted attack.
> +
> +======  ===========================
> +Name:   SL_ERROR_MLE_BUFFER_OVERLAP
> +Value:  0xc000801b
> +======  ===========================
> +
> +Description:
> +
> +One of the buffers passed to the MLE via the OS-MLE TXT heap table overlaps
> +with the MLE image in memory. This value is set by the pre-launch environment
> +so the issue most likely originates there. It could also be the sign of an attempted
> +attack.
> +
> +======  ==========================
> +Name:   SL_ERROR_BUFFER_BEYOND_PMR
> +Value:  0xc000801c
> +======  ==========================
> +
> +Description:
> +
> +One of the buffers passed to the MLE via the OS-MLE TXT heap table is not
> +protected by a PMR. This value is set by the pre-launch environment so the
> +issue most likey  originates there. It could also be the sign of an attempted
> +attack.
> +
> +======  =============================
> +Name:   SL_ERROR_OS_SINIT_BAD_VERSION
> +Value:  0xc000801d
> +======  =============================
> +
> +Description:
> +
> +The version of the OS-SINIT TXT heap table is bad. It must be 6 or greater.
> +This value is set by the pre-launch environment so the issue most likely
> +originates there. It could also be the sign of an attempted attack. It is also
> +possible though very unlikely that the platform is so old that the ACM being
> +used requires an unsupported version.
> +
> +======  =====================
> +Name:   SL_ERROR_EVENTLOG_MAP
> +Value:  0xc000801e
> +======  =====================
> +
> +Description:
> +
> +An error occurred in the Secure Launch module while mapping the TPM event log.
> +The underlying issue is memremap() failure, most likely due to a resource
> +shortage.
> +
> +======  ========================
> +Name:   SL_ERROR_TPM_NUMBER_ALGS
> +Value:  0xc000801f
> +======  ========================
> +
> +Description:
> +
> +The TPM 2.0 event log reports an unsupported number of hashing algorithms.
> +Secure launch currently only supports a maximum of two: SHA1 and SHA256.
> +
> +======  ===========================
> +Name:   SL_ERROR_TPM_UNKNOWN_DIGEST
> +Value:  0xc0008020
> +======  ===========================
> +
> +Description:
> +
> +The TPM 2.0 event log reports an unsupported hashing algorithm. Secure launch
> +currently only supports two algorithms: SHA1 and SHA256.
> +
> +======  ==========================
> +Name:   SL_ERROR_TPM_INVALID_EVENT
> +Value:  0xc0008021
> +======  ==========================
> +
> +Description:
> +
> +An invalid/malformed event was found in the TPM event log while reading it.
> +Since only trusted entities are supposed to be writing the event log, this
> +would indicate either a bug or a possible attack.
> +
> +======  =====================
> +Name:   SL_ERROR_INVALID_SLRT
> +Value:  0xc0008022
> +======  =====================
> +
> +Description:
> +
> +The Secure Launch Resource Table is invalid or malformed and is unusable.
> +This implies the pre-launch code did not properly setup the SLRT.
> +
> +======  ===========================
> +Name:   SL_ERROR_SLRT_MISSING_ENTRY
> +Value:  0xc0008023
> +======  ===========================
> +
> +Description:
> +
> +The Secure Launch Resource Table is missing a required entry within it.
> +This implies the pre-launch code did not properly setup the SLRT.
> +
> +======  =================
> +Name:   SL_ERROR_SLRT_MAP
> +Value:  0xc0008024
> +======  =================
> +
> +Description:
> +
> +An error occurred in the Secure Launch module while mapping the Secure Launch
> +Resource table. The underlying issue is memremap() failure, most likely due to
> +a resource shortage.
> +
> +.. [1]
> +    MLE: Measured Launch Environment is the binary runtime that is measured and
> +    then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
> +    requirements for the MLE in detail.
> +
> +.. [2]
> +    PMR: Intel VTd has a feature in the IOMMU called Protected Memory Registers.
> +    There are two of these registers and they allow all DMA to be blocked
> +    to large areas of memory. The low PMR can cover all memory below 4Gb on 2Mb
> +    boundaries. The high PMR can cover all RAM on the system, again on 2Mb
> +    boundaries. This feature is used during a Secure Launch by TXT.
> +
> +.. [3]
> +    Secure Launch Specification: https://trenchboot.org/specifications/Secure_Launch/
> diff --git a/Documentation/security/launch-integrity/secure_launch_overview.rst b/Documentation/security/launch-integrity/secure_launch_overview.rst
> new file mode 100644
> index 0000000..ba91d73
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/secure_launch_overview.rst
> @@ -0,0 +1,220 @@
> +======================
> +Secure Launch Overview
> +======================
> +
> +Overview
> +========
> +
> +Prior to the start of the TrenchBoot project, the only active Open Source
> +project supporting dynamic launch was Intel's tboot project to support their
> +implementation of dynamic launch known as Intel Trusted eXecution Technology
> +(TXT). The approach taken by tboot was to provide an exokernel that could
> +handle the launch protocol implemented by Intel's special loader, the SINIT
> +Authenticated Code Module (ACM [2]_) and remained in memory to manage the SMX
> +CPU mode that a dynamic launch would put a system. While it is not precluded
> +from being used for doing a late launch, tboot's primary use case was to be
> +used as an early launch solution. As a result the TrenchBoot project started
> +the development of Secure Launch kernel feature to provide a more generalized
> +approach. The focus of the effort is twofold, the first is to make the Linux
> +kernel directly aware of the launch protocol used by Intel, AMD/Hygon, Arm, and
> +potentially OpenPOWER. The second is to make the Linux kernel be able to
> +initiate a dynamic launch. It is through this approach that the Secure Launch
> +kernel feature creates a basis for the Linux kernel to be used in a variety of
> +dynamic launch use cases.
> +
> +.. note::
> +    A quick note on terminology. The larger open source project itself is
> +    called TrenchBoot, which is hosted on GitHub (links below). The kernel
> +    feature enabling the use of the x86 technology is referred to as "Secure
> +    Launch" within the kernel code.
> +
> +Goals
> +=====
> +
> +The first use case that the TrenchBoot project focused on was the ability for
> +the Linux kernel to be started by a dynamic launch, in particular as part of an
> +early launch sequence. In this case the dynamic launch will be initiated by any
> +boot loader with associated support added to it, for example the first targeted
> +boot loader in this case was GRUB2. An integral part of establishing a
> +measurement-based launch integrity involves measuring everything that is
> +intended to be executed (kernel image, initrd, etc) and everything that will
> +configure that kernel to execute (command line, boot params, etc). Then storing
> +those measurements in a protected manner. Both the Intel and AMD dynamic launch
> +implementations leverage the Trusted Platform Module (TPM) to store those
> +measurements. The TPM itself has been designed such that a dynamic launch
> +unlocks a specific set of Platform Configuration Registers (PCR) for holding
> +measurement taken during the dynamic launch.  These are referred to as the DRTM
> +PCRs, PCRs 17-22. Further details on this process can be found in the
> +documentation for the GETSEC instruction provided by Intel's TXT and the SKINIT
> +instruction provided by AMD's AMD-V. The documentation on these technologies
> +can be readily found online; see the `Resources`_ section below for references.
> +
> +.. note::
> +    Currently only Intel TXT is supported in this first release of the Secure
> +    Launch feature. AMD/Hygon SKINIT and Arm support will be added in a
> +    subsequent release.
> +
> +To enable the kernel to be launched by GETSEC a stub, the Secure Launch stub,
> +must be built into the setup section of the compressed kernel to handle the
> +specific state that the dynamic launch process leaves the BSP. Also the Secure
> +Launch stub must measure everything that is going to be used as early as
> +possible. This stub code and subsequent code must also deal with the specific
> +state that the dynamic launch leaves the APs as well.
> +
> +Design Decisions
> +================
> +
> +A number of design decisions were made during the development of the Secure
> +Launch feature. The two primary guiding decisions were:
> +
> + - Keeping the Secure Launch code as separate from the rest of the kernel
> +   as possible.
> + - Modifying the existing boot path of the kernel as little as possible.
> +
> +The following illustrate how the implementation followed these design
> +decisions:
> +
> + - All the entry point code necessary to properly configure the system post
> +   launch is found in st_stub.S in the compressed kernel image. This code
> +   validates the state of the system, restores necessary system operating
> +   configurations and properly handles post launch CPU states.
> + - After the sl_stub.S is complete, it jumps directly to the unmodified
> +   startup_32 kernel entry point.
> + - A single call is made to a function sl_main() prior to the main kernel
> +   decompression step. This code performs further validation and takes the
> +   needed DRTM measurements.
> + - After the call to sl_main(), the main kernel is decompressed and boots as
> +   it normally would.
> + - Final setup for the Secure Launch kernel is done in a separate Secure
> +   Launch module that is loaded via a late initcall. This code is responsible
> +   for extending the measurements taken earlier into the TPM DRTM PCRs and
> +   setting up the securityfs interface to allow access the TPM event log and
> +   public TXT registers.
> + - On the reboot and kexec paths, calls are made to a function to finalize the
> +   state of the Secure Launch kernel.
> +
> +The one place where Secure Launch code is mixed directly in with kernel code is
> +in the SMP boot code. This is due to the unique state that the dynamic launch
> +leaves the APs in. On Intel this involves using a method other than the
> +standard INIT-SIPI sequence.
> +
> +A final note is that originally the extending of the PCRs was completed in the
> +Secure Launch stub when the measurements were taken. An alternative solution
> +had to be implemented due to the TPM maintainers objecting to the PCR
> +extensions being done with a minimal interface to the TPM that was an
> +independent implementation of the mainline kernel driver. Since the mainline
> +driver relies heavily on kernel interfaces not available in the compressed
> +kernel, it was not possible to reuse the mainline TPM driver. This resulted in
> +the decision to move the extension operations to the Secure Launch module in
> +the mainline kernel where the TPM driver would be available.
> +
> +Basic Boot Flow
> +===============
> +
> +Outlined here is summary of the boot flow for Secure Launch. A more detailed
> +review of Secure Launch process can be found in the Secure Launch
> +Specification, a link is located in the `Resources`_ section.
> +
> +Pre-launch: *Phase where the environment is prepared and configured to initiate the
> +secure launch by the boot chain.*
> +
> + - The SLRT is initialized and dl_stub is placed in memory.
> + - Load the kernel, initrd and ACM [2]_ into memory.
> + - Setup the TXT heap and page tables describing the MLE [1]_ per the
> +   specification.
> + - If non-UEFI platform, dl_stub is called.
> + - If UEFI platforms, SLRT registered with UEFI and efi-stub called.
> + - Upon completion, efi-stub will call EBS followed by dl_stub.
> + - The dl_stub will prepare the CPU and the TPM for the launch.
> + - The secure launch is then initiated with the GETSET[SENTER] instruction.
> +
> +Post-launch: *Phase where control is passed from the ACM to the MLE and the secure
> +kernel begins execution.*
> +
> + - Entry from the dynamic launch jumps to the SL stub.
> + - SL stub fixes up the world on the BSP.
> + - For TXT, SL stub wakes the APs, fixes up their worlds.
> + - For TXT, APs are left halted waiting for an NMI to wake them.
> + - SL stub jumps to startup_32.
> + - SL main does validation of buffers and memory locations. It sets
> +   the boot parameter loadflag value SLAUNCH_FLAG to inform the main
> +   kernel that a Secure Launch was done.
> + - SL main locates the TPM event log and writes the measurements of
> +   configuration and module information into it.
> + - Kernel boot proceeds normally from this point.
> + - During early setup, slaunch_setup() runs to finish some validation
> +   and setup tasks.
> + - The SMP bring up code is modified to wake the waiting APs. APs vector
> +   to rmpiggy and start up normally from that point.
> + - SL platform module is registered as a late initcall module. It reads
> +   the TPM event log and extends the measurements taken into the TPM PCRs.
> + - SL platform module initializes the securityfs interface to allow
> +   access to the TPM event log and TXT public registers.
> + - Kernel boot finishes booting normally
> + - SEXIT support to leave SMX mode is present on the kexec path and
> +   the various reboot paths (poweroff, reset, halt).
> +
> +PCR Usage
> +=========
> +
> +The TCG DRTM architecture there are three PCRs defined for usage, PCR.Details
> +(PCR17), PCR.Authorities (PCR18), and PCR.DLME_Authority (PCR19). For a deeper
> +understanding of Detail and Authorities it is recommended to review the TCG
> +DRTM architecture.
> +
> +To determine PCR usage, Linux Secure Launch follows the TrenchBoot Secure
> +Launch Specification of using a measurement policy stored in the SLRT. The
> +policy details what should be measured and the PCR in which to store the
> +measurement. The measurement policy provides the ability to select the
> +PCR.DLME_Detail (PCR20) PCR as the location for the DRTM components measured by
> +the kernel, e.g. external initrd image. This can then be combined with storing
> +the user authority in the PCR.DLME_Authority PCR to seal/attest to different
> +variations of platform details/authorities and user details/authorities. An
> +example of how this can be achieved was presented in the FOSDEM - 2021 talk
> +"Secure Upgrades with DRTM".
> +
> +Resources
> +=========
> +
> +The TrenchBoot project:
> +
> +https://trenchboot.org
> +
> +Secure Launch Specification:
> +
> +https://trenchboot.org/specifications/Secure_Launch/
> +
> +Trusted Computing Group's D-RTM Architecture:
> +
> +https://trustedcomputinggroup.org/wp-content/uploads/TCG_D-RTM_Architecture_v1-0_Published_06172013.pdf
> +
> +TXT documentation in the Intel TXT MLE Development Guide:
> +
> +https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
> +
> +TXT instructions documentation in the Intel SDM Instruction Set volume:
> +
> +https://software.intel.com/en-us/articles/intel-sdm
> +
> +AMD SKINIT documentation in the System Programming manual:
> +
> +https://www.amd.com/system/files/TechDocs/24593.pdf
> +
> +GRUB Secure Launch support:
> +
> +https://github.com/TrenchBoot/grub/tree/grub-sl-fc-38-dlstub
> +
> +FOSDEM 2021: Secure Upgrades with DRTM
> +
> +https://archive.fosdem.org/2021/schedule/event/firmware_suwd/
> +
> +.. [1]
> +    MLE: Measured Launch Environment is the binary runtime that is measured and
> +    then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
> +    requirements for the MLE in detail.
> +
> +.. [2]
> +    ACM: Intel's Authenticated Code Module. This is the 32b bit binary blob that
> +    is run securely by the GETSEC[SENTER] during a measured launch. It is described
> +    in the Intel documentation on TXT and versions for various chipsets are
> +    signed and distributed by Intel.
 
The formatting LGTM, thanks!

Regardless,

Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com>

-- 
An old man doll... just what I always wanted! - Clara

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 143 bytes --]

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 12/14] x86: Secure Launch late initcall platform module
  2023-05-05 19:42     ` Simon Horman
@ 2023-05-08 15:07       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-08 15:07 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 15:42, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:21PM +0000, Ross Philipson wrote:
>> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>>
>> The Secure Launch platform module is a late init module. During the
>> init call, the TPM event log is read and measurements taken in the
>> early boot stub code are located. These measurements are extended
>> into the TPM PCRs using the mainline TPM kernel driver.
>>
>> The platform module also registers the securityfs nodes to allow
>> access to TXT register fields on Intel along with the fetching of
>> and writing events to the late launch TPM log.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
>> Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> 
> Hi Ross,
> 
> a few more items from my side.
> 
> ...
> 
>> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
> 
> ...
> 
>> +/*
>> + * Securityfs exposure
>> + */
>> +struct memfile {
>> +	char *name;
>> +	void *addr;
>> +	size_t size;
>> +};
>> +
>> +static struct memfile sl_evtlog = {"eventlog", 0, 0};
> 
> I don't think the 0 fields are necessary above, memset will zero
> any fields not explicitly set. But if you want to go that way, then
> I think the first one should be NULL, as the addr field is a pointer.
> 
>> +static void *txt_heap;
>> +static struct txt_heap_event_log_pointer2_1_element __iomem *evtlog20;
>> +static DEFINE_MUTEX(sl_evt_log_mutex);
> 
>> +static ssize_t sl_evtlog_read(struct file *file, char __user *buf,
>> +			      size_t count, loff_t *pos)
>> +{
>> +	ssize_t size;
>> +
>> +	if (!sl_evtlog.addr)
>> +		return 0;
>> +
>> +	mutex_lock(&sl_evt_log_mutex);
>> +	size = simple_read_from_buffer(buf, count, pos, sl_evtlog.addr,
>> +				       sl_evtlog.size);
>> +	mutex_unlock(&sl_evt_log_mutex);
>> +
>> +	return size;
>> +}
>> +
>> +static ssize_t sl_evtlog_write(struct file *file, const char __user *buf,
>> +				size_t datalen, loff_t *ppos)
> 
> nit: the line above doesn't align to the '(' on the line before that.
> 
>> +{
>> +	ssize_t result;
>> +	char *data;
>> +
>> +	if (!sl_evtlog.addr)
>> +		return 0;
>> +
>> +	/* No partial writes. */
>> +	result = -EINVAL;
>> +	if (*ppos != 0)
>> +		goto out;
>> +
>> +	data = memdup_user(buf, datalen);
>> +	if (IS_ERR(data)) {
>> +		result = PTR_ERR(data);
>> +		goto out;
>> +	}
>> +
>> +	mutex_lock(&sl_evt_log_mutex);
>> +	if (evtlog20)
>> +		result = tpm20_log_event(evtlog20, sl_evtlog.addr,
>> +					 sl_evtlog.size, datalen, data);
> 
> Sparse says that the type of the first argument of tmp20_log_event is:
> 
> 	struct txt_heap_event_log_pointer2_1_element *
> 
> However, the type of evtlog20 is:
> 
> 	struct txt_heap_event_log_pointer2_1_element __iomem *

I have to look into what is going on here. The TXT heap is just a memory 
range not IO space. I will track this down.

As to all the rest of your comments here, I will fix them.

Thanks
Ross

> 
>> +	else
>> +		result = tpm12_log_event(sl_evtlog.addr, sl_evtlog.size,
>> +					 datalen, data);
>> +	mutex_unlock(&sl_evt_log_mutex);
>> +
>> +	kfree(data);
>> +out:
>> +	return result;
>> +}
> 
> ...
> 
>> +static long slaunch_expose_securityfs(void)
>> +{
>> +	long ret = 0;
>> +	int i;
>> +
>> +	slaunch_dir = securityfs_create_dir("slaunch", NULL);
>> +	if (IS_ERR(slaunch_dir))
>> +		return PTR_ERR(slaunch_dir);
>> +
>> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
>> +		txt_dir = securityfs_create_dir("txt", slaunch_dir);
>> +		if (IS_ERR(txt_dir)) {
>> +			ret = PTR_ERR(txt_dir);
>> +			goto remove_slaunch;
>> +		}
>> +
>> +		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++) {
>> +			txt_entries[i] = securityfs_create_file(
>> +						sl_txt_files[i].name, 0440,
>> +						txt_dir, NULL,
>> +						sl_txt_files[i].fops);
>> +			if (IS_ERR(txt_entries[i])) {
>> +				ret = PTR_ERR(txt_entries[i]);
>> +				goto remove_files;
>> +			}
>> +		}
>> +
> 
> nit: no blank line here.
> 
>> +	}
>> +
>> +	if (sl_evtlog.addr > 0) {
> 
> addr is a pointer. So perhaps:
> 
> 	if (sl_evtlog.addr) {
> 
>> +		event_file = securityfs_create_file(
>> +					sl_evtlog.name, 0440,
>> +					slaunch_dir, NULL,
>> +					&sl_evtlog_ops);
>> +		if (IS_ERR(event_file)) {
>> +			ret = PTR_ERR(event_file);
>> +			goto remove_files;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +
>> +remove_files:
>> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
>> +		while (--i >= 0)
>> +			securityfs_remove(txt_entries[i]);
>> +		securityfs_remove(txt_dir);
>> +	}
>> +remove_slaunch:
>> +	securityfs_remove(slaunch_dir);
>> +
>> +	return ret;
>> +}
> 
> ...
> 
>> +static void slaunch_intel_evtlog(void __iomem *txt)
>> +{
>> +	struct slr_entry_log_info *log_info;
>> +	struct txt_os_mle_data *params;
>> +	struct slr_table *slrt;
>> +	void *os_sinit_data;
>> +	u64 base, size;
>> +
>> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
>> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
>> +
>> +	/* now map TXT heap */
>> +	txt_heap = memremap(base, size, MEMREMAP_WB);
>> +	if (!txt_heap)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap TXT heap\n",
>> +			SL_ERROR_HEAP_MAP);
> 
> nit: These lines are not aligned to the opening '('
> 
>> +
>> +	params = (struct txt_os_mle_data *)txt_os_mle_data_start(txt_heap);
>> +
>> +	/* Get the SLRT and remap it */
>> +	slrt = memremap(params->slrt, sizeof(*slrt), MEMREMAP_WB);
>> +	if (!slrt)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap SLR Table\n",
>> +			SL_ERROR_SLRT_MAP);
>> +	size = slrt->size;
>> +	memunmap(slrt);
>> +
>> +	slrt = memremap(params->slrt, size, MEMREMAP_WB);
>> +	if (!slrt)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap SLR Table\n",
>> +			SL_ERROR_SLRT_MAP);
>> +
>> +	log_info = (struct slr_entry_log_info *)
>> +			slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
>> +	if (!log_info)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap SLR Table\n",
>> +			SL_ERROR_SLRT_MISSING_ENTRY);
>> +
>> +	sl_evtlog.size = log_info->size;
>> +	sl_evtlog.addr = memremap(log_info->addr, log_info->size,
>> +				  MEMREMAP_WB);
>> +	if (!sl_evtlog.addr)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap TPM event log\n",
>> +			SL_ERROR_EVENTLOG_MAP);
>> +
>> +	memunmap(slrt);
>> +
>> +	/* Determine if this is TPM 1.2 or 2.0 event log */
>> +	if (memcmp(sl_evtlog.addr + sizeof(struct tcg_pcr_event),
>> +		    TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
>> +		return; /* looks like it is not 2.0 */
>> +
>> +	/* For TPM 2.0 logs, the extended heap element must be located */
>> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
>> +
> 
> The return type of tmp20_find_lot2_1_element() is:
> 
> 	struct txt_heap_event_log_pointer2_1_element *
> 
> However, the type of evtlog20 is:
> 
> 	struct txt_heap_event_log_pointer2_1_element __iomem *
> 
>> +	evtlog20 = tpm20_find_log2_1_element(os_sinit_data);
>> +
>> +	/*
>> +	 * If this fails, things are in really bad shape. Any attempt to write
>> +	 * events to the log will fail.
>> +	 */
>> +	if (!evtlog20)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to find TPM20 event log element\n",
>> +			SL_ERROR_TPM_INVALID_LOG20);
>> +}
>> +
>> +static void slaunch_tpm20_extend_event(struct tpm_chip *tpm, void __iomem *txt,
>> +				       struct tcg_pcr_event2_head *event)
>> +{
>> +	u16 *alg_id_field = (u16 *)((u8 *)event +
>> +				    sizeof(struct tcg_pcr_event2_head));
>> +	struct tpm_digest *digests;
>> +	u8 *dptr;
>> +	int ret;
>> +	u32 i, j;
>> +
>> +	digests = kcalloc(tpm->nr_allocated_banks, sizeof(*digests),
>> +			  GFP_KERNEL);
>> +	if (!digests)
>> +		slaunch_txt_reset(txt,
>> +			"Failed to allocate array of digests\n",
>> +			SL_ERROR_GENERIC);
>> +
>> +	for (i = 0; i < tpm->nr_allocated_banks; i++)
>> +		digests[i].alg_id = tpm->allocated_banks[i].alg_id;
>> +
>> +
> 
> nit: one blank line is enough.
> 
>> +	/* Early SL code ensured there was a max count of 2 digests */
>> +	for (i = 0; i < event->count; i++) {
>> +		dptr = (u8 *)alg_id_field + sizeof(u16);
>> +
>> +		for (j = 0; j < tpm->nr_allocated_banks; j++) {
>> +			if (digests[j].alg_id != *alg_id_field)
>> +				continue;
>> +
>> +			switch (digests[j].alg_id) {
>> +			case TPM_ALG_SHA256:
>> +				memcpy(&digests[j].digest[0], dptr,
>> +				       SHA256_DIGEST_SIZE);
>> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
>> +					SHA256_DIGEST_SIZE + sizeof(u16));
>> +				break;
>> +			case TPM_ALG_SHA1:
>> +				memcpy(&digests[j].digest[0], dptr,
>> +				       SHA1_DIGEST_SIZE);
>> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
>> +					SHA1_DIGEST_SIZE + sizeof(u16));
>> +			default:
>> +				break;
>> +			}
>> +		}
>> +	}
>> +
>> +	ret = tpm_pcr_extend(tpm, event->pcr_idx, digests);
>> +	if (ret) {
>> +		pr_err("Error extending TPM20 PCR, result: %d\n", ret);
>> +		slaunch_txt_reset(txt,
>> +			"Failed to extend TPM20 PCR\n",
>> +			SL_ERROR_TPM_EXTEND);
>> +	}
>> +
>> +	kfree(digests);
>> +}
>> +
>> +static void slaunch_tpm20_extend(struct tpm_chip *tpm, void __iomem *txt)
>> +{
>> +	struct tcg_pcr_event *event_header;
>> +	struct tcg_pcr_event2_head *event;
>> +	int start = 0, end = 0, size;
>> +
>> +	event_header = (struct tcg_pcr_event *)(sl_evtlog.addr +
>> +						evtlog20->first_record_offset);
> 
> Sparse says that evtlog20 shouldn't be dereferenced because it
> has a __iomem attribute.
> 
>> +
>> +	/* Skip first TPM 1.2 event to get to first TPM 2.0 event */
>> +	event = (struct tcg_pcr_event2_head *)((u8 *)event_header +
>> +						sizeof(struct tcg_pcr_event) +
>> +						event_header->event_size);
>> +
>> +	while ((void  *)event < sl_evtlog.addr + evtlog20->next_record_offset) {
> 
> Ditto.
> 
>> +		size = __calc_tpm2_event_size(event, event_header, false);
>> +		if (!size)
>> +			slaunch_txt_reset(txt,
>> +				"TPM20 invalid event in event log\n",
>> +				SL_ERROR_TPM_INVALID_EVENT);
>> +
>> +		/*
>> +		 * Marker events indicate where the Secure Launch early stub
>> +		 * started and ended adding post launch events.
>> +		 */
>> +		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
>> +			end = 1;
>> +			break;
>> +		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
>> +			start = 1;
>> +			goto next;
>> +		}
>> +
>> +		if (start)
>> +			slaunch_tpm20_extend_event(tpm, txt, event);
>> +
>> +next:
>> +		event = (struct tcg_pcr_event2_head *)((u8 *)event + size);
>> +	}
>> +
>> +	if (!start || !end)
>> +		slaunch_txt_reset(txt,
>> +			"Missing start or end events for extending TPM20 PCRs\n",
>> +			SL_ERROR_TPM_EXTEND);
>> +}
> 
> ...
> 
>> +static void slaunch_pcr_extend(void __iomem *txt)
>> +{
>> +	struct tpm_chip *tpm;
>> +
>> +	tpm = tpm_default_chip();
>> +	if (!tpm)
>> +		slaunch_txt_reset(txt,
>> +			"Could not get default TPM chip\n",
>> +			SL_ERROR_TPM_INIT);
>> +	if (evtlog20)
>> +		slaunch_tpm20_extend(tpm, txt);
>> +	else
>> +		slaunch_tpm12_extend(tpm, txt);
>> +}
>> +
>> +static int __init slaunch_module_init(void)
>> +{
>> +	void __iomem *txt;
>> +
>> +	/* Check to see if Secure Launch happened */
>> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
>> +	    (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT))
> 
> nit: spaces around '|'
>       Likewise elsewhere in this patch.
> 
> 
>> +		return 0;
>> +
>> +	txt = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
>> +		      PAGE_SIZE);
>> +	if (!txt)
>> +		panic("Error ioremap of TXT priv registers\n");
>> +
>> +	/* Only Intel TXT is supported at this point */
>> +	slaunch_intel_evtlog(txt);
>> +
>> +	slaunch_pcr_extend(txt);
>> +
>> +	iounmap(txt);
>> +
>> +	return slaunch_expose_securityfs();
>> +}
> 
> ...


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

* Re: [PATCH v6 12/14] x86: Secure Launch late initcall platform module
@ 2023-05-08 15:07       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-08 15:07 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 15:42, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:21PM +0000, Ross Philipson wrote:
>> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>>
>> The Secure Launch platform module is a late init module. During the
>> init call, the TPM event log is read and measurements taken in the
>> early boot stub code are located. These measurements are extended
>> into the TPM PCRs using the mainline TPM kernel driver.
>>
>> The platform module also registers the securityfs nodes to allow
>> access to TXT register fields on Intel along with the fetching of
>> and writing events to the late launch TPM log.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
>> Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> 
> Hi Ross,
> 
> a few more items from my side.
> 
> ...
> 
>> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
> 
> ...
> 
>> +/*
>> + * Securityfs exposure
>> + */
>> +struct memfile {
>> +	char *name;
>> +	void *addr;
>> +	size_t size;
>> +};
>> +
>> +static struct memfile sl_evtlog = {"eventlog", 0, 0};
> 
> I don't think the 0 fields are necessary above, memset will zero
> any fields not explicitly set. But if you want to go that way, then
> I think the first one should be NULL, as the addr field is a pointer.
> 
>> +static void *txt_heap;
>> +static struct txt_heap_event_log_pointer2_1_element __iomem *evtlog20;
>> +static DEFINE_MUTEX(sl_evt_log_mutex);
> 
>> +static ssize_t sl_evtlog_read(struct file *file, char __user *buf,
>> +			      size_t count, loff_t *pos)
>> +{
>> +	ssize_t size;
>> +
>> +	if (!sl_evtlog.addr)
>> +		return 0;
>> +
>> +	mutex_lock(&sl_evt_log_mutex);
>> +	size = simple_read_from_buffer(buf, count, pos, sl_evtlog.addr,
>> +				       sl_evtlog.size);
>> +	mutex_unlock(&sl_evt_log_mutex);
>> +
>> +	return size;
>> +}
>> +
>> +static ssize_t sl_evtlog_write(struct file *file, const char __user *buf,
>> +				size_t datalen, loff_t *ppos)
> 
> nit: the line above doesn't align to the '(' on the line before that.
> 
>> +{
>> +	ssize_t result;
>> +	char *data;
>> +
>> +	if (!sl_evtlog.addr)
>> +		return 0;
>> +
>> +	/* No partial writes. */
>> +	result = -EINVAL;
>> +	if (*ppos != 0)
>> +		goto out;
>> +
>> +	data = memdup_user(buf, datalen);
>> +	if (IS_ERR(data)) {
>> +		result = PTR_ERR(data);
>> +		goto out;
>> +	}
>> +
>> +	mutex_lock(&sl_evt_log_mutex);
>> +	if (evtlog20)
>> +		result = tpm20_log_event(evtlog20, sl_evtlog.addr,
>> +					 sl_evtlog.size, datalen, data);
> 
> Sparse says that the type of the first argument of tmp20_log_event is:
> 
> 	struct txt_heap_event_log_pointer2_1_element *
> 
> However, the type of evtlog20 is:
> 
> 	struct txt_heap_event_log_pointer2_1_element __iomem *

I have to look into what is going on here. The TXT heap is just a memory 
range not IO space. I will track this down.

As to all the rest of your comments here, I will fix them.

Thanks
Ross

> 
>> +	else
>> +		result = tpm12_log_event(sl_evtlog.addr, sl_evtlog.size,
>> +					 datalen, data);
>> +	mutex_unlock(&sl_evt_log_mutex);
>> +
>> +	kfree(data);
>> +out:
>> +	return result;
>> +}
> 
> ...
> 
>> +static long slaunch_expose_securityfs(void)
>> +{
>> +	long ret = 0;
>> +	int i;
>> +
>> +	slaunch_dir = securityfs_create_dir("slaunch", NULL);
>> +	if (IS_ERR(slaunch_dir))
>> +		return PTR_ERR(slaunch_dir);
>> +
>> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
>> +		txt_dir = securityfs_create_dir("txt", slaunch_dir);
>> +		if (IS_ERR(txt_dir)) {
>> +			ret = PTR_ERR(txt_dir);
>> +			goto remove_slaunch;
>> +		}
>> +
>> +		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++) {
>> +			txt_entries[i] = securityfs_create_file(
>> +						sl_txt_files[i].name, 0440,
>> +						txt_dir, NULL,
>> +						sl_txt_files[i].fops);
>> +			if (IS_ERR(txt_entries[i])) {
>> +				ret = PTR_ERR(txt_entries[i]);
>> +				goto remove_files;
>> +			}
>> +		}
>> +
> 
> nit: no blank line here.
> 
>> +	}
>> +
>> +	if (sl_evtlog.addr > 0) {
> 
> addr is a pointer. So perhaps:
> 
> 	if (sl_evtlog.addr) {
> 
>> +		event_file = securityfs_create_file(
>> +					sl_evtlog.name, 0440,
>> +					slaunch_dir, NULL,
>> +					&sl_evtlog_ops);
>> +		if (IS_ERR(event_file)) {
>> +			ret = PTR_ERR(event_file);
>> +			goto remove_files;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +
>> +remove_files:
>> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
>> +		while (--i >= 0)
>> +			securityfs_remove(txt_entries[i]);
>> +		securityfs_remove(txt_dir);
>> +	}
>> +remove_slaunch:
>> +	securityfs_remove(slaunch_dir);
>> +
>> +	return ret;
>> +}
> 
> ...
> 
>> +static void slaunch_intel_evtlog(void __iomem *txt)
>> +{
>> +	struct slr_entry_log_info *log_info;
>> +	struct txt_os_mle_data *params;
>> +	struct slr_table *slrt;
>> +	void *os_sinit_data;
>> +	u64 base, size;
>> +
>> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
>> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
>> +
>> +	/* now map TXT heap */
>> +	txt_heap = memremap(base, size, MEMREMAP_WB);
>> +	if (!txt_heap)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap TXT heap\n",
>> +			SL_ERROR_HEAP_MAP);
> 
> nit: These lines are not aligned to the opening '('
> 
>> +
>> +	params = (struct txt_os_mle_data *)txt_os_mle_data_start(txt_heap);
>> +
>> +	/* Get the SLRT and remap it */
>> +	slrt = memremap(params->slrt, sizeof(*slrt), MEMREMAP_WB);
>> +	if (!slrt)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap SLR Table\n",
>> +			SL_ERROR_SLRT_MAP);
>> +	size = slrt->size;
>> +	memunmap(slrt);
>> +
>> +	slrt = memremap(params->slrt, size, MEMREMAP_WB);
>> +	if (!slrt)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap SLR Table\n",
>> +			SL_ERROR_SLRT_MAP);
>> +
>> +	log_info = (struct slr_entry_log_info *)
>> +			slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
>> +	if (!log_info)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap SLR Table\n",
>> +			SL_ERROR_SLRT_MISSING_ENTRY);
>> +
>> +	sl_evtlog.size = log_info->size;
>> +	sl_evtlog.addr = memremap(log_info->addr, log_info->size,
>> +				  MEMREMAP_WB);
>> +	if (!sl_evtlog.addr)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap TPM event log\n",
>> +			SL_ERROR_EVENTLOG_MAP);
>> +
>> +	memunmap(slrt);
>> +
>> +	/* Determine if this is TPM 1.2 or 2.0 event log */
>> +	if (memcmp(sl_evtlog.addr + sizeof(struct tcg_pcr_event),
>> +		    TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
>> +		return; /* looks like it is not 2.0 */
>> +
>> +	/* For TPM 2.0 logs, the extended heap element must be located */
>> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
>> +
> 
> The return type of tmp20_find_lot2_1_element() is:
> 
> 	struct txt_heap_event_log_pointer2_1_element *
> 
> However, the type of evtlog20 is:
> 
> 	struct txt_heap_event_log_pointer2_1_element __iomem *
> 
>> +	evtlog20 = tpm20_find_log2_1_element(os_sinit_data);
>> +
>> +	/*
>> +	 * If this fails, things are in really bad shape. Any attempt to write
>> +	 * events to the log will fail.
>> +	 */
>> +	if (!evtlog20)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to find TPM20 event log element\n",
>> +			SL_ERROR_TPM_INVALID_LOG20);
>> +}
>> +
>> +static void slaunch_tpm20_extend_event(struct tpm_chip *tpm, void __iomem *txt,
>> +				       struct tcg_pcr_event2_head *event)
>> +{
>> +	u16 *alg_id_field = (u16 *)((u8 *)event +
>> +				    sizeof(struct tcg_pcr_event2_head));
>> +	struct tpm_digest *digests;
>> +	u8 *dptr;
>> +	int ret;
>> +	u32 i, j;
>> +
>> +	digests = kcalloc(tpm->nr_allocated_banks, sizeof(*digests),
>> +			  GFP_KERNEL);
>> +	if (!digests)
>> +		slaunch_txt_reset(txt,
>> +			"Failed to allocate array of digests\n",
>> +			SL_ERROR_GENERIC);
>> +
>> +	for (i = 0; i < tpm->nr_allocated_banks; i++)
>> +		digests[i].alg_id = tpm->allocated_banks[i].alg_id;
>> +
>> +
> 
> nit: one blank line is enough.
> 
>> +	/* Early SL code ensured there was a max count of 2 digests */
>> +	for (i = 0; i < event->count; i++) {
>> +		dptr = (u8 *)alg_id_field + sizeof(u16);
>> +
>> +		for (j = 0; j < tpm->nr_allocated_banks; j++) {
>> +			if (digests[j].alg_id != *alg_id_field)
>> +				continue;
>> +
>> +			switch (digests[j].alg_id) {
>> +			case TPM_ALG_SHA256:
>> +				memcpy(&digests[j].digest[0], dptr,
>> +				       SHA256_DIGEST_SIZE);
>> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
>> +					SHA256_DIGEST_SIZE + sizeof(u16));
>> +				break;
>> +			case TPM_ALG_SHA1:
>> +				memcpy(&digests[j].digest[0], dptr,
>> +				       SHA1_DIGEST_SIZE);
>> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
>> +					SHA1_DIGEST_SIZE + sizeof(u16));
>> +			default:
>> +				break;
>> +			}
>> +		}
>> +	}
>> +
>> +	ret = tpm_pcr_extend(tpm, event->pcr_idx, digests);
>> +	if (ret) {
>> +		pr_err("Error extending TPM20 PCR, result: %d\n", ret);
>> +		slaunch_txt_reset(txt,
>> +			"Failed to extend TPM20 PCR\n",
>> +			SL_ERROR_TPM_EXTEND);
>> +	}
>> +
>> +	kfree(digests);
>> +}
>> +
>> +static void slaunch_tpm20_extend(struct tpm_chip *tpm, void __iomem *txt)
>> +{
>> +	struct tcg_pcr_event *event_header;
>> +	struct tcg_pcr_event2_head *event;
>> +	int start = 0, end = 0, size;
>> +
>> +	event_header = (struct tcg_pcr_event *)(sl_evtlog.addr +
>> +						evtlog20->first_record_offset);
> 
> Sparse says that evtlog20 shouldn't be dereferenced because it
> has a __iomem attribute.
> 
>> +
>> +	/* Skip first TPM 1.2 event to get to first TPM 2.0 event */
>> +	event = (struct tcg_pcr_event2_head *)((u8 *)event_header +
>> +						sizeof(struct tcg_pcr_event) +
>> +						event_header->event_size);
>> +
>> +	while ((void  *)event < sl_evtlog.addr + evtlog20->next_record_offset) {
> 
> Ditto.
> 
>> +		size = __calc_tpm2_event_size(event, event_header, false);
>> +		if (!size)
>> +			slaunch_txt_reset(txt,
>> +				"TPM20 invalid event in event log\n",
>> +				SL_ERROR_TPM_INVALID_EVENT);
>> +
>> +		/*
>> +		 * Marker events indicate where the Secure Launch early stub
>> +		 * started and ended adding post launch events.
>> +		 */
>> +		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
>> +			end = 1;
>> +			break;
>> +		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
>> +			start = 1;
>> +			goto next;
>> +		}
>> +
>> +		if (start)
>> +			slaunch_tpm20_extend_event(tpm, txt, event);
>> +
>> +next:
>> +		event = (struct tcg_pcr_event2_head *)((u8 *)event + size);
>> +	}
>> +
>> +	if (!start || !end)
>> +		slaunch_txt_reset(txt,
>> +			"Missing start or end events for extending TPM20 PCRs\n",
>> +			SL_ERROR_TPM_EXTEND);
>> +}
> 
> ...
> 
>> +static void slaunch_pcr_extend(void __iomem *txt)
>> +{
>> +	struct tpm_chip *tpm;
>> +
>> +	tpm = tpm_default_chip();
>> +	if (!tpm)
>> +		slaunch_txt_reset(txt,
>> +			"Could not get default TPM chip\n",
>> +			SL_ERROR_TPM_INIT);
>> +	if (evtlog20)
>> +		slaunch_tpm20_extend(tpm, txt);
>> +	else
>> +		slaunch_tpm12_extend(tpm, txt);
>> +}
>> +
>> +static int __init slaunch_module_init(void)
>> +{
>> +	void __iomem *txt;
>> +
>> +	/* Check to see if Secure Launch happened */
>> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
>> +	    (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT))
> 
> nit: spaces around '|'
>       Likewise elsewhere in this patch.
> 
> 
>> +		return 0;
>> +
>> +	txt = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
>> +		      PAGE_SIZE);
>> +	if (!txt)
>> +		panic("Error ioremap of TXT priv registers\n");
>> +
>> +	/* Only Intel TXT is supported at this point */
>> +	slaunch_intel_evtlog(txt);
>> +
>> +	slaunch_pcr_extend(txt);
>> +
>> +	iounmap(txt);
>> +
>> +	return slaunch_expose_securityfs();
>> +}
> 
> ...


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-05 16:34     ` Simon Horman
@ 2023-05-09 16:09       ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-09 16:09 UTC (permalink / raw)
  To: Simon Horman, Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 12:34, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:15PM +0000, Ross Philipson wrote:
>> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>>
>> The SHA algorithms are necessary to measure configuration information into
>> the TPM as early as possible before using the values. This implementation
>> uses the established approach of #including the SHA libraries directly in
>> the code since the compressed kernel is not uncompressed at this point.
>>
>> The SHA code here has its origins in the code from the main kernel:
>>
>> commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")
>>
>> That code could not be pulled directly into the setup portion of the
>> compressed kernel because of other dependencies it pulls in. The result
>> is this is a modified copy of that code that still leverages the core
>> SHA algorithms.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   arch/x86/boot/compressed/Makefile       |  2 +
>>   arch/x86/boot/compressed/early_sha1.c   | 97 +++++++++++++++++++++++++++++++++
>>   arch/x86/boot/compressed/early_sha1.h   | 17 ++++++
>>   arch/x86/boot/compressed/early_sha256.c |  7 +++
>>   lib/crypto/sha1.c                       |  4 ++
>>   lib/crypto/sha256.c                     |  8 +++
>>   6 files changed, 135 insertions(+)
>>   create mode 100644 arch/x86/boot/compressed/early_sha1.c
>>   create mode 100644 arch/x86/boot/compressed/early_sha1.h
>>   create mode 100644 arch/x86/boot/compressed/early_sha256.c
>>
>> diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
>> index 6b6cfe6..1d327d4 100644
>> --- a/arch/x86/boot/compressed/Makefile
>> +++ b/arch/x86/boot/compressed/Makefile
>> @@ -112,6 +112,8 @@ vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
>>   vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
>>   vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
>>   
>> +vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/early_sha1.o $(obj)/early_sha256.o
>> +
>>   $(obj)/vmlinux: $(vmlinux-objs-y) FORCE
>>   	$(call if_changed,ld)
>>   
>> diff --git a/arch/x86/boot/compressed/early_sha1.c b/arch/x86/boot/compressed/early_sha1.c
>> new file mode 100644
>> index 0000000..524ec23
>> --- /dev/null
>> +++ b/arch/x86/boot/compressed/early_sha1.c
>> @@ -0,0 +1,97 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2022 Apertus Solutions, LLC.
>> + */
>> +
>> +#include <linux/init.h>
>> +#include <linux/linkage.h>
>> +#include <linux/string.h>
>> +#include <asm/boot.h>
>> +#include <asm/unaligned.h>
>> +
>> +#include "early_sha1.h"
>> +
>> +#define SHA1_DISABLE_EXPORT
> 
> Hi Ross,
> 
> I could be mistaken, but it seems to me that *_DISABLE_EXPORT
> is a mechanism of this patch to disable exporting symbols
> (use of EXPORT_SYMBOL), at compile time.
> 
> If so, this doesn't strike me as something that should be part of upstream
> kernel code.  Could you consider dropping this part of the patch?

Greetings Simon,

This was patterned after the move of sha256 to /lib. Upon re-inspection, 
it appears this has since been updated to use the __DISABLE_EXPORTS 
CFLAG mechanism of EXPORT_SYMBOL as a conditionally included rule in the 
Makefile where the desire to disable exporting is wanted. We will update 
this patch to follow the same pattern.

V/r,
Daniel P. Smith

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-09 16:09       ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-09 16:09 UTC (permalink / raw)
  To: Simon Horman, Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/5/23 12:34, Simon Horman wrote:
> On Thu, May 04, 2023 at 02:50:15PM +0000, Ross Philipson wrote:
>> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>>
>> The SHA algorithms are necessary to measure configuration information into
>> the TPM as early as possible before using the values. This implementation
>> uses the established approach of #including the SHA libraries directly in
>> the code since the compressed kernel is not uncompressed at this point.
>>
>> The SHA code here has its origins in the code from the main kernel:
>>
>> commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")
>>
>> That code could not be pulled directly into the setup portion of the
>> compressed kernel because of other dependencies it pulls in. The result
>> is this is a modified copy of that code that still leverages the core
>> SHA algorithms.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   arch/x86/boot/compressed/Makefile       |  2 +
>>   arch/x86/boot/compressed/early_sha1.c   | 97 +++++++++++++++++++++++++++++++++
>>   arch/x86/boot/compressed/early_sha1.h   | 17 ++++++
>>   arch/x86/boot/compressed/early_sha256.c |  7 +++
>>   lib/crypto/sha1.c                       |  4 ++
>>   lib/crypto/sha256.c                     |  8 +++
>>   6 files changed, 135 insertions(+)
>>   create mode 100644 arch/x86/boot/compressed/early_sha1.c
>>   create mode 100644 arch/x86/boot/compressed/early_sha1.h
>>   create mode 100644 arch/x86/boot/compressed/early_sha256.c
>>
>> diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
>> index 6b6cfe6..1d327d4 100644
>> --- a/arch/x86/boot/compressed/Makefile
>> +++ b/arch/x86/boot/compressed/Makefile
>> @@ -112,6 +112,8 @@ vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
>>   vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
>>   vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
>>   
>> +vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/early_sha1.o $(obj)/early_sha256.o
>> +
>>   $(obj)/vmlinux: $(vmlinux-objs-y) FORCE
>>   	$(call if_changed,ld)
>>   
>> diff --git a/arch/x86/boot/compressed/early_sha1.c b/arch/x86/boot/compressed/early_sha1.c
>> new file mode 100644
>> index 0000000..524ec23
>> --- /dev/null
>> +++ b/arch/x86/boot/compressed/early_sha1.c
>> @@ -0,0 +1,97 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2022 Apertus Solutions, LLC.
>> + */
>> +
>> +#include <linux/init.h>
>> +#include <linux/linkage.h>
>> +#include <linux/string.h>
>> +#include <asm/boot.h>
>> +#include <asm/unaligned.h>
>> +
>> +#include "early_sha1.h"
>> +
>> +#define SHA1_DISABLE_EXPORT
> 
> Hi Ross,
> 
> I could be mistaken, but it seems to me that *_DISABLE_EXPORT
> is a mechanism of this patch to disable exporting symbols
> (use of EXPORT_SYMBOL), at compile time.
> 
> If so, this doesn't strike me as something that should be part of upstream
> kernel code.  Could you consider dropping this part of the patch?

Greetings Simon,

This was patterned after the move of sha256 to /lib. Upon re-inspection, 
it appears this has since been updated to use the __DISABLE_EXPORTS 
CFLAG mechanism of EXPORT_SYMBOL as a conditionally included rule in the 
Makefile where the desire to disable exporting is wanted. We will update 
this patch to follow the same pattern.

V/r,
Daniel P. Smith

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-10  1:21     ` Eric Biggers
  -1 siblings, 0 replies; 200+ messages in thread
From: Eric Biggers @ 2023-05-10  1:21 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:15PM +0000, Ross Philipson wrote:
> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
> 
> The SHA algorithms are necessary to measure configuration information into
> the TPM as early as possible before using the values. This implementation
> uses the established approach of #including the SHA libraries directly in
> the code since the compressed kernel is not uncompressed at this point.
> 
> The SHA code here has its origins in the code from the main kernel:
> 
> commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")
> 
> That code could not be pulled directly into the setup portion of the
> compressed kernel because of other dependencies it pulls in. The result
> is this is a modified copy of that code that still leverages the core
> SHA algorithms.
> 
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>

SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
now?

And if you absolutely MUST use SHA-1 despite it being insecure, please at least
don't obfuscate it by calling it simply "SHA".

- Eric

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-10  1:21     ` Eric Biggers
  0 siblings, 0 replies; 200+ messages in thread
From: Eric Biggers @ 2023-05-10  1:21 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:15PM +0000, Ross Philipson wrote:
> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
> 
> The SHA algorithms are necessary to measure configuration information into
> the TPM as early as possible before using the values. This implementation
> uses the established approach of #including the SHA libraries directly in
> the code since the compressed kernel is not uncompressed at this point.
> 
> The SHA code here has its origins in the code from the main kernel:
> 
> commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")
> 
> That code could not be pulled directly into the setup portion of the
> compressed kernel because of other dependencies it pulls in. The result
> is this is a modified copy of that code that still leverages the core
> SHA algorithms.
> 
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>

SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
now?

And if you absolutely MUST use SHA-1 despite it being insecure, please at least
don't obfuscate it by calling it simply "SHA".

- Eric

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
  2023-05-06  8:48     ` Bagas Sanjaya
@ 2023-05-10 15:41       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-10 15:41 UTC (permalink / raw)
  To: Bagas Sanjaya, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, kexec, linux-efi, iommu
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On 5/6/23 04:48, Bagas Sanjaya wrote:
> On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
>> +=====================================
>> +System Launch Integrity documentation
>> +=====================================
>> +
>> +.. toctree::
> 
> By convention, doc toctree have 2-level depth (only page title and
> first-level headings are visible). You may consider adding
> `:maxdepth: 2` option.

Will do.

> 
>> diff --git a/Documentation/security/launch-integrity/principles.rst b/Documentation/security/launch-integrity/principles.rst
>> new file mode 100644
>> index 0000000..73cf063
>> --- /dev/null
>> +++ b/Documentation/security/launch-integrity/principles.rst
>> @@ -0,0 +1,313 @@
>> +=======================
>> +System Launch Integrity
>> +=======================
>> +
>> +This document serves to establish a common understanding of what is system
>> +launch, the integrity concern for system launch, and why using a Root of Trust
>> +(RoT) from a Dynamic Launch may be desired. Through out this document
>> +terminology from the Trusted Computing Group (TCG) and National Institue for
>> +Science and Technology (NIST) is used to ensure a vendor nutrual language is
>> +used to describe and reference security-related concepts.
>> +
>> +System Launch
>> +=============
>> +
>> +There is a tendency to only consider the classical power-on boot as the only
>> +means to launch an Operating System (OS) on a computer system, but in fact most
>> +modern processors support two methods to launch the system. To provide clarity a
>> +common definition of a system launch should be established. This definition is
>> +that a during a single power life cycle of a system, a System Launch consists
>> +of an initialization event, typically in hardware, that is followed by an
>> +executing software payload that takes the system from the initialized state to
>> +a running state. Driven by the Trusted Computing Group (TCG) architecture,
>> +modern processors are able to support two methods to launch a system, these two
>> +types of system launch are known as Static Launch and Dynamic Launch.
>> +
>> +Static Launch
>> +-------------
>> +
>> +Static launch is the system launch associated with the power cycle of the CPU.
>> +Thus static launch refers to the classical power-on boot where the
>> +initialization event is the release of the CPU from reset and the system
>> +firmware is the software payload that brings the system up to a running state.
>> +Since static launch is the system launch associated with the beginning of the
>> +power lifecycle of a system, it is therefore a fixed, one-time system launch.
>> +It is because of this that static launch is referred to and thought of as being
>> +"static".
>> +
>> +Dynamic Launch
>> +--------------
>> +
>> +Modern CPUs architectures provides a mechanism to re-initialize the system to a
>> +"known good" state without requiring a power event. This re-initialization
>> +event is the event for a dynamic launch and is referred to as the Dynamic
>> +Launch Event (DLE). The DLE functions by accepting a software payload, referred
>> +to as the Dynamic Configuration Environment (DCE), that execution is handed to
>> +after the DLE is invoked. The DCE is responsible for bringing the system back
>> +to a running state. Since the dynamic launch is not tied to a power event like
>> +the static launch, this enables a dynamic launch to be initiated at any time
>> +and multiple times during a single power life cycle. This dynamism is the
>> +reasoning behind referring to this system launch as being dynamic.
>> +
>> +Because a dynamic launch can be conducted at any time during a single power
>> +life cycle, they are classified into one of two types, an early launch or a
>> +late launch.
>> +
>> +:Early Launch: When a dynamic launch is used as a transition from a static
>> +   launch chain to the final Operating System.
>> +
>> +:Late Launch: The usage of a dynamic launch by an executing Operating System to
>> +   transition to a “known good” state to perform one or more operations, e.g. to
>> +   launch into a new Operating System.
>> +
>> +System Integrity
>> +================
>> +
>> +A computer system can be considered a collection of mechanisms that work
>> +together to produce a result. The assurance that the mechanisms are functioning
>> +correctly and producing the expected result is the integrity of the system. To
>> +ensure a system's integrity there are a subset of these mechanisms, commonly
>> +referred to as security mechanisms, that are present to help ensure the system
>> +produces the expected result or at least detect the potential of an unexpected
>> +result may have happened. Since the security mechanisms are relied upon to
>> +ensue the integrity of the system, these mechanisms are trusted. Upon
>> +inspection these security mechanisms each have a set of properties and these
>> +properties can be evaluated to determine how susceptible a mechanism might be
>> +to failure. This assessment is referred to as the Strength of Mechanism and for
>> +trusted mechanism enables for the trustworthiness of that mechanism to be
>> +quantified.
>> +
>> +For software systems there are two system states for which the integrity is
>> +critical, when the software is loaded into memory and when the software is
>> +executing on the hardware. Ensuring that the expected software is load into
>> +memory is referred to as load-time integrity while ensuring that the software
>> +executing is the expected software is the runtime integrity of that software.
>> +
>> +Load-time Integrity
>> +-------------------
>> +
>> +It is critical to understand what load-time integrity establishes about a
>> +system and what is assumed, i.e. what is being trusted. Load-time integrity is
>> +when a trusted entity, i.e. an entity with an assumed integrity, takes an
>> +action to assess an entity being loaded into memory before it is used. A
>> +variety of mechanisms may be used to conduct the assessment, each with
>> +different properties. A particular property is whether the mechanism creates an
>> +evidence of the assessment. Often either cryptographic signature checking or
>> +hashing are the common assessment operations used.
>> +
>> +A signature checking assessment functions by requiring a representation of the
>> +accepted authorities and uses those representations to assess if the entity has
>> +been signed by an accepted authority. The benefit to this process is that
>> +assessment process includes an adjudication of the assessment. The drawbacks
>> +are that 1) the adjudication is susceptible to tampering by the Trusted
>> +Computing Base (TCB), 2) there is no evidence to assert that an untampered
>> +adjudication was completed, and 3) the system must be an active participant in
>> +the key management infrastructure.
>> +
>> +A cryptographic hashing assessment does not adjudicate the assessment but
>> +instead generates evidence of the assessment to be adjudicated independently.
>> +The benefits to this approach is that the assessment may be simple such that it
>> +is able to be implemented as an immutable mechanism, e.g. in hardware.
>> +Additionally it is possible for the adjudication to be conducted where it
>> +cannot be tampered with by the TCB. The drawback is that a compromised
>> +environment will be allowed to execute until an adjudication can be completed.
>> +
>> +Ultimately load-time integrity provides confidence that the correct entity was
>> +loaded and in the absence of a run-time integrity mechanism assumes, i.e
>> +trusts, that the entity will never become corrupted.
>> +
>> +Runtime Integrity
>> +-----------------
>> +
>> +Runtime integrity in the general sense is when a trusted entity makes an
>> +assessment of an entity at any point in time during the assessed entity's
>> +execution. A more concrete explanation is the taking of an integrity assessment
>> +of an active process executing on the system at any point during the process'
>> +execution. Often the load-time integrity of an operating system's user-space,
>> +i.e. the operating environment, is confused to be the runtime integrity of the
>> +system since it is an integrity assessment of the "runtime" software. The
>> +reality is that actual runtime integrity is a very difficult problem and thus
>> +not very many solutions are public and/or available. One example of a runtime
>> +integrity solution would be John Hopkins Advanced Physics Labratory's (APL)
>> +Linux Kernel Integrity Module (LKIM).
>> +
>> +Trust Chains
>> +============
>> +
>> +Bulding upon the understanding of security mechanisms to establish load-time
>> +integrity of an entity, it is possible to chain together load-time integrity
>> +assessments to establish the integrity of the whole system. This process is
>> +known as transitive trust and provides the concept of building a chain of
>> +load-time integrity assessments, commonly referred to as a trust chain. These
>> +assessments may be used to adjudicate the load-time integrity of the whole
>> +system. This trust chain is started by a trusted entity that does the first
>> +assessment. This first entity is referred to as the Root of Trust(RoT) with the
>> +entities name being derived from the mechanism used for the assessment, i.e.
>> +RoT for Verification (RTV) and RoT for Measurement (RTM).
>> +
>> +A trust chain is itself a mechanism, specifically a mechanism of mechanisms,
>> +and therefore it too has a Strength of Mechanism. The factors that contribute
>> +to a trust chain's strength are,
>> +
>> +  - The strength of the chain's RoT
>> +  - The strength of each member of the trust chain
>> +  - The length, i.e. the number of members, of the chain
>> +
>> +Therefore to provide the strongest trust chains, they should start with a
>> +strong RoT and should consist of members being of low complexity and minimizing
>> +the number of members participating as is possible. In a more colloquial sense,
>> +a trust chain is only as strong as it weakests link and more links increase
>> +the probability of a weak link.
>> +
>> +Dynamic Launch Components
>> +=========================
>> +
>> +The TCG architecture for dynamic launch is composed of a component series that
>> +are used to setup and then carry out the launch. These components work together
>> +to construct a RTM trust chain that is rooted in the dynamic launch and thus
>> +commonly referred to as the Dynamic Root of Trust for Measurement (DRTM) chain.
>> +
>> +What follows is a brief explanation of each component in execution order. A
>> +subset of these components are what establishes the dynamic launch's trust
>> +chain.
>> +
>> +Dynamic Configuration Environment Preamble
>> +------------------------------------------
>> +
>> +The Dynamic Configuration Environment (DCE) Preamble is responsible for setting
>> +up the system environment in preparation for a dynamic launch. The DCE Preamble
>> +is not a part of the DRTM trust chain.
>> +
>> +Dynamic Launch Event
>> +--------------------
>> +
>> +The dynamic launch event is the event, typically a CPU instruction, that triggers
>> +the system's dynamic launch mechanism to begin the launch. The dynamic launch
>> +mechanism is also the RoT for the DRTM trust chain.
>> +
>> +Dynamic Configuration Environment
>> +---------------------------------
>> +
>> +The dynamic launch mechanism may have resulted in a reset of a portion of the
>> +system. To bring the system back to an adequate state for system software the
>> +dynamic launch will hand over control to the DCE. Prior to handing over this
>> +control, the dynamic launch will measure the DCE. Once the DCE is complete it
>> +will proceed to measure and then execute the Dynamic Launch Measured
>> +Environment (DLME).
>> +
>> +Dynamic Launch Measured Environment
>> +-----------------------------------
>> +
>> +The DLME is the first system kernel to have control of the system but may not
>> +be the last. Depending on the usage and configuration, the DLME may be the
>> +final/target operating system or it may be a boot loader that will load the
>> +final/target operating system.
>> +
>> +Why DRTM
>> +========
>> +
>> +It is a fact that DRTM increases the load-time integrity of the system by
>> +providing a trust chain that has an immutable hardware RoT, uses a limited
>> +number of small, special purpose code to establish the trust chain that starts
>> +the target operating system. As mentioned in the Trust Chain section, these are
>> +the main three factors in driving up the strength of a trust chain. As can been
>> +seen by the BootHole exploit, which in fact did not effect the integrity of
>> +DRTM solutions, the sophistication of attacks targeting system launch is at an
>> +all time high. There is no reason a system should not employ every integrity
>> +measure hardware makes available. This is the crux of a defense-in-depth
>> +approach to system security. In the past the now closed SMI gap was often
>> +pointed to as invalidating DRTM, which in fact was nothing but a strawman
>> +argument. As has continued to be demonstrated, if/when SMM is corrupted it can
>> +always circumvent all load-time integrity, SRTM and DRTM, because it is a
>> +run-time integrity problem. Regardless, Intel and AMD have both deployed
>> +runtime integrity for SMI and SMM which is tied directly to DRTM such that this
>> +perceived deficiency is now non-existent and the world is moving forward with
>> +an expectation that DRTM must be present.
>> +
>> +Glossary
>> +========
>> +
>> +.. glossary::
>> +  integrity
>> +    Guarding against improper information modification or destruction, and
>> +    includes ensuring information non-repudiation and authenticity.
>> +
>> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
>> +
>> +  mechanism
>> +    A process or system that is used to produce a particular result.
>> +
>> +    - NIST Special Publication 800-160 (VOLUME 1 ) - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-160v1.pdf
>> +
>> +  risk
>> +    A measure of the extent to which an entity is threatened by a potential
>> +    circumstance or event, and typically a function of: (i) the adverse impacts
>> +    that would arise if the circumstance or event occurs; and (ii) the
>> +    likelihood of occurrence.
>> +
>> +    - NIST SP 800-30 Rev. 1 - https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-30r1.pdf
>> +
>> +  security mechanism
>> +    A device or function designed to provide one or more security services
>> +    usually rated in terms of strength of service and assurance of the design.
>> +
>> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
>> +
>> +  Strength of Mechanism
>> +    A scale for measuring the relative strength of a security mechanism
>> +
>> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
>> +
>> +  transitive trust
>> +    Also known as "Inductive Trust", in this process a Root of Trust gives a
>> +    trustworthy description of a second group of functions. Based on this
>> +    description, an interested entity can determine the trust it is to place in
>> +    this second group of functions. If the interested entity determines that
>> +    the trust level of the second group of functions is acceptable, the trust
>> +    boundary is extended from the Root of Trust to include the second group of
>> +    functions. In this case, the process can be iterated. The second group of
>> +    functions can give a trustworthy description of the third group of
>> +    functions, etc. Transitive trust is used to provide a trustworthy
>> +    description of platform characteristics, and also to prove that
>> +    non-migratable keys are non-migratable
>> +
>> +    - TCG Glossary - https://trustedcomputinggroup.org/wp-content/uploads/TCG-Glossary-V1.1-Rev-1.0.pdf
>> +
>> +  trust
>> +    The confidence one element has in another that the second element will
>> +    behave as expected`
>> +
>> +    - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
>> +
>> +  trust anchor
>> +    An authoritative entity for which trust is assumed.
>> +
>> +    - NIST SP 800-57 Part 1 Rev. 5 - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf
>> +
>> +  trusted
>> +    An element that another element relies upon to fulfill critical
>> +    requirements on its behalf.
>> +
>> +    - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
>> +
>> +  trusted computing base (TCB)
>> +    Totality of protection mechanisms within a computer system, including
>> +    hardware, firmware, and software, the combination responsible for enforcing
>> +    a security policy.
>> +
>> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
>> +
>> +  trusted computer system
>> +    A system that has the necessary security functions and assurance that the
>> +    security policy will be enforced and that can process a range of
>> +    information sensitivities (i.e. classified, controlled unclassified
>> +    information (CUI), or unclassified public information) simultaneously.
>> +
>> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
>> +
>> +  trustworthiness
>> +    The attribute of a person or enterprise that provides confidence to others
>> +    of the qualifications, capabilities, and reliability of that entity to
>> +    perform specific tasks and fulfill assigned responsibilities.
>> +
>> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
>> diff --git a/Documentation/security/launch-integrity/secure_launch_details.rst b/Documentation/security/launch-integrity/secure_launch_details.rst
>> new file mode 100644
>> index 0000000..2e71543
>> --- /dev/null
>> +++ b/Documentation/security/launch-integrity/secure_launch_details.rst
>> @@ -0,0 +1,564 @@
>> +===================================
>> +Secure Launch Config and Interfaces
>> +===================================
>> +
>> +Configuration
>> +=============
>> +
>> +The settings to enable Secure Launch using Kconfig are under::
>> +
>> +  "Processor type and features" --> "Secure Launch support"
>> +
>> +A kernel with this option enabled can still be booted using other supported
>> +methods.
>> +
>> +To reduce the Trusted Computing Base (TCB) of the MLE [1]_, the build
>> +configuration should be pared down as narrowly as one's use case allows.
>> +The fewer drivers (less active hardware) and features reduces the attack
>> +surface. E.g. in the extreme, the MLE could only have local disk access
>> +and no other hardware support. Or only network access for remote attestation.
>> +
>> +It is also desirable if possible to embed the initrd used with the MLE kernel
>> +image to reduce complexity.
>> +
>> +The following are a few important configuration necessities to always consider:
>> +
>> +KASLR Configuration
>> +-------------------
>> +
>> +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
>> +built with KASLR disabled::
>> +
>> +  "Processor type and features" -->
>> +      "Build a relocatable kernel" -->
>> +          "Randomize the address of the kernel image (KASLR) [ ]"
>> +
>> +This unsets the Kconfig value CONFIG_RANDOMIZE_BASE.
>> +
>> +If not possible, KASLR must be disabled on the kernel command line when doing
>> +a Secure Launch as follows::
>> +
>> +  nokaslr
>> +
>> +IOMMU Configuration
>> +-------------------
>> +
>> +When doing a Secure Launch, the IOMMU should always be enabled and the drivers
>> +loaded. However, IOMMU passthrough mode should never be used. This leaves the
>> +MLE completely exposed to DMA after the PMR's [2]_ are disabled. The current default
>> +mode is to use IOMMU in lazy translated mode but strict translated mode is the preferred
>> +IOMMU mode and this should be selected in the build configuration::
>> +
>> +  "Device Drivers" -->
>> +      "IOMMU Hardware Support" -->
>> +          "IOMMU default domain type" -->
>> +              "(X) Translated - Strict"
>> +
>> +In addition, the Intel IOMMU should be on by default. The following sets this as the
>> +default in the build configuration::
>> +
>> +  "Device Drivers" -->
>> +      "IOMMU Hardware Support" -->
>> +          "Support for Intel IOMMU using DMA Remapping Devices [*]"
>> +
>> +and::
>> +
>> +  "Device Drivers" -->
>> +      "IOMMU Hardware Support" -->
>> +          "Support for Intel IOMMU using DMA Remapping Devices [*]" -->
>> +              "Enable Intel DMA Remapping Devices by default  [*]"
>> +
>> +It is recommended that no other command line options should be set to override
>> +the defaults above.
>> +
>> +Secure Launch Resource Table
>> +============================
>> +
>> +The Secure Launch Resource Table (SLRT) is a platform-agnostic, standard format
>> +for providing information for the pre-launch environment and to pass
>> +information to the post-launch environment. The table is populated by one or
>> +more bootloaders in the boot chain and used by Secure Launch on how to setup
>> +the environment during post-launch. The details for the SLRT are documented
>> +in the TrenchBoot Secure Launch Specifcation [3]_.
>> +
>> +Intel TXT Interface
>> +===================
>> +
>> +The primary interfaces between the various components in TXT are the TXT MMIO
>> +registers and the TXT heap. The MMIO register banks are described in Appendix B
>> +of the TXT MLE [1]_ Development Guide.
>> +
>> +The TXT heap is described in Appendix C of the TXT MLE [1]_ Development
>> +Guide. Most of the TXT heap is predefined in the specification. The heap is
>> +initialized by firmware and the pre-launch environment and is subsequently used
>> +by the SINIT ACM. One section, called the OS to MLE Data Table, is reserved for
>> +software to define. This table is set up per the recommendation detailed in
>> +Appendix B of the TrenchBoot Secure Launch Specification::
>> +
>> +        /*
>> +         * Secure Launch defined OS/MLE TXT Heap table
>> +         */
>> +        struct txt_os_mle_data {
>> +                u32 version;
>> +                u32 boot_params_addr;
>> +                struct slr_table *slrt;
>> +                u64 txt_info;
>> +                u32 ap_wake_block;
>> +                u32 ap_wake_block_size;
>> +                u8 mle_scratch[64];
>> +        } __packed;
>> +
>> +Description of structure:
>> +
>> +=====================  ========================================================================
>> +Field                  Use
>> +=====================  ========================================================================
>> +version                Structure version, current value 1
>> +boot_params_addr       Physical base address of the Linux boot parameters
>> +slrt                   Physical address of the Secure Launch Resource Table
>> +txt_info               Pointer into the SLRT for easily locating TXT specific table
>> +ap_wake_block          Physical address of the block of memory for parking APs after a launch
>> +ap_wake_block_size     Size of the AP wake block
>> +mle_scratch            Scratch area used post-launch by the MLE kernel. Fields:
>> +
>> +                        - SL_SCRATCH_AP_EBX area to share %ebx base pointer among CPUs
>> +                        - SL_SCRATCH_AP_JMP_OFFSET offset to abs. ljmp fixup location for APs
>> +=====================  ========================================================================
>> +
>> +Error Codes
>> +-----------
>> +
>> +The TXT specification defines the layout for TXT 32 bit error code values.
>> +The bit encodings indicate where the error originated (e.g. with the CPU,
>> +in the SINIT ACM, in software). The error is written to a sticky TXT
>> +register that persists across resets called TXT.ERRORCODE (see the TXT
>> +MLE Development Guide). The errors defined by the Secure Launch feature are
>> +those generated in the MLE software. They have the format::
>> +
>> +  0xc0008XXX
>> +
>> +The low 12 bits are free for defining the following Secure Launch specific
>> +error codes.
>> +
>> +======  ================
>> +Name:   SL_ERROR_GENERIC
>> +Value:  0xc0008001
>> +======  ================
>> +
>> +Description:
>> +
>> +Generic catch all error. Currently unused.
>> +
>> +======  =================
>> +Name:   SL_ERROR_TPM_INIT
>> +Value:  0xc0008002
>> +======  =================
>> +
>> +Description:
>> +
>> +The Secure Launch code failed to get an access to the TPM hardware interface.
>> +This is most likely to due to misconfigured hardware or kernel. Ensure the
>> +TPM chip is enabled and the kernel TPM support is built in (it should not be
>> +built as a module).
>> +
>> +======  ==========================
>> +Name:   SL_ERROR_TPM_INVALID_LOG20
>> +Value:  0xc0008003
>> +======  ==========================
>> +
>> +Description:
>> +
>> +The Secure Launch code failed to find a valid event log descriptor for TPM
>> +version 2.0 or the event log descriptor is malformed. Usually this indicates
>> +that incompatible versions of the pre-launch environment and the MLE kernel.
>> +The pre-launch environment and the kernel share a structure in the TXT heap and
>> +if this structure (the OS-MLE table) is mismatched, this error is often seen.
>> +This TXT heap area is setup by the pre-launch environment so the issue may
>> +originate there. It could be the sign of an attempted attack.
>> +
>> +======  ===========================
>> +Name:   SL_ERROR_TPM_LOGGING_FAILED
>> +Value:  0xc0008004
>> +======  ===========================
>> +
>> +Description:
>> +
>> +There was a failed attempt to write a TPM event to the event log early in the
>> +Secure Launch process. This is likely the result of a malformed TPM event log
>> +buffer. Formatting of the event log buffer information is done by the
>> +pre-launch environment so the issue most likely originates there.
>> +
>> +======  ============================
>> +Name:   SL_ERROR_REGION_STRADDLE_4GB
>> +Value:  0xc0008005
>> +======  ============================
>> +
>> +Description:
>> +
>> +During early validation a buffer or region was found to straddle the 4GB
>> +boundary. Because of the way TXT does DMA memory protection, this is an
>> +unsafe configuration and is flagged as an error. This is most likely a
>> +configuration issue in the pre-launch environment. It could also be the sign of
>> +an attempted attack.
>> +
>> +======  ===================
>> +Name:   SL_ERROR_TPM_EXTEND
>> +Value:  0xc0008006
>> +======  ===================
>> +
>> +Description:
>> +
>> +There was a failed attempt to extend a TPM PCR in the Secure Launch platform
>> +module. This is most likely to due to misconfigured hardware or kernel. Ensure
>> +the TPM chip is enabled and the kernel TPM support is built in (it should not
>> +be built as a module).
>> +
>> +======  ======================
>> +Name:   SL_ERROR_MTRR_INV_VCNT
>> +Value:  0xc0008007
>> +======  ======================
>> +
>> +Description:
>> +
>> +During early Secure Launch validation an invalid variable MTRR count was found.
>> +The pre-launch environment passes a number of MSR values to the MLE to restore
>> +including the MTRRs. The values are restored by the Secure Launch early entry
>> +point code. After measuring the values supplied by the pre-launch environment,
>> +a discrepancy was found validating the values. It could be the sign of an
>> +attempted attack.
>> +
>> +======  ==========================
>> +Name:   SL_ERROR_MTRR_INV_DEF_TYPE
>> +Value:  0xc0008008
>> +======  ==========================
>> +
>> +Description:
>> +
>> +During early Secure Launch validation an invalid default MTRR type was found.
>> +See SL_ERROR_MTRR_INV_VCNT for more details.
>> +
>> +======  ======================
>> +Name:   SL_ERROR_MTRR_INV_BASE
>> +Value:  0xc0008009
>> +======  ======================
>> +
>> +Description:
>> +
>> +During early Secure Launch validation an invalid variable MTRR base value was
>> +found. See SL_ERROR_MTRR_INV_VCNT for more details.
>> +
>> +======  ======================
>> +Name:   SL_ERROR_MTRR_INV_MASK
>> +Value:  0xc000800a
>> +======  ======================
>> +
>> +Description:
>> +
>> +During early Secure Launch validation an invalid variable MTRR mask value was
>> +found. See SL_ERROR_MTRR_INV_VCNT for more details.
>> +
>> +======  ========================
>> +Name:   SL_ERROR_MSR_INV_MISC_EN
>> +Value:  0xc000800b
>> +======  ========================
>> +
>> +Description:
>> +
>> +During early Secure Launch validation an invalid miscellaneous enable MSR value
>> +was found. See SL_ERROR_MTRR_INV_VCNT for more details.
>> +
>> +======  =========================
>> +Name:   SL_ERROR_INV_AP_INTERRUPT
>> +Value:  0xc000800c
>> +======  =========================
>> +
>> +Description:
>> +
>> +The application processors (APs) wait to be woken up by the SMP initialization
>> +code. The only interrupt that they expect is an NMI; all other interrupts
>> +should be masked. If an AP gets some other interrupt other than an NMI it will
>> +cause this error. This error is very unlikely to occur.
>> +
>> +======  =========================
>> +Name:   SL_ERROR_INTEGER_OVERFLOW
>> +Value:  0xc000800d
>> +======  =========================
>> +
>> +Description:
>> +
>> +A buffer base and size passed to the MLE caused an integer overflow when
>> +added together. This is most likely a configuration issue in the pre-launch
>> +environment. It could also be the sign of an attempted attack.
>> +
>> +======  ==================
>> +Name:   SL_ERROR_HEAP_WALK
>> +Value:  0xc000800e
>> +======  ==================
>> +
>> +Description:
>> +
>> +An error occurred in TXT heap walking code. The underlying issue is a failure to
>> +early_memremap() portions of the heap, most likely due to a resource shortage.
>> +
>> +======  =================
>> +Name:   SL_ERROR_HEAP_MAP
>> +Value:  0xc000800f
>> +======  =================
>> +
>> +Description:
>> +
>> +This error is essentially the same as SL_ERROR_HEAP_WALK but occurred during the
>> +actual early_memremap() operation.
>> +
>> +======  =========================
>> +Name:   SL_ERROR_REGION_ABOVE_4GB
>> +Value:  0xc0008010
>> +======  =========================
>> +
>> +Description:
>> +
>> +A memory region used by the MLE is above 4GB. In general this is not a problem
>> +because memory > 4Gb can be protected from DMA. There are certain buffers that
>> +should never be above 4Gb though and one of these caused the violation. This is
>> +most likely a configuration issue in the pre-launch environment. It could also
>> +be the sign of an attempted attack.
>> +
>> +======  ==========================
>> +Name:   SL_ERROR_HEAP_INVALID_DMAR
>> +Value:  0xc0008011
>> +======  ==========================
>> +
>> +Description:
>> +
>> +The backup copy of the ACPI DMAR table which is supposed to be located in the
>> +TXT heap could not be found. This is due to a bug in the platform's ACM module
>> +or in firmware.
>> +
>> +======  =======================
>> +Name:   SL_ERROR_HEAP_DMAR_SIZE
>> +Value:  0xc0008012
>> +======  =======================
>> +
>> +Description:
>> +
>> +The backup copy of the ACPI DMAR table in the TXT heap is to large to be stored
>> +for later usage. This error is very unlikely to occur since the area reserved
>> +for the copy is far larger than the DMAR should be.
>> +
>> +======  ======================
>> +Name:   SL_ERROR_HEAP_DMAR_MAP
>> +Value:  0xc0008013
>> +======  ======================
>> +
>> +Description:
>> +
>> +The backup copy of the ACPI DMAR table in the TXT heap could not be mapped. The
>> +underlying issue is a failure to early_memremap() the DMAR table, most likely
>> +due to a resource shortage.
>> +
>> +======  ====================
>> +Name:   SL_ERROR_HI_PMR_BASE
>> +Value:  0xc0008014
>> +======  ====================
>> +
>> +Description:
>> +
>> +On a system with more than 4G of RAM, the high PMR [2]_ base address should be set
>> +to 4G. This error is due to that not being the case. This PMR value is set by
>> +the pre-launch environment so the issue most likely originates there. It could also
>> +be the sign of an attempted attack.
>> +
>> +======  ====================
>> +Name:   SL_ERROR_HI_PMR_SIZE
>> +Value:  0xc0008015
>> +======  ====================
>> +
>> +Description:
>> +
>> +On a system with more than 4G of RAM, the high PMR [2]_ size should be set to cover
>> +all RAM > 4G. This error is due to that not being the case. This PMR value is
>> +set by the pre-launch environment so the issue most likely originates there. It
>> +could also be the sign of an attempted attack.
>> +
>> +======  ====================
>> +Name:   SL_ERROR_LO_PMR_BASE
>> +Value:  0xc0008016
>> +======  ====================
>> +
>> +Description:
>> +
>> +The low PMR [2]_ base should always be set to address zero. This error is due to
>> +that not being the case. This PMR value is set by the pre-launch environment
>> +so the issue most likely originates there. It could also be the sign of an attempted
>> +attack.
>> +
>> +======  ====================
>> +Name:   SL_ERROR_LO_PMR_MLE
>> +Value:  0xc0008017
>> +======  ====================
>> +
>> +Description:
>> +
>> +This error indicates the MLE image is not covered by the low PMR [2]_ range. The
>> +PMR values are set by the pre-launch environment so the issue most likely originates
>> +there. It could also be the sign of an attempted attack.
>> +
>> +======  =======================
>> +Name:   SL_ERROR_INITRD_TOO_BIG
>> +Value:  0xc0008018
>> +======  =======================
>> +
>> +Description:
>> +
>> +The external initrd provided is larger than 4Gb. This is not a valid
>> +configuration for a Secure Launch due to managing DMA protection.
>> +
>> +======  =========================
>> +Name:   SL_ERROR_HEAP_ZERO_OFFSET
>> +Value:  0xc0008019
>> +======  =========================
>> +
>> +Description:
>> +
>> +During a TXT heap walk an invalid/zero next table offset value was found. This
>> +indicates the TXT heap is malformed. The TXT heap is initialized by the
>> +pre-launch environment so the issue most likely originates there. It could also
>> +be a sign of an attempted attack. In addition, ACM is also responsible for
>> +manipulating parts of the TXT heap so the issue could be due to a bug in the
>> +platform's ACM module.
>> +
>> +======  =============================
>> +Name:   SL_ERROR_WAKE_BLOCK_TOO_SMALL
>> +Value:  0xc000801a
>> +======  =============================
>> +
>> +Description:
>> +
>> +The AP wake block buffer passed to the MLE via the OS-MLE TXT heap table is not
>> +large enough. This value is set by the pre-launch environment so the issue most
>> +likely originates there. It also could be the sign of an attempted attack.
>> +
>> +======  ===========================
>> +Name:   SL_ERROR_MLE_BUFFER_OVERLAP
>> +Value:  0xc000801b
>> +======  ===========================
>> +
>> +Description:
>> +
>> +One of the buffers passed to the MLE via the OS-MLE TXT heap table overlaps
>> +with the MLE image in memory. This value is set by the pre-launch environment
>> +so the issue most likely originates there. It could also be the sign of an attempted
>> +attack.
>> +
>> +======  ==========================
>> +Name:   SL_ERROR_BUFFER_BEYOND_PMR
>> +Value:  0xc000801c
>> +======  ==========================
>> +
>> +Description:
>> +
>> +One of the buffers passed to the MLE via the OS-MLE TXT heap table is not
>> +protected by a PMR. This value is set by the pre-launch environment so the
>> +issue most likey  originates there. It could also be the sign of an attempted
>> +attack.
>> +
>> +======  =============================
>> +Name:   SL_ERROR_OS_SINIT_BAD_VERSION
>> +Value:  0xc000801d
>> +======  =============================
>> +
>> +Description:
>> +
>> +The version of the OS-SINIT TXT heap table is bad. It must be 6 or greater.
>> +This value is set by the pre-launch environment so the issue most likely
>> +originates there. It could also be the sign of an attempted attack. It is also
>> +possible though very unlikely that the platform is so old that the ACM being
>> +used requires an unsupported version.
>> +
>> +======  =====================
>> +Name:   SL_ERROR_EVENTLOG_MAP
>> +Value:  0xc000801e
>> +======  =====================
>> +
>> +Description:
>> +
>> +An error occurred in the Secure Launch module while mapping the TPM event log.
>> +The underlying issue is memremap() failure, most likely due to a resource
>> +shortage.
>> +
>> +======  ========================
>> +Name:   SL_ERROR_TPM_NUMBER_ALGS
>> +Value:  0xc000801f
>> +======  ========================
>> +
>> +Description:
>> +
>> +The TPM 2.0 event log reports an unsupported number of hashing algorithms.
>> +Secure launch currently only supports a maximum of two: SHA1 and SHA256.
>> +
>> +======  ===========================
>> +Name:   SL_ERROR_TPM_UNKNOWN_DIGEST
>> +Value:  0xc0008020
>> +======  ===========================
>> +
>> +Description:
>> +
>> +The TPM 2.0 event log reports an unsupported hashing algorithm. Secure launch
>> +currently only supports two algorithms: SHA1 and SHA256.
>> +
>> +======  ==========================
>> +Name:   SL_ERROR_TPM_INVALID_EVENT
>> +Value:  0xc0008021
>> +======  ==========================
>> +
>> +Description:
>> +
>> +An invalid/malformed event was found in the TPM event log while reading it.
>> +Since only trusted entities are supposed to be writing the event log, this
>> +would indicate either a bug or a possible attack.
>> +
>> +======  =====================
>> +Name:   SL_ERROR_INVALID_SLRT
>> +Value:  0xc0008022
>> +======  =====================
>> +
>> +Description:
>> +
>> +The Secure Launch Resource Table is invalid or malformed and is unusable.
>> +This implies the pre-launch code did not properly setup the SLRT.
>> +
>> +======  ===========================
>> +Name:   SL_ERROR_SLRT_MISSING_ENTRY
>> +Value:  0xc0008023
>> +======  ===========================
>> +
>> +Description:
>> +
>> +The Secure Launch Resource Table is missing a required entry within it.
>> +This implies the pre-launch code did not properly setup the SLRT.
>> +
>> +======  =================
>> +Name:   SL_ERROR_SLRT_MAP
>> +Value:  0xc0008024
>> +======  =================
>> +
>> +Description:
>> +
>> +An error occurred in the Secure Launch module while mapping the Secure Launch
>> +Resource table. The underlying issue is memremap() failure, most likely due to
>> +a resource shortage.
>> +
>> +.. [1]
>> +    MLE: Measured Launch Environment is the binary runtime that is measured and
>> +    then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
>> +    requirements for the MLE in detail.
>> +
>> +.. [2]
>> +    PMR: Intel VTd has a feature in the IOMMU called Protected Memory Registers.
>> +    There are two of these registers and they allow all DMA to be blocked
>> +    to large areas of memory. The low PMR can cover all memory below 4Gb on 2Mb
>> +    boundaries. The high PMR can cover all RAM on the system, again on 2Mb
>> +    boundaries. This feature is used during a Secure Launch by TXT.
>> +
>> +.. [3]
>> +    Secure Launch Specification: https://trenchboot.org/specifications/Secure_Launch/
>> diff --git a/Documentation/security/launch-integrity/secure_launch_overview.rst b/Documentation/security/launch-integrity/secure_launch_overview.rst
>> new file mode 100644
>> index 0000000..ba91d73
>> --- /dev/null
>> +++ b/Documentation/security/launch-integrity/secure_launch_overview.rst
>> @@ -0,0 +1,220 @@
>> +======================
>> +Secure Launch Overview
>> +======================
>> +
>> +Overview
>> +========
>> +
>> +Prior to the start of the TrenchBoot project, the only active Open Source
>> +project supporting dynamic launch was Intel's tboot project to support their
>> +implementation of dynamic launch known as Intel Trusted eXecution Technology
>> +(TXT). The approach taken by tboot was to provide an exokernel that could
>> +handle the launch protocol implemented by Intel's special loader, the SINIT
>> +Authenticated Code Module (ACM [2]_) and remained in memory to manage the SMX
>> +CPU mode that a dynamic launch would put a system. While it is not precluded
>> +from being used for doing a late launch, tboot's primary use case was to be
>> +used as an early launch solution. As a result the TrenchBoot project started
>> +the development of Secure Launch kernel feature to provide a more generalized
>> +approach. The focus of the effort is twofold, the first is to make the Linux
>> +kernel directly aware of the launch protocol used by Intel, AMD/Hygon, Arm, and
>> +potentially OpenPOWER. The second is to make the Linux kernel be able to
>> +initiate a dynamic launch. It is through this approach that the Secure Launch
>> +kernel feature creates a basis for the Linux kernel to be used in a variety of
>> +dynamic launch use cases.
>> +
>> +.. note::
>> +    A quick note on terminology. The larger open source project itself is
>> +    called TrenchBoot, which is hosted on GitHub (links below). The kernel
>> +    feature enabling the use of the x86 technology is referred to as "Secure
>> +    Launch" within the kernel code.
>> +
>> +Goals
>> +=====
>> +
>> +The first use case that the TrenchBoot project focused on was the ability for
>> +the Linux kernel to be started by a dynamic launch, in particular as part of an
>> +early launch sequence. In this case the dynamic launch will be initiated by any
>> +boot loader with associated support added to it, for example the first targeted
>> +boot loader in this case was GRUB2. An integral part of establishing a
>> +measurement-based launch integrity involves measuring everything that is
>> +intended to be executed (kernel image, initrd, etc) and everything that will
>> +configure that kernel to execute (command line, boot params, etc). Then storing
>> +those measurements in a protected manner. Both the Intel and AMD dynamic launch
>> +implementations leverage the Trusted Platform Module (TPM) to store those
>> +measurements. The TPM itself has been designed such that a dynamic launch
>> +unlocks a specific set of Platform Configuration Registers (PCR) for holding
>> +measurement taken during the dynamic launch.  These are referred to as the DRTM
>> +PCRs, PCRs 17-22. Further details on this process can be found in the
>> +documentation for the GETSEC instruction provided by Intel's TXT and the SKINIT
>> +instruction provided by AMD's AMD-V. The documentation on these technologies
>> +can be readily found online; see the `Resources`_ section below for references.
>> +
>> +.. note::
>> +    Currently only Intel TXT is supported in this first release of the Secure
>> +    Launch feature. AMD/Hygon SKINIT and Arm support will be added in a
>> +    subsequent release.
>> +
>> +To enable the kernel to be launched by GETSEC a stub, the Secure Launch stub,
>> +must be built into the setup section of the compressed kernel to handle the
>> +specific state that the dynamic launch process leaves the BSP. Also the Secure
>> +Launch stub must measure everything that is going to be used as early as
>> +possible. This stub code and subsequent code must also deal with the specific
>> +state that the dynamic launch leaves the APs as well.
>> +
>> +Design Decisions
>> +================
>> +
>> +A number of design decisions were made during the development of the Secure
>> +Launch feature. The two primary guiding decisions were:
>> +
>> + - Keeping the Secure Launch code as separate from the rest of the kernel
>> +   as possible.
>> + - Modifying the existing boot path of the kernel as little as possible.
>> +
>> +The following illustrate how the implementation followed these design
>> +decisions:
>> +
>> + - All the entry point code necessary to properly configure the system post
>> +   launch is found in st_stub.S in the compressed kernel image. This code
>> +   validates the state of the system, restores necessary system operating
>> +   configurations and properly handles post launch CPU states.
>> + - After the sl_stub.S is complete, it jumps directly to the unmodified
>> +   startup_32 kernel entry point.
>> + - A single call is made to a function sl_main() prior to the main kernel
>> +   decompression step. This code performs further validation and takes the
>> +   needed DRTM measurements.
>> + - After the call to sl_main(), the main kernel is decompressed and boots as
>> +   it normally would.
>> + - Final setup for the Secure Launch kernel is done in a separate Secure
>> +   Launch module that is loaded via a late initcall. This code is responsible
>> +   for extending the measurements taken earlier into the TPM DRTM PCRs and
>> +   setting up the securityfs interface to allow access the TPM event log and
>> +   public TXT registers.
>> + - On the reboot and kexec paths, calls are made to a function to finalize the
>> +   state of the Secure Launch kernel.
>> +
>> +The one place where Secure Launch code is mixed directly in with kernel code is
>> +in the SMP boot code. This is due to the unique state that the dynamic launch
>> +leaves the APs in. On Intel this involves using a method other than the
>> +standard INIT-SIPI sequence.
>> +
>> +A final note is that originally the extending of the PCRs was completed in the
>> +Secure Launch stub when the measurements were taken. An alternative solution
>> +had to be implemented due to the TPM maintainers objecting to the PCR
>> +extensions being done with a minimal interface to the TPM that was an
>> +independent implementation of the mainline kernel driver. Since the mainline
>> +driver relies heavily on kernel interfaces not available in the compressed
>> +kernel, it was not possible to reuse the mainline TPM driver. This resulted in
>> +the decision to move the extension operations to the Secure Launch module in
>> +the mainline kernel where the TPM driver would be available.
>> +
>> +Basic Boot Flow
>> +===============
>> +
>> +Outlined here is summary of the boot flow for Secure Launch. A more detailed
>> +review of Secure Launch process can be found in the Secure Launch
>> +Specification, a link is located in the `Resources`_ section.
>> +
>> +Pre-launch: *Phase where the environment is prepared and configured to initiate the
>> +secure launch by the boot chain.*
>> +
>> + - The SLRT is initialized and dl_stub is placed in memory.
>> + - Load the kernel, initrd and ACM [2]_ into memory.
>> + - Setup the TXT heap and page tables describing the MLE [1]_ per the
>> +   specification.
>> + - If non-UEFI platform, dl_stub is called.
>> + - If UEFI platforms, SLRT registered with UEFI and efi-stub called.
>> + - Upon completion, efi-stub will call EBS followed by dl_stub.
>> + - The dl_stub will prepare the CPU and the TPM for the launch.
>> + - The secure launch is then initiated with the GETSET[SENTER] instruction.
>> +
>> +Post-launch: *Phase where control is passed from the ACM to the MLE and the secure
>> +kernel begins execution.*
>> +
>> + - Entry from the dynamic launch jumps to the SL stub.
>> + - SL stub fixes up the world on the BSP.
>> + - For TXT, SL stub wakes the APs, fixes up their worlds.
>> + - For TXT, APs are left halted waiting for an NMI to wake them.
>> + - SL stub jumps to startup_32.
>> + - SL main does validation of buffers and memory locations. It sets
>> +   the boot parameter loadflag value SLAUNCH_FLAG to inform the main
>> +   kernel that a Secure Launch was done.
>> + - SL main locates the TPM event log and writes the measurements of
>> +   configuration and module information into it.
>> + - Kernel boot proceeds normally from this point.
>> + - During early setup, slaunch_setup() runs to finish some validation
>> +   and setup tasks.
>> + - The SMP bring up code is modified to wake the waiting APs. APs vector
>> +   to rmpiggy and start up normally from that point.
>> + - SL platform module is registered as a late initcall module. It reads
>> +   the TPM event log and extends the measurements taken into the TPM PCRs.
>> + - SL platform module initializes the securityfs interface to allow
>> +   access to the TPM event log and TXT public registers.
>> + - Kernel boot finishes booting normally
>> + - SEXIT support to leave SMX mode is present on the kexec path and
>> +   the various reboot paths (poweroff, reset, halt).
>> +
>> +PCR Usage
>> +=========
>> +
>> +The TCG DRTM architecture there are three PCRs defined for usage, PCR.Details
>> +(PCR17), PCR.Authorities (PCR18), and PCR.DLME_Authority (PCR19). For a deeper
>> +understanding of Detail and Authorities it is recommended to review the TCG
>> +DRTM architecture.
>> +
>> +To determine PCR usage, Linux Secure Launch follows the TrenchBoot Secure
>> +Launch Specification of using a measurement policy stored in the SLRT. The
>> +policy details what should be measured and the PCR in which to store the
>> +measurement. The measurement policy provides the ability to select the
>> +PCR.DLME_Detail (PCR20) PCR as the location for the DRTM components measured by
>> +the kernel, e.g. external initrd image. This can then be combined with storing
>> +the user authority in the PCR.DLME_Authority PCR to seal/attest to different
>> +variations of platform details/authorities and user details/authorities. An
>> +example of how this can be achieved was presented in the FOSDEM - 2021 talk
>> +"Secure Upgrades with DRTM".
>> +
>> +Resources
>> +=========
>> +
>> +The TrenchBoot project:
>> +
>> +https://trenchboot.org
>> +
>> +Secure Launch Specification:
>> +
>> +https://trenchboot.org/specifications/Secure_Launch/
>> +
>> +Trusted Computing Group's D-RTM Architecture:
>> +
>> +https://trustedcomputinggroup.org/wp-content/uploads/TCG_D-RTM_Architecture_v1-0_Published_06172013.pdf
>> +
>> +TXT documentation in the Intel TXT MLE Development Guide:
>> +
>> +https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
>> +
>> +TXT instructions documentation in the Intel SDM Instruction Set volume:
>> +
>> +https://software.intel.com/en-us/articles/intel-sdm
>> +
>> +AMD SKINIT documentation in the System Programming manual:
>> +
>> +https://www.amd.com/system/files/TechDocs/24593.pdf
>> +
>> +GRUB Secure Launch support:
>> +
>> +https://github.com/TrenchBoot/grub/tree/grub-sl-fc-38-dlstub
>> +
>> +FOSDEM 2021: Secure Upgrades with DRTM
>> +
>> +https://archive.fosdem.org/2021/schedule/event/firmware_suwd/
>> +
>> +.. [1]
>> +    MLE: Measured Launch Environment is the binary runtime that is measured and
>> +    then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
>> +    requirements for the MLE in detail.
>> +
>> +.. [2]
>> +    ACM: Intel's Authenticated Code Module. This is the 32b bit binary blob that
>> +    is run securely by the GETSEC[SENTER] during a measured launch. It is described
>> +    in the Intel documentation on TXT and versions for various chipsets are
>> +    signed and distributed by Intel.
>   
> The formatting LGTM, thanks!
> 
> Regardless,
> 
> Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com>

Thank you,
Ross

> 


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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
@ 2023-05-10 15:41       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-10 15:41 UTC (permalink / raw)
  To: Bagas Sanjaya, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, kexec, linux-efi, iommu
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On 5/6/23 04:48, Bagas Sanjaya wrote:
> On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
>> +=====================================
>> +System Launch Integrity documentation
>> +=====================================
>> +
>> +.. toctree::
> 
> By convention, doc toctree have 2-level depth (only page title and
> first-level headings are visible). You may consider adding
> `:maxdepth: 2` option.

Will do.

> 
>> diff --git a/Documentation/security/launch-integrity/principles.rst b/Documentation/security/launch-integrity/principles.rst
>> new file mode 100644
>> index 0000000..73cf063
>> --- /dev/null
>> +++ b/Documentation/security/launch-integrity/principles.rst
>> @@ -0,0 +1,313 @@
>> +=======================
>> +System Launch Integrity
>> +=======================
>> +
>> +This document serves to establish a common understanding of what is system
>> +launch, the integrity concern for system launch, and why using a Root of Trust
>> +(RoT) from a Dynamic Launch may be desired. Through out this document
>> +terminology from the Trusted Computing Group (TCG) and National Institue for
>> +Science and Technology (NIST) is used to ensure a vendor nutrual language is
>> +used to describe and reference security-related concepts.
>> +
>> +System Launch
>> +=============
>> +
>> +There is a tendency to only consider the classical power-on boot as the only
>> +means to launch an Operating System (OS) on a computer system, but in fact most
>> +modern processors support two methods to launch the system. To provide clarity a
>> +common definition of a system launch should be established. This definition is
>> +that a during a single power life cycle of a system, a System Launch consists
>> +of an initialization event, typically in hardware, that is followed by an
>> +executing software payload that takes the system from the initialized state to
>> +a running state. Driven by the Trusted Computing Group (TCG) architecture,
>> +modern processors are able to support two methods to launch a system, these two
>> +types of system launch are known as Static Launch and Dynamic Launch.
>> +
>> +Static Launch
>> +-------------
>> +
>> +Static launch is the system launch associated with the power cycle of the CPU.
>> +Thus static launch refers to the classical power-on boot where the
>> +initialization event is the release of the CPU from reset and the system
>> +firmware is the software payload that brings the system up to a running state.
>> +Since static launch is the system launch associated with the beginning of the
>> +power lifecycle of a system, it is therefore a fixed, one-time system launch.
>> +It is because of this that static launch is referred to and thought of as being
>> +"static".
>> +
>> +Dynamic Launch
>> +--------------
>> +
>> +Modern CPUs architectures provides a mechanism to re-initialize the system to a
>> +"known good" state without requiring a power event. This re-initialization
>> +event is the event for a dynamic launch and is referred to as the Dynamic
>> +Launch Event (DLE). The DLE functions by accepting a software payload, referred
>> +to as the Dynamic Configuration Environment (DCE), that execution is handed to
>> +after the DLE is invoked. The DCE is responsible for bringing the system back
>> +to a running state. Since the dynamic launch is not tied to a power event like
>> +the static launch, this enables a dynamic launch to be initiated at any time
>> +and multiple times during a single power life cycle. This dynamism is the
>> +reasoning behind referring to this system launch as being dynamic.
>> +
>> +Because a dynamic launch can be conducted at any time during a single power
>> +life cycle, they are classified into one of two types, an early launch or a
>> +late launch.
>> +
>> +:Early Launch: When a dynamic launch is used as a transition from a static
>> +   launch chain to the final Operating System.
>> +
>> +:Late Launch: The usage of a dynamic launch by an executing Operating System to
>> +   transition to a “known good” state to perform one or more operations, e.g. to
>> +   launch into a new Operating System.
>> +
>> +System Integrity
>> +================
>> +
>> +A computer system can be considered a collection of mechanisms that work
>> +together to produce a result. The assurance that the mechanisms are functioning
>> +correctly and producing the expected result is the integrity of the system. To
>> +ensure a system's integrity there are a subset of these mechanisms, commonly
>> +referred to as security mechanisms, that are present to help ensure the system
>> +produces the expected result or at least detect the potential of an unexpected
>> +result may have happened. Since the security mechanisms are relied upon to
>> +ensue the integrity of the system, these mechanisms are trusted. Upon
>> +inspection these security mechanisms each have a set of properties and these
>> +properties can be evaluated to determine how susceptible a mechanism might be
>> +to failure. This assessment is referred to as the Strength of Mechanism and for
>> +trusted mechanism enables for the trustworthiness of that mechanism to be
>> +quantified.
>> +
>> +For software systems there are two system states for which the integrity is
>> +critical, when the software is loaded into memory and when the software is
>> +executing on the hardware. Ensuring that the expected software is load into
>> +memory is referred to as load-time integrity while ensuring that the software
>> +executing is the expected software is the runtime integrity of that software.
>> +
>> +Load-time Integrity
>> +-------------------
>> +
>> +It is critical to understand what load-time integrity establishes about a
>> +system and what is assumed, i.e. what is being trusted. Load-time integrity is
>> +when a trusted entity, i.e. an entity with an assumed integrity, takes an
>> +action to assess an entity being loaded into memory before it is used. A
>> +variety of mechanisms may be used to conduct the assessment, each with
>> +different properties. A particular property is whether the mechanism creates an
>> +evidence of the assessment. Often either cryptographic signature checking or
>> +hashing are the common assessment operations used.
>> +
>> +A signature checking assessment functions by requiring a representation of the
>> +accepted authorities and uses those representations to assess if the entity has
>> +been signed by an accepted authority. The benefit to this process is that
>> +assessment process includes an adjudication of the assessment. The drawbacks
>> +are that 1) the adjudication is susceptible to tampering by the Trusted
>> +Computing Base (TCB), 2) there is no evidence to assert that an untampered
>> +adjudication was completed, and 3) the system must be an active participant in
>> +the key management infrastructure.
>> +
>> +A cryptographic hashing assessment does not adjudicate the assessment but
>> +instead generates evidence of the assessment to be adjudicated independently.
>> +The benefits to this approach is that the assessment may be simple such that it
>> +is able to be implemented as an immutable mechanism, e.g. in hardware.
>> +Additionally it is possible for the adjudication to be conducted where it
>> +cannot be tampered with by the TCB. The drawback is that a compromised
>> +environment will be allowed to execute until an adjudication can be completed.
>> +
>> +Ultimately load-time integrity provides confidence that the correct entity was
>> +loaded and in the absence of a run-time integrity mechanism assumes, i.e
>> +trusts, that the entity will never become corrupted.
>> +
>> +Runtime Integrity
>> +-----------------
>> +
>> +Runtime integrity in the general sense is when a trusted entity makes an
>> +assessment of an entity at any point in time during the assessed entity's
>> +execution. A more concrete explanation is the taking of an integrity assessment
>> +of an active process executing on the system at any point during the process'
>> +execution. Often the load-time integrity of an operating system's user-space,
>> +i.e. the operating environment, is confused to be the runtime integrity of the
>> +system since it is an integrity assessment of the "runtime" software. The
>> +reality is that actual runtime integrity is a very difficult problem and thus
>> +not very many solutions are public and/or available. One example of a runtime
>> +integrity solution would be John Hopkins Advanced Physics Labratory's (APL)
>> +Linux Kernel Integrity Module (LKIM).
>> +
>> +Trust Chains
>> +============
>> +
>> +Bulding upon the understanding of security mechanisms to establish load-time
>> +integrity of an entity, it is possible to chain together load-time integrity
>> +assessments to establish the integrity of the whole system. This process is
>> +known as transitive trust and provides the concept of building a chain of
>> +load-time integrity assessments, commonly referred to as a trust chain. These
>> +assessments may be used to adjudicate the load-time integrity of the whole
>> +system. This trust chain is started by a trusted entity that does the first
>> +assessment. This first entity is referred to as the Root of Trust(RoT) with the
>> +entities name being derived from the mechanism used for the assessment, i.e.
>> +RoT for Verification (RTV) and RoT for Measurement (RTM).
>> +
>> +A trust chain is itself a mechanism, specifically a mechanism of mechanisms,
>> +and therefore it too has a Strength of Mechanism. The factors that contribute
>> +to a trust chain's strength are,
>> +
>> +  - The strength of the chain's RoT
>> +  - The strength of each member of the trust chain
>> +  - The length, i.e. the number of members, of the chain
>> +
>> +Therefore to provide the strongest trust chains, they should start with a
>> +strong RoT and should consist of members being of low complexity and minimizing
>> +the number of members participating as is possible. In a more colloquial sense,
>> +a trust chain is only as strong as it weakests link and more links increase
>> +the probability of a weak link.
>> +
>> +Dynamic Launch Components
>> +=========================
>> +
>> +The TCG architecture for dynamic launch is composed of a component series that
>> +are used to setup and then carry out the launch. These components work together
>> +to construct a RTM trust chain that is rooted in the dynamic launch and thus
>> +commonly referred to as the Dynamic Root of Trust for Measurement (DRTM) chain.
>> +
>> +What follows is a brief explanation of each component in execution order. A
>> +subset of these components are what establishes the dynamic launch's trust
>> +chain.
>> +
>> +Dynamic Configuration Environment Preamble
>> +------------------------------------------
>> +
>> +The Dynamic Configuration Environment (DCE) Preamble is responsible for setting
>> +up the system environment in preparation for a dynamic launch. The DCE Preamble
>> +is not a part of the DRTM trust chain.
>> +
>> +Dynamic Launch Event
>> +--------------------
>> +
>> +The dynamic launch event is the event, typically a CPU instruction, that triggers
>> +the system's dynamic launch mechanism to begin the launch. The dynamic launch
>> +mechanism is also the RoT for the DRTM trust chain.
>> +
>> +Dynamic Configuration Environment
>> +---------------------------------
>> +
>> +The dynamic launch mechanism may have resulted in a reset of a portion of the
>> +system. To bring the system back to an adequate state for system software the
>> +dynamic launch will hand over control to the DCE. Prior to handing over this
>> +control, the dynamic launch will measure the DCE. Once the DCE is complete it
>> +will proceed to measure and then execute the Dynamic Launch Measured
>> +Environment (DLME).
>> +
>> +Dynamic Launch Measured Environment
>> +-----------------------------------
>> +
>> +The DLME is the first system kernel to have control of the system but may not
>> +be the last. Depending on the usage and configuration, the DLME may be the
>> +final/target operating system or it may be a boot loader that will load the
>> +final/target operating system.
>> +
>> +Why DRTM
>> +========
>> +
>> +It is a fact that DRTM increases the load-time integrity of the system by
>> +providing a trust chain that has an immutable hardware RoT, uses a limited
>> +number of small, special purpose code to establish the trust chain that starts
>> +the target operating system. As mentioned in the Trust Chain section, these are
>> +the main three factors in driving up the strength of a trust chain. As can been
>> +seen by the BootHole exploit, which in fact did not effect the integrity of
>> +DRTM solutions, the sophistication of attacks targeting system launch is at an
>> +all time high. There is no reason a system should not employ every integrity
>> +measure hardware makes available. This is the crux of a defense-in-depth
>> +approach to system security. In the past the now closed SMI gap was often
>> +pointed to as invalidating DRTM, which in fact was nothing but a strawman
>> +argument. As has continued to be demonstrated, if/when SMM is corrupted it can
>> +always circumvent all load-time integrity, SRTM and DRTM, because it is a
>> +run-time integrity problem. Regardless, Intel and AMD have both deployed
>> +runtime integrity for SMI and SMM which is tied directly to DRTM such that this
>> +perceived deficiency is now non-existent and the world is moving forward with
>> +an expectation that DRTM must be present.
>> +
>> +Glossary
>> +========
>> +
>> +.. glossary::
>> +  integrity
>> +    Guarding against improper information modification or destruction, and
>> +    includes ensuring information non-repudiation and authenticity.
>> +
>> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
>> +
>> +  mechanism
>> +    A process or system that is used to produce a particular result.
>> +
>> +    - NIST Special Publication 800-160 (VOLUME 1 ) - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-160v1.pdf
>> +
>> +  risk
>> +    A measure of the extent to which an entity is threatened by a potential
>> +    circumstance or event, and typically a function of: (i) the adverse impacts
>> +    that would arise if the circumstance or event occurs; and (ii) the
>> +    likelihood of occurrence.
>> +
>> +    - NIST SP 800-30 Rev. 1 - https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-30r1.pdf
>> +
>> +  security mechanism
>> +    A device or function designed to provide one or more security services
>> +    usually rated in terms of strength of service and assurance of the design.
>> +
>> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
>> +
>> +  Strength of Mechanism
>> +    A scale for measuring the relative strength of a security mechanism
>> +
>> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
>> +
>> +  transitive trust
>> +    Also known as "Inductive Trust", in this process a Root of Trust gives a
>> +    trustworthy description of a second group of functions. Based on this
>> +    description, an interested entity can determine the trust it is to place in
>> +    this second group of functions. If the interested entity determines that
>> +    the trust level of the second group of functions is acceptable, the trust
>> +    boundary is extended from the Root of Trust to include the second group of
>> +    functions. In this case, the process can be iterated. The second group of
>> +    functions can give a trustworthy description of the third group of
>> +    functions, etc. Transitive trust is used to provide a trustworthy
>> +    description of platform characteristics, and also to prove that
>> +    non-migratable keys are non-migratable
>> +
>> +    - TCG Glossary - https://trustedcomputinggroup.org/wp-content/uploads/TCG-Glossary-V1.1-Rev-1.0.pdf
>> +
>> +  trust
>> +    The confidence one element has in another that the second element will
>> +    behave as expected`
>> +
>> +    - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
>> +
>> +  trust anchor
>> +    An authoritative entity for which trust is assumed.
>> +
>> +    - NIST SP 800-57 Part 1 Rev. 5 - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf
>> +
>> +  trusted
>> +    An element that another element relies upon to fulfill critical
>> +    requirements on its behalf.
>> +
>> +    - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
>> +
>> +  trusted computing base (TCB)
>> +    Totality of protection mechanisms within a computer system, including
>> +    hardware, firmware, and software, the combination responsible for enforcing
>> +    a security policy.
>> +
>> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
>> +
>> +  trusted computer system
>> +    A system that has the necessary security functions and assurance that the
>> +    security policy will be enforced and that can process a range of
>> +    information sensitivities (i.e. classified, controlled unclassified
>> +    information (CUI), or unclassified public information) simultaneously.
>> +
>> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
>> +
>> +  trustworthiness
>> +    The attribute of a person or enterprise that provides confidence to others
>> +    of the qualifications, capabilities, and reliability of that entity to
>> +    perform specific tasks and fulfill assigned responsibilities.
>> +
>> +    - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
>> diff --git a/Documentation/security/launch-integrity/secure_launch_details.rst b/Documentation/security/launch-integrity/secure_launch_details.rst
>> new file mode 100644
>> index 0000000..2e71543
>> --- /dev/null
>> +++ b/Documentation/security/launch-integrity/secure_launch_details.rst
>> @@ -0,0 +1,564 @@
>> +===================================
>> +Secure Launch Config and Interfaces
>> +===================================
>> +
>> +Configuration
>> +=============
>> +
>> +The settings to enable Secure Launch using Kconfig are under::
>> +
>> +  "Processor type and features" --> "Secure Launch support"
>> +
>> +A kernel with this option enabled can still be booted using other supported
>> +methods.
>> +
>> +To reduce the Trusted Computing Base (TCB) of the MLE [1]_, the build
>> +configuration should be pared down as narrowly as one's use case allows.
>> +The fewer drivers (less active hardware) and features reduces the attack
>> +surface. E.g. in the extreme, the MLE could only have local disk access
>> +and no other hardware support. Or only network access for remote attestation.
>> +
>> +It is also desirable if possible to embed the initrd used with the MLE kernel
>> +image to reduce complexity.
>> +
>> +The following are a few important configuration necessities to always consider:
>> +
>> +KASLR Configuration
>> +-------------------
>> +
>> +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
>> +built with KASLR disabled::
>> +
>> +  "Processor type and features" -->
>> +      "Build a relocatable kernel" -->
>> +          "Randomize the address of the kernel image (KASLR) [ ]"
>> +
>> +This unsets the Kconfig value CONFIG_RANDOMIZE_BASE.
>> +
>> +If not possible, KASLR must be disabled on the kernel command line when doing
>> +a Secure Launch as follows::
>> +
>> +  nokaslr
>> +
>> +IOMMU Configuration
>> +-------------------
>> +
>> +When doing a Secure Launch, the IOMMU should always be enabled and the drivers
>> +loaded. However, IOMMU passthrough mode should never be used. This leaves the
>> +MLE completely exposed to DMA after the PMR's [2]_ are disabled. The current default
>> +mode is to use IOMMU in lazy translated mode but strict translated mode is the preferred
>> +IOMMU mode and this should be selected in the build configuration::
>> +
>> +  "Device Drivers" -->
>> +      "IOMMU Hardware Support" -->
>> +          "IOMMU default domain type" -->
>> +              "(X) Translated - Strict"
>> +
>> +In addition, the Intel IOMMU should be on by default. The following sets this as the
>> +default in the build configuration::
>> +
>> +  "Device Drivers" -->
>> +      "IOMMU Hardware Support" -->
>> +          "Support for Intel IOMMU using DMA Remapping Devices [*]"
>> +
>> +and::
>> +
>> +  "Device Drivers" -->
>> +      "IOMMU Hardware Support" -->
>> +          "Support for Intel IOMMU using DMA Remapping Devices [*]" -->
>> +              "Enable Intel DMA Remapping Devices by default  [*]"
>> +
>> +It is recommended that no other command line options should be set to override
>> +the defaults above.
>> +
>> +Secure Launch Resource Table
>> +============================
>> +
>> +The Secure Launch Resource Table (SLRT) is a platform-agnostic, standard format
>> +for providing information for the pre-launch environment and to pass
>> +information to the post-launch environment. The table is populated by one or
>> +more bootloaders in the boot chain and used by Secure Launch on how to setup
>> +the environment during post-launch. The details for the SLRT are documented
>> +in the TrenchBoot Secure Launch Specifcation [3]_.
>> +
>> +Intel TXT Interface
>> +===================
>> +
>> +The primary interfaces between the various components in TXT are the TXT MMIO
>> +registers and the TXT heap. The MMIO register banks are described in Appendix B
>> +of the TXT MLE [1]_ Development Guide.
>> +
>> +The TXT heap is described in Appendix C of the TXT MLE [1]_ Development
>> +Guide. Most of the TXT heap is predefined in the specification. The heap is
>> +initialized by firmware and the pre-launch environment and is subsequently used
>> +by the SINIT ACM. One section, called the OS to MLE Data Table, is reserved for
>> +software to define. This table is set up per the recommendation detailed in
>> +Appendix B of the TrenchBoot Secure Launch Specification::
>> +
>> +        /*
>> +         * Secure Launch defined OS/MLE TXT Heap table
>> +         */
>> +        struct txt_os_mle_data {
>> +                u32 version;
>> +                u32 boot_params_addr;
>> +                struct slr_table *slrt;
>> +                u64 txt_info;
>> +                u32 ap_wake_block;
>> +                u32 ap_wake_block_size;
>> +                u8 mle_scratch[64];
>> +        } __packed;
>> +
>> +Description of structure:
>> +
>> +=====================  ========================================================================
>> +Field                  Use
>> +=====================  ========================================================================
>> +version                Structure version, current value 1
>> +boot_params_addr       Physical base address of the Linux boot parameters
>> +slrt                   Physical address of the Secure Launch Resource Table
>> +txt_info               Pointer into the SLRT for easily locating TXT specific table
>> +ap_wake_block          Physical address of the block of memory for parking APs after a launch
>> +ap_wake_block_size     Size of the AP wake block
>> +mle_scratch            Scratch area used post-launch by the MLE kernel. Fields:
>> +
>> +                        - SL_SCRATCH_AP_EBX area to share %ebx base pointer among CPUs
>> +                        - SL_SCRATCH_AP_JMP_OFFSET offset to abs. ljmp fixup location for APs
>> +=====================  ========================================================================
>> +
>> +Error Codes
>> +-----------
>> +
>> +The TXT specification defines the layout for TXT 32 bit error code values.
>> +The bit encodings indicate where the error originated (e.g. with the CPU,
>> +in the SINIT ACM, in software). The error is written to a sticky TXT
>> +register that persists across resets called TXT.ERRORCODE (see the TXT
>> +MLE Development Guide). The errors defined by the Secure Launch feature are
>> +those generated in the MLE software. They have the format::
>> +
>> +  0xc0008XXX
>> +
>> +The low 12 bits are free for defining the following Secure Launch specific
>> +error codes.
>> +
>> +======  ================
>> +Name:   SL_ERROR_GENERIC
>> +Value:  0xc0008001
>> +======  ================
>> +
>> +Description:
>> +
>> +Generic catch all error. Currently unused.
>> +
>> +======  =================
>> +Name:   SL_ERROR_TPM_INIT
>> +Value:  0xc0008002
>> +======  =================
>> +
>> +Description:
>> +
>> +The Secure Launch code failed to get an access to the TPM hardware interface.
>> +This is most likely to due to misconfigured hardware or kernel. Ensure the
>> +TPM chip is enabled and the kernel TPM support is built in (it should not be
>> +built as a module).
>> +
>> +======  ==========================
>> +Name:   SL_ERROR_TPM_INVALID_LOG20
>> +Value:  0xc0008003
>> +======  ==========================
>> +
>> +Description:
>> +
>> +The Secure Launch code failed to find a valid event log descriptor for TPM
>> +version 2.0 or the event log descriptor is malformed. Usually this indicates
>> +that incompatible versions of the pre-launch environment and the MLE kernel.
>> +The pre-launch environment and the kernel share a structure in the TXT heap and
>> +if this structure (the OS-MLE table) is mismatched, this error is often seen.
>> +This TXT heap area is setup by the pre-launch environment so the issue may
>> +originate there. It could be the sign of an attempted attack.
>> +
>> +======  ===========================
>> +Name:   SL_ERROR_TPM_LOGGING_FAILED
>> +Value:  0xc0008004
>> +======  ===========================
>> +
>> +Description:
>> +
>> +There was a failed attempt to write a TPM event to the event log early in the
>> +Secure Launch process. This is likely the result of a malformed TPM event log
>> +buffer. Formatting of the event log buffer information is done by the
>> +pre-launch environment so the issue most likely originates there.
>> +
>> +======  ============================
>> +Name:   SL_ERROR_REGION_STRADDLE_4GB
>> +Value:  0xc0008005
>> +======  ============================
>> +
>> +Description:
>> +
>> +During early validation a buffer or region was found to straddle the 4GB
>> +boundary. Because of the way TXT does DMA memory protection, this is an
>> +unsafe configuration and is flagged as an error. This is most likely a
>> +configuration issue in the pre-launch environment. It could also be the sign of
>> +an attempted attack.
>> +
>> +======  ===================
>> +Name:   SL_ERROR_TPM_EXTEND
>> +Value:  0xc0008006
>> +======  ===================
>> +
>> +Description:
>> +
>> +There was a failed attempt to extend a TPM PCR in the Secure Launch platform
>> +module. This is most likely to due to misconfigured hardware or kernel. Ensure
>> +the TPM chip is enabled and the kernel TPM support is built in (it should not
>> +be built as a module).
>> +
>> +======  ======================
>> +Name:   SL_ERROR_MTRR_INV_VCNT
>> +Value:  0xc0008007
>> +======  ======================
>> +
>> +Description:
>> +
>> +During early Secure Launch validation an invalid variable MTRR count was found.
>> +The pre-launch environment passes a number of MSR values to the MLE to restore
>> +including the MTRRs. The values are restored by the Secure Launch early entry
>> +point code. After measuring the values supplied by the pre-launch environment,
>> +a discrepancy was found validating the values. It could be the sign of an
>> +attempted attack.
>> +
>> +======  ==========================
>> +Name:   SL_ERROR_MTRR_INV_DEF_TYPE
>> +Value:  0xc0008008
>> +======  ==========================
>> +
>> +Description:
>> +
>> +During early Secure Launch validation an invalid default MTRR type was found.
>> +See SL_ERROR_MTRR_INV_VCNT for more details.
>> +
>> +======  ======================
>> +Name:   SL_ERROR_MTRR_INV_BASE
>> +Value:  0xc0008009
>> +======  ======================
>> +
>> +Description:
>> +
>> +During early Secure Launch validation an invalid variable MTRR base value was
>> +found. See SL_ERROR_MTRR_INV_VCNT for more details.
>> +
>> +======  ======================
>> +Name:   SL_ERROR_MTRR_INV_MASK
>> +Value:  0xc000800a
>> +======  ======================
>> +
>> +Description:
>> +
>> +During early Secure Launch validation an invalid variable MTRR mask value was
>> +found. See SL_ERROR_MTRR_INV_VCNT for more details.
>> +
>> +======  ========================
>> +Name:   SL_ERROR_MSR_INV_MISC_EN
>> +Value:  0xc000800b
>> +======  ========================
>> +
>> +Description:
>> +
>> +During early Secure Launch validation an invalid miscellaneous enable MSR value
>> +was found. See SL_ERROR_MTRR_INV_VCNT for more details.
>> +
>> +======  =========================
>> +Name:   SL_ERROR_INV_AP_INTERRUPT
>> +Value:  0xc000800c
>> +======  =========================
>> +
>> +Description:
>> +
>> +The application processors (APs) wait to be woken up by the SMP initialization
>> +code. The only interrupt that they expect is an NMI; all other interrupts
>> +should be masked. If an AP gets some other interrupt other than an NMI it will
>> +cause this error. This error is very unlikely to occur.
>> +
>> +======  =========================
>> +Name:   SL_ERROR_INTEGER_OVERFLOW
>> +Value:  0xc000800d
>> +======  =========================
>> +
>> +Description:
>> +
>> +A buffer base and size passed to the MLE caused an integer overflow when
>> +added together. This is most likely a configuration issue in the pre-launch
>> +environment. It could also be the sign of an attempted attack.
>> +
>> +======  ==================
>> +Name:   SL_ERROR_HEAP_WALK
>> +Value:  0xc000800e
>> +======  ==================
>> +
>> +Description:
>> +
>> +An error occurred in TXT heap walking code. The underlying issue is a failure to
>> +early_memremap() portions of the heap, most likely due to a resource shortage.
>> +
>> +======  =================
>> +Name:   SL_ERROR_HEAP_MAP
>> +Value:  0xc000800f
>> +======  =================
>> +
>> +Description:
>> +
>> +This error is essentially the same as SL_ERROR_HEAP_WALK but occurred during the
>> +actual early_memremap() operation.
>> +
>> +======  =========================
>> +Name:   SL_ERROR_REGION_ABOVE_4GB
>> +Value:  0xc0008010
>> +======  =========================
>> +
>> +Description:
>> +
>> +A memory region used by the MLE is above 4GB. In general this is not a problem
>> +because memory > 4Gb can be protected from DMA. There are certain buffers that
>> +should never be above 4Gb though and one of these caused the violation. This is
>> +most likely a configuration issue in the pre-launch environment. It could also
>> +be the sign of an attempted attack.
>> +
>> +======  ==========================
>> +Name:   SL_ERROR_HEAP_INVALID_DMAR
>> +Value:  0xc0008011
>> +======  ==========================
>> +
>> +Description:
>> +
>> +The backup copy of the ACPI DMAR table which is supposed to be located in the
>> +TXT heap could not be found. This is due to a bug in the platform's ACM module
>> +or in firmware.
>> +
>> +======  =======================
>> +Name:   SL_ERROR_HEAP_DMAR_SIZE
>> +Value:  0xc0008012
>> +======  =======================
>> +
>> +Description:
>> +
>> +The backup copy of the ACPI DMAR table in the TXT heap is to large to be stored
>> +for later usage. This error is very unlikely to occur since the area reserved
>> +for the copy is far larger than the DMAR should be.
>> +
>> +======  ======================
>> +Name:   SL_ERROR_HEAP_DMAR_MAP
>> +Value:  0xc0008013
>> +======  ======================
>> +
>> +Description:
>> +
>> +The backup copy of the ACPI DMAR table in the TXT heap could not be mapped. The
>> +underlying issue is a failure to early_memremap() the DMAR table, most likely
>> +due to a resource shortage.
>> +
>> +======  ====================
>> +Name:   SL_ERROR_HI_PMR_BASE
>> +Value:  0xc0008014
>> +======  ====================
>> +
>> +Description:
>> +
>> +On a system with more than 4G of RAM, the high PMR [2]_ base address should be set
>> +to 4G. This error is due to that not being the case. This PMR value is set by
>> +the pre-launch environment so the issue most likely originates there. It could also
>> +be the sign of an attempted attack.
>> +
>> +======  ====================
>> +Name:   SL_ERROR_HI_PMR_SIZE
>> +Value:  0xc0008015
>> +======  ====================
>> +
>> +Description:
>> +
>> +On a system with more than 4G of RAM, the high PMR [2]_ size should be set to cover
>> +all RAM > 4G. This error is due to that not being the case. This PMR value is
>> +set by the pre-launch environment so the issue most likely originates there. It
>> +could also be the sign of an attempted attack.
>> +
>> +======  ====================
>> +Name:   SL_ERROR_LO_PMR_BASE
>> +Value:  0xc0008016
>> +======  ====================
>> +
>> +Description:
>> +
>> +The low PMR [2]_ base should always be set to address zero. This error is due to
>> +that not being the case. This PMR value is set by the pre-launch environment
>> +so the issue most likely originates there. It could also be the sign of an attempted
>> +attack.
>> +
>> +======  ====================
>> +Name:   SL_ERROR_LO_PMR_MLE
>> +Value:  0xc0008017
>> +======  ====================
>> +
>> +Description:
>> +
>> +This error indicates the MLE image is not covered by the low PMR [2]_ range. The
>> +PMR values are set by the pre-launch environment so the issue most likely originates
>> +there. It could also be the sign of an attempted attack.
>> +
>> +======  =======================
>> +Name:   SL_ERROR_INITRD_TOO_BIG
>> +Value:  0xc0008018
>> +======  =======================
>> +
>> +Description:
>> +
>> +The external initrd provided is larger than 4Gb. This is not a valid
>> +configuration for a Secure Launch due to managing DMA protection.
>> +
>> +======  =========================
>> +Name:   SL_ERROR_HEAP_ZERO_OFFSET
>> +Value:  0xc0008019
>> +======  =========================
>> +
>> +Description:
>> +
>> +During a TXT heap walk an invalid/zero next table offset value was found. This
>> +indicates the TXT heap is malformed. The TXT heap is initialized by the
>> +pre-launch environment so the issue most likely originates there. It could also
>> +be a sign of an attempted attack. In addition, ACM is also responsible for
>> +manipulating parts of the TXT heap so the issue could be due to a bug in the
>> +platform's ACM module.
>> +
>> +======  =============================
>> +Name:   SL_ERROR_WAKE_BLOCK_TOO_SMALL
>> +Value:  0xc000801a
>> +======  =============================
>> +
>> +Description:
>> +
>> +The AP wake block buffer passed to the MLE via the OS-MLE TXT heap table is not
>> +large enough. This value is set by the pre-launch environment so the issue most
>> +likely originates there. It also could be the sign of an attempted attack.
>> +
>> +======  ===========================
>> +Name:   SL_ERROR_MLE_BUFFER_OVERLAP
>> +Value:  0xc000801b
>> +======  ===========================
>> +
>> +Description:
>> +
>> +One of the buffers passed to the MLE via the OS-MLE TXT heap table overlaps
>> +with the MLE image in memory. This value is set by the pre-launch environment
>> +so the issue most likely originates there. It could also be the sign of an attempted
>> +attack.
>> +
>> +======  ==========================
>> +Name:   SL_ERROR_BUFFER_BEYOND_PMR
>> +Value:  0xc000801c
>> +======  ==========================
>> +
>> +Description:
>> +
>> +One of the buffers passed to the MLE via the OS-MLE TXT heap table is not
>> +protected by a PMR. This value is set by the pre-launch environment so the
>> +issue most likey  originates there. It could also be the sign of an attempted
>> +attack.
>> +
>> +======  =============================
>> +Name:   SL_ERROR_OS_SINIT_BAD_VERSION
>> +Value:  0xc000801d
>> +======  =============================
>> +
>> +Description:
>> +
>> +The version of the OS-SINIT TXT heap table is bad. It must be 6 or greater.
>> +This value is set by the pre-launch environment so the issue most likely
>> +originates there. It could also be the sign of an attempted attack. It is also
>> +possible though very unlikely that the platform is so old that the ACM being
>> +used requires an unsupported version.
>> +
>> +======  =====================
>> +Name:   SL_ERROR_EVENTLOG_MAP
>> +Value:  0xc000801e
>> +======  =====================
>> +
>> +Description:
>> +
>> +An error occurred in the Secure Launch module while mapping the TPM event log.
>> +The underlying issue is memremap() failure, most likely due to a resource
>> +shortage.
>> +
>> +======  ========================
>> +Name:   SL_ERROR_TPM_NUMBER_ALGS
>> +Value:  0xc000801f
>> +======  ========================
>> +
>> +Description:
>> +
>> +The TPM 2.0 event log reports an unsupported number of hashing algorithms.
>> +Secure launch currently only supports a maximum of two: SHA1 and SHA256.
>> +
>> +======  ===========================
>> +Name:   SL_ERROR_TPM_UNKNOWN_DIGEST
>> +Value:  0xc0008020
>> +======  ===========================
>> +
>> +Description:
>> +
>> +The TPM 2.0 event log reports an unsupported hashing algorithm. Secure launch
>> +currently only supports two algorithms: SHA1 and SHA256.
>> +
>> +======  ==========================
>> +Name:   SL_ERROR_TPM_INVALID_EVENT
>> +Value:  0xc0008021
>> +======  ==========================
>> +
>> +Description:
>> +
>> +An invalid/malformed event was found in the TPM event log while reading it.
>> +Since only trusted entities are supposed to be writing the event log, this
>> +would indicate either a bug or a possible attack.
>> +
>> +======  =====================
>> +Name:   SL_ERROR_INVALID_SLRT
>> +Value:  0xc0008022
>> +======  =====================
>> +
>> +Description:
>> +
>> +The Secure Launch Resource Table is invalid or malformed and is unusable.
>> +This implies the pre-launch code did not properly setup the SLRT.
>> +
>> +======  ===========================
>> +Name:   SL_ERROR_SLRT_MISSING_ENTRY
>> +Value:  0xc0008023
>> +======  ===========================
>> +
>> +Description:
>> +
>> +The Secure Launch Resource Table is missing a required entry within it.
>> +This implies the pre-launch code did not properly setup the SLRT.
>> +
>> +======  =================
>> +Name:   SL_ERROR_SLRT_MAP
>> +Value:  0xc0008024
>> +======  =================
>> +
>> +Description:
>> +
>> +An error occurred in the Secure Launch module while mapping the Secure Launch
>> +Resource table. The underlying issue is memremap() failure, most likely due to
>> +a resource shortage.
>> +
>> +.. [1]
>> +    MLE: Measured Launch Environment is the binary runtime that is measured and
>> +    then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
>> +    requirements for the MLE in detail.
>> +
>> +.. [2]
>> +    PMR: Intel VTd has a feature in the IOMMU called Protected Memory Registers.
>> +    There are two of these registers and they allow all DMA to be blocked
>> +    to large areas of memory. The low PMR can cover all memory below 4Gb on 2Mb
>> +    boundaries. The high PMR can cover all RAM on the system, again on 2Mb
>> +    boundaries. This feature is used during a Secure Launch by TXT.
>> +
>> +.. [3]
>> +    Secure Launch Specification: https://trenchboot.org/specifications/Secure_Launch/
>> diff --git a/Documentation/security/launch-integrity/secure_launch_overview.rst b/Documentation/security/launch-integrity/secure_launch_overview.rst
>> new file mode 100644
>> index 0000000..ba91d73
>> --- /dev/null
>> +++ b/Documentation/security/launch-integrity/secure_launch_overview.rst
>> @@ -0,0 +1,220 @@
>> +======================
>> +Secure Launch Overview
>> +======================
>> +
>> +Overview
>> +========
>> +
>> +Prior to the start of the TrenchBoot project, the only active Open Source
>> +project supporting dynamic launch was Intel's tboot project to support their
>> +implementation of dynamic launch known as Intel Trusted eXecution Technology
>> +(TXT). The approach taken by tboot was to provide an exokernel that could
>> +handle the launch protocol implemented by Intel's special loader, the SINIT
>> +Authenticated Code Module (ACM [2]_) and remained in memory to manage the SMX
>> +CPU mode that a dynamic launch would put a system. While it is not precluded
>> +from being used for doing a late launch, tboot's primary use case was to be
>> +used as an early launch solution. As a result the TrenchBoot project started
>> +the development of Secure Launch kernel feature to provide a more generalized
>> +approach. The focus of the effort is twofold, the first is to make the Linux
>> +kernel directly aware of the launch protocol used by Intel, AMD/Hygon, Arm, and
>> +potentially OpenPOWER. The second is to make the Linux kernel be able to
>> +initiate a dynamic launch. It is through this approach that the Secure Launch
>> +kernel feature creates a basis for the Linux kernel to be used in a variety of
>> +dynamic launch use cases.
>> +
>> +.. note::
>> +    A quick note on terminology. The larger open source project itself is
>> +    called TrenchBoot, which is hosted on GitHub (links below). The kernel
>> +    feature enabling the use of the x86 technology is referred to as "Secure
>> +    Launch" within the kernel code.
>> +
>> +Goals
>> +=====
>> +
>> +The first use case that the TrenchBoot project focused on was the ability for
>> +the Linux kernel to be started by a dynamic launch, in particular as part of an
>> +early launch sequence. In this case the dynamic launch will be initiated by any
>> +boot loader with associated support added to it, for example the first targeted
>> +boot loader in this case was GRUB2. An integral part of establishing a
>> +measurement-based launch integrity involves measuring everything that is
>> +intended to be executed (kernel image, initrd, etc) and everything that will
>> +configure that kernel to execute (command line, boot params, etc). Then storing
>> +those measurements in a protected manner. Both the Intel and AMD dynamic launch
>> +implementations leverage the Trusted Platform Module (TPM) to store those
>> +measurements. The TPM itself has been designed such that a dynamic launch
>> +unlocks a specific set of Platform Configuration Registers (PCR) for holding
>> +measurement taken during the dynamic launch.  These are referred to as the DRTM
>> +PCRs, PCRs 17-22. Further details on this process can be found in the
>> +documentation for the GETSEC instruction provided by Intel's TXT and the SKINIT
>> +instruction provided by AMD's AMD-V. The documentation on these technologies
>> +can be readily found online; see the `Resources`_ section below for references.
>> +
>> +.. note::
>> +    Currently only Intel TXT is supported in this first release of the Secure
>> +    Launch feature. AMD/Hygon SKINIT and Arm support will be added in a
>> +    subsequent release.
>> +
>> +To enable the kernel to be launched by GETSEC a stub, the Secure Launch stub,
>> +must be built into the setup section of the compressed kernel to handle the
>> +specific state that the dynamic launch process leaves the BSP. Also the Secure
>> +Launch stub must measure everything that is going to be used as early as
>> +possible. This stub code and subsequent code must also deal with the specific
>> +state that the dynamic launch leaves the APs as well.
>> +
>> +Design Decisions
>> +================
>> +
>> +A number of design decisions were made during the development of the Secure
>> +Launch feature. The two primary guiding decisions were:
>> +
>> + - Keeping the Secure Launch code as separate from the rest of the kernel
>> +   as possible.
>> + - Modifying the existing boot path of the kernel as little as possible.
>> +
>> +The following illustrate how the implementation followed these design
>> +decisions:
>> +
>> + - All the entry point code necessary to properly configure the system post
>> +   launch is found in st_stub.S in the compressed kernel image. This code
>> +   validates the state of the system, restores necessary system operating
>> +   configurations and properly handles post launch CPU states.
>> + - After the sl_stub.S is complete, it jumps directly to the unmodified
>> +   startup_32 kernel entry point.
>> + - A single call is made to a function sl_main() prior to the main kernel
>> +   decompression step. This code performs further validation and takes the
>> +   needed DRTM measurements.
>> + - After the call to sl_main(), the main kernel is decompressed and boots as
>> +   it normally would.
>> + - Final setup for the Secure Launch kernel is done in a separate Secure
>> +   Launch module that is loaded via a late initcall. This code is responsible
>> +   for extending the measurements taken earlier into the TPM DRTM PCRs and
>> +   setting up the securityfs interface to allow access the TPM event log and
>> +   public TXT registers.
>> + - On the reboot and kexec paths, calls are made to a function to finalize the
>> +   state of the Secure Launch kernel.
>> +
>> +The one place where Secure Launch code is mixed directly in with kernel code is
>> +in the SMP boot code. This is due to the unique state that the dynamic launch
>> +leaves the APs in. On Intel this involves using a method other than the
>> +standard INIT-SIPI sequence.
>> +
>> +A final note is that originally the extending of the PCRs was completed in the
>> +Secure Launch stub when the measurements were taken. An alternative solution
>> +had to be implemented due to the TPM maintainers objecting to the PCR
>> +extensions being done with a minimal interface to the TPM that was an
>> +independent implementation of the mainline kernel driver. Since the mainline
>> +driver relies heavily on kernel interfaces not available in the compressed
>> +kernel, it was not possible to reuse the mainline TPM driver. This resulted in
>> +the decision to move the extension operations to the Secure Launch module in
>> +the mainline kernel where the TPM driver would be available.
>> +
>> +Basic Boot Flow
>> +===============
>> +
>> +Outlined here is summary of the boot flow for Secure Launch. A more detailed
>> +review of Secure Launch process can be found in the Secure Launch
>> +Specification, a link is located in the `Resources`_ section.
>> +
>> +Pre-launch: *Phase where the environment is prepared and configured to initiate the
>> +secure launch by the boot chain.*
>> +
>> + - The SLRT is initialized and dl_stub is placed in memory.
>> + - Load the kernel, initrd and ACM [2]_ into memory.
>> + - Setup the TXT heap and page tables describing the MLE [1]_ per the
>> +   specification.
>> + - If non-UEFI platform, dl_stub is called.
>> + - If UEFI platforms, SLRT registered with UEFI and efi-stub called.
>> + - Upon completion, efi-stub will call EBS followed by dl_stub.
>> + - The dl_stub will prepare the CPU and the TPM for the launch.
>> + - The secure launch is then initiated with the GETSET[SENTER] instruction.
>> +
>> +Post-launch: *Phase where control is passed from the ACM to the MLE and the secure
>> +kernel begins execution.*
>> +
>> + - Entry from the dynamic launch jumps to the SL stub.
>> + - SL stub fixes up the world on the BSP.
>> + - For TXT, SL stub wakes the APs, fixes up their worlds.
>> + - For TXT, APs are left halted waiting for an NMI to wake them.
>> + - SL stub jumps to startup_32.
>> + - SL main does validation of buffers and memory locations. It sets
>> +   the boot parameter loadflag value SLAUNCH_FLAG to inform the main
>> +   kernel that a Secure Launch was done.
>> + - SL main locates the TPM event log and writes the measurements of
>> +   configuration and module information into it.
>> + - Kernel boot proceeds normally from this point.
>> + - During early setup, slaunch_setup() runs to finish some validation
>> +   and setup tasks.
>> + - The SMP bring up code is modified to wake the waiting APs. APs vector
>> +   to rmpiggy and start up normally from that point.
>> + - SL platform module is registered as a late initcall module. It reads
>> +   the TPM event log and extends the measurements taken into the TPM PCRs.
>> + - SL platform module initializes the securityfs interface to allow
>> +   access to the TPM event log and TXT public registers.
>> + - Kernel boot finishes booting normally
>> + - SEXIT support to leave SMX mode is present on the kexec path and
>> +   the various reboot paths (poweroff, reset, halt).
>> +
>> +PCR Usage
>> +=========
>> +
>> +The TCG DRTM architecture there are three PCRs defined for usage, PCR.Details
>> +(PCR17), PCR.Authorities (PCR18), and PCR.DLME_Authority (PCR19). For a deeper
>> +understanding of Detail and Authorities it is recommended to review the TCG
>> +DRTM architecture.
>> +
>> +To determine PCR usage, Linux Secure Launch follows the TrenchBoot Secure
>> +Launch Specification of using a measurement policy stored in the SLRT. The
>> +policy details what should be measured and the PCR in which to store the
>> +measurement. The measurement policy provides the ability to select the
>> +PCR.DLME_Detail (PCR20) PCR as the location for the DRTM components measured by
>> +the kernel, e.g. external initrd image. This can then be combined with storing
>> +the user authority in the PCR.DLME_Authority PCR to seal/attest to different
>> +variations of platform details/authorities and user details/authorities. An
>> +example of how this can be achieved was presented in the FOSDEM - 2021 talk
>> +"Secure Upgrades with DRTM".
>> +
>> +Resources
>> +=========
>> +
>> +The TrenchBoot project:
>> +
>> +https://trenchboot.org
>> +
>> +Secure Launch Specification:
>> +
>> +https://trenchboot.org/specifications/Secure_Launch/
>> +
>> +Trusted Computing Group's D-RTM Architecture:
>> +
>> +https://trustedcomputinggroup.org/wp-content/uploads/TCG_D-RTM_Architecture_v1-0_Published_06172013.pdf
>> +
>> +TXT documentation in the Intel TXT MLE Development Guide:
>> +
>> +https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
>> +
>> +TXT instructions documentation in the Intel SDM Instruction Set volume:
>> +
>> +https://software.intel.com/en-us/articles/intel-sdm
>> +
>> +AMD SKINIT documentation in the System Programming manual:
>> +
>> +https://www.amd.com/system/files/TechDocs/24593.pdf
>> +
>> +GRUB Secure Launch support:
>> +
>> +https://github.com/TrenchBoot/grub/tree/grub-sl-fc-38-dlstub
>> +
>> +FOSDEM 2021: Secure Upgrades with DRTM
>> +
>> +https://archive.fosdem.org/2021/schedule/event/firmware_suwd/
>> +
>> +.. [1]
>> +    MLE: Measured Launch Environment is the binary runtime that is measured and
>> +    then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
>> +    requirements for the MLE in detail.
>> +
>> +.. [2]
>> +    ACM: Intel's Authenticated Code Module. This is the 32b bit binary blob that
>> +    is run securely by the GETSEC[SENTER] during a measured launch. It is described
>> +    in the Intel documentation on TXT and versions for various chipsets are
>> +    signed and distributed by Intel.
>   
> The formatting LGTM, thanks!
> 
> Regardless,
> 
> Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com>

Thank you,
Ross

> 


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-10  1:21     ` Eric Biggers
@ 2023-05-10 22:28       ` Jarkko Sakkinen
  -1 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-10 22:28 UTC (permalink / raw)
  To: Eric Biggers, Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Wed May 10, 2023 at 4:21 AM EEST, Eric Biggers wrote:
> On Thu, May 04, 2023 at 02:50:15PM +0000, Ross Philipson wrote:
> > From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
> > 
> > The SHA algorithms are necessary to measure configuration information into
> > the TPM as early as possible before using the values. This implementation
> > uses the established approach of #including the SHA libraries directly in
> > the code since the compressed kernel is not uncompressed at this point.
> > 
> > The SHA code here has its origins in the code from the main kernel:
> > 
> > commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")
> > 
> > That code could not be pulled directly into the setup portion of the
> > compressed kernel because of other dependencies it pulls in. The result
> > is this is a modified copy of that code that still leverages the core
> > SHA algorithms.
> > 
> > Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> > Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>
> SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> now?
>
> And if you absolutely MUST use SHA-1 despite it being insecure, please at least
> don't obfuscate it by calling it simply "SHA".

AFAIK the TCG specs require for any TPM2 implementation to support both
SHA-1 and SHA-256, so this as a new feature should lock in to the
latter.

BR, Jarkko

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-10 22:28       ` Jarkko Sakkinen
  0 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-10 22:28 UTC (permalink / raw)
  To: Eric Biggers, Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	mjg59, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Wed May 10, 2023 at 4:21 AM EEST, Eric Biggers wrote:
> On Thu, May 04, 2023 at 02:50:15PM +0000, Ross Philipson wrote:
> > From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
> > 
> > The SHA algorithms are necessary to measure configuration information into
> > the TPM as early as possible before using the values. This implementation
> > uses the established approach of #including the SHA libraries directly in
> > the code since the compressed kernel is not uncompressed at this point.
> > 
> > The SHA code here has its origins in the code from the main kernel:
> > 
> > commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")
> > 
> > That code could not be pulled directly into the setup portion of the
> > compressed kernel because of other dependencies it pulls in. The result
> > is this is a modified copy of that code that still leverages the core
> > SHA algorithms.
> > 
> > Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> > Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>
> SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> now?
>
> And if you absolutely MUST use SHA-1 despite it being insecure, please at least
> don't obfuscate it by calling it simply "SHA".

AFAIK the TCG specs require for any TPM2 implementation to support both
SHA-1 and SHA-256, so this as a new feature should lock in to the
latter.

BR, Jarkko

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 12/14] x86: Secure Launch late initcall platform module
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-10 22:39     ` Jarkko Sakkinen
  -1 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-10 22:39 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>
> The Secure Launch platform module is a late init module. During the
> init call, the TPM event log is read and measurements taken in the
> early boot stub code are located. These measurements are extended
> into the TPM PCRs using the mainline TPM kernel driver.
>
> The platform module also registers the securityfs nodes to allow
> access to TXT register fields on Intel along with the fetching of
> and writing events to the late launch TPM log.
>
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  arch/x86/kernel/Makefile   |   1 +
>  arch/x86/kernel/slmodule.c | 520 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 521 insertions(+)
>  create mode 100644 arch/x86/kernel/slmodule.c
>
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index 3d2a33e..ee3fe300 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -73,6 +73,7 @@ obj-$(CONFIG_IA32_EMULATION)	+= tls.o
>  obj-y				+= step.o
>  obj-$(CONFIG_INTEL_TXT)		+= tboot.o
>  obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
> +obj-$(CONFIG_SECURE_LAUNCH)	+= slmodule.o
>  obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
>  obj-y				+= stacktrace.o
>  obj-y				+= cpu/
> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
> new file mode 100644
> index 0000000..70dcff5
> --- /dev/null
> +++ b/arch/x86/kernel/slmodule.c
> @@ -0,0 +1,520 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Secure Launch late validation/setup, securityfs exposure and
> + * finalization support.
> + *
> + * Copyright (c) 2022 Apertus Solutions, LLC
> + * Copyright (c) 2021 Assured Information Security, Inc.
> + * Copyright (c) 2022, Oracle and/or its affiliates.
> + *
> + * Author(s):
> + *     Daniel P. Smith <dpsmith@apertussolutions.com>
> + *     Garnet T. Grimm <grimmg@ainfosec.com>

I'm not sure what the authors list is good for in the days of Git,
and all the tags we have for commit messages.

Instead of this you could just put to the commit:

Co-developed-by: Garnet T. Grimm <grimmg@ainfosec.com>
Signed-off-by: Garnet T. Grimm <grimmg@ainfosec.com>
Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>

See:

https://www.kernel.org/doc/html/latest/process/submitting-patches.html#when-to-use-acked-by-cc-and-co-developed-by

> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/fs.h>
> +#include <linux/init.h>
> +#include <linux/linkage.h>
> +#include <linux/mm.h>
> +#include <linux/io.h>
> +#include <linux/uaccess.h>
> +#include <linux/security.h>
> +#include <linux/memblock.h>
> +#include <asm/segment.h>
> +#include <asm/sections.h>
> +#include <crypto/sha2.h>
> +#include <linux/slr_table.h>
> +#include <linux/slaunch.h>
> +
> +#define DECLARE_TXT_PUB_READ_U(size, fmt, msg_size)			\
> +static ssize_t txt_pub_read_u##size(unsigned int offset,		\
> +		loff_t *read_offset,					\
> +		size_t read_len,					\
> +		char __user *buf)					\

This would really deserve:

/*
 * Explain what DECLARE_TXT_PUB_READ_U is.
 */

> +{									\
> +	void __iomem *txt;						\
> +	char msg_buffer[msg_size];					\

Reverse-christmas tree order.

> +	u##size reg_value = 0;						\
> +	txt = ioremap(TXT_PUB_CONFIG_REGS_BASE,				\
> +			TXT_NR_CONFIG_PAGES * PAGE_SIZE);		\
> +	if (!txt)						\
> +		return -EFAULT;					\
> +	memcpy_fromio(&reg_value, txt + offset, sizeof(u##size));	\
> +	iounmap(txt);							\
> +	snprintf(msg_buffer, msg_size, fmt, reg_value);			\
> +	return simple_read_from_buffer(buf, read_len, read_offset,	\
> +			&msg_buffer, msg_size);				\
> +}
> +
> +DECLARE_TXT_PUB_READ_U(8, "%#04x\n", 6);
> +DECLARE_TXT_PUB_READ_U(32, "%#010x\n", 12);
> +DECLARE_TXT_PUB_READ_U(64, "%#018llx\n", 20);
> +
> +#define DECLARE_TXT_FOPS(reg_name, reg_offset, reg_size)		\
> +static ssize_t txt_##reg_name##_read(struct file *flip,			\
> +		char __user *buf, size_t read_len, loff_t *read_offset)	\
> +{									\
> +	return txt_pub_read_u##reg_size(reg_offset, read_offset,	\
> +			read_len, buf);					\
> +}									\
> +static const struct file_operations reg_name##_ops = {			\
> +	.read = txt_##reg_name##_read,					\
> +}
> +
> +DECLARE_TXT_FOPS(sts, TXT_CR_STS, 64);
> +DECLARE_TXT_FOPS(ests, TXT_CR_ESTS, 8);
> +DECLARE_TXT_FOPS(errorcode, TXT_CR_ERRORCODE, 32);
> +DECLARE_TXT_FOPS(didvid, TXT_CR_DIDVID, 64);
> +DECLARE_TXT_FOPS(e2sts, TXT_CR_E2STS, 64);
> +DECLARE_TXT_FOPS(ver_emif, TXT_CR_VER_EMIF, 32);
> +DECLARE_TXT_FOPS(scratchpad, TXT_CR_SCRATCHPAD, 64);
> +
> +/*
> + * Securityfs exposure
> + */
> +struct memfile {
> +	char *name;
> +	void *addr;
> +	size_t size;
> +};
> +
> +static struct memfile sl_evtlog = {"eventlog", 0, 0};
> +static void *txt_heap;
> +static struct txt_heap_event_log_pointer2_1_element __iomem *evtlog20;
> +static DEFINE_MUTEX(sl_evt_log_mutex);
> +
> +static ssize_t sl_evtlog_read(struct file *file, char __user *buf,
> +			      size_t count, loff_t *pos)
> +{
> +	ssize_t size;
> +
> +	if (!sl_evtlog.addr)
> +		return 0;
> +
> +	mutex_lock(&sl_evt_log_mutex);
> +	size = simple_read_from_buffer(buf, count, pos, sl_evtlog.addr,
> +				       sl_evtlog.size);
> +	mutex_unlock(&sl_evt_log_mutex);
> +
> +	return size;
> +}
> +
> +static ssize_t sl_evtlog_write(struct file *file, const char __user *buf,
> +				size_t datalen, loff_t *ppos)
> +{
> +	ssize_t result;
> +	char *data;
> +
> +	if (!sl_evtlog.addr)
> +		return 0;
> +
> +	/* No partial writes. */
> +	result = -EINVAL;
> +	if (*ppos != 0)
> +		goto out;
> +
> +	data = memdup_user(buf, datalen);
> +	if (IS_ERR(data)) {
> +		result = PTR_ERR(data);
> +		goto out;
> +	}
> +
> +	mutex_lock(&sl_evt_log_mutex);
> +	if (evtlog20)
> +		result = tpm20_log_event(evtlog20, sl_evtlog.addr,
> +					 sl_evtlog.size, datalen, data);
> +	else
> +		result = tpm12_log_event(sl_evtlog.addr, sl_evtlog.size,
> +					 datalen, data);
> +	mutex_unlock(&sl_evt_log_mutex);
> +
> +	kfree(data);
> +out:
> +	return result;
> +}
> +
> +static const struct file_operations sl_evtlog_ops = {
> +	.read = sl_evtlog_read,
> +	.write = sl_evtlog_write,
> +	.llseek	= default_llseek,
> +};
> +
> +struct sfs_file {
> +	const char *name;
> +	const struct file_operations *fops;
> +};
> +
> +#define SL_TXT_ENTRY_COUNT	7
> +static const struct sfs_file sl_txt_files[] = {
> +	{ "sts", &sts_ops },
> +	{ "ests", &ests_ops },
> +	{ "errorcode", &errorcode_ops },
> +	{ "didvid", &didvid_ops },
> +	{ "ver_emif", &ver_emif_ops },
> +	{ "scratchpad", &scratchpad_ops },
> +	{ "e2sts", &e2sts_ops }
> +};
> +
> +/* sysfs file handles */
> +static struct dentry *slaunch_dir;
> +static struct dentry *event_file;
> +static struct dentry *txt_dir;
> +static struct dentry *txt_entries[SL_TXT_ENTRY_COUNT];
> +
> +static long slaunch_expose_securityfs(void)
> +{
> +	long ret = 0;
> +	int i;
> +
> +	slaunch_dir = securityfs_create_dir("slaunch", NULL);
> +	if (IS_ERR(slaunch_dir))
> +		return PTR_ERR(slaunch_dir);
> +
> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> +		txt_dir = securityfs_create_dir("txt", slaunch_dir);
> +		if (IS_ERR(txt_dir)) {
> +			ret = PTR_ERR(txt_dir);
> +			goto remove_slaunch;
> +		}
> +
> +		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++) {
> +			txt_entries[i] = securityfs_create_file(
> +						sl_txt_files[i].name, 0440,
> +						txt_dir, NULL,
> +						sl_txt_files[i].fops);
> +			if (IS_ERR(txt_entries[i])) {
> +				ret = PTR_ERR(txt_entries[i]);
> +				goto remove_files;
> +			}
> +		}
> +
> +	}
> +
> +	if (sl_evtlog.addr > 0) {
> +		event_file = securityfs_create_file(
> +					sl_evtlog.name, 0440,
> +					slaunch_dir, NULL,
> +					&sl_evtlog_ops);
> +		if (IS_ERR(event_file)) {
> +			ret = PTR_ERR(event_file);
> +			goto remove_files;
> +		}
> +	}
> +
> +	return 0;
> +
> +remove_files:
> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> +		while (--i >= 0)
> +			securityfs_remove(txt_entries[i]);
> +		securityfs_remove(txt_dir);
> +	}
> +remove_slaunch:
> +	securityfs_remove(slaunch_dir);
> +
> +	return ret;
> +}
> +
> +static void slaunch_teardown_securityfs(void)
> +{
> +	int i;
> +
> +	securityfs_remove(event_file);
> +	if (sl_evtlog.addr) {
> +		memunmap(sl_evtlog.addr);
> +		sl_evtlog.addr = NULL;
> +	}
> +	sl_evtlog.size = 0;
> +
> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> +		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++)
> +			securityfs_remove(txt_entries[i]);
> +
> +		securityfs_remove(txt_dir);
> +
> +		if (txt_heap) {
> +			memunmap(txt_heap);
> +			txt_heap = NULL;
> +		}
> +	}
> +
> +	securityfs_remove(slaunch_dir);
> +}
> +
> +static void slaunch_intel_evtlog(void __iomem *txt)
> +{
> +	struct slr_entry_log_info *log_info;
> +	struct txt_os_mle_data *params;
> +	struct slr_table *slrt;
> +	void *os_sinit_data;
> +	u64 base, size;
> +
> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
> +
> +	/* now map TXT heap */
> +	txt_heap = memremap(base, size, MEMREMAP_WB);
> +	if (!txt_heap)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap TXT heap\n",
> +			SL_ERROR_HEAP_MAP);
> +
> +	params = (struct txt_os_mle_data *)txt_os_mle_data_start(txt_heap);
> +
> +	/* Get the SLRT and remap it */
> +	slrt = memremap(params->slrt, sizeof(*slrt), MEMREMAP_WB);
> +	if (!slrt)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap SLR Table\n",
> +			SL_ERROR_SLRT_MAP);
> +	size = slrt->size;
> +	memunmap(slrt);
> +
> +	slrt = memremap(params->slrt, size, MEMREMAP_WB);
> +	if (!slrt)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap SLR Table\n",
> +			SL_ERROR_SLRT_MAP);
> +
> +	log_info = (struct slr_entry_log_info *)
> +			slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
> +	if (!log_info)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap SLR Table\n",
> +			SL_ERROR_SLRT_MISSING_ENTRY);
> +
> +	sl_evtlog.size = log_info->size;
> +	sl_evtlog.addr = memremap(log_info->addr, log_info->size,
> +				  MEMREMAP_WB);
> +	if (!sl_evtlog.addr)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap TPM event log\n",
> +			SL_ERROR_EVENTLOG_MAP);
> +
> +	memunmap(slrt);
> +
> +	/* Determine if this is TPM 1.2 or 2.0 event log */
> +	if (memcmp(sl_evtlog.addr + sizeof(struct tcg_pcr_event),
> +		    TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
> +		return; /* looks like it is not 2.0 */
> +
> +	/* For TPM 2.0 logs, the extended heap element must be located */
> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
> +
> +	evtlog20 = tpm20_find_log2_1_element(os_sinit_data);
> +
> +	/*
> +	 * If this fails, things are in really bad shape. Any attempt to write
> +	 * events to the log will fail.
> +	 */
> +	if (!evtlog20)
> +		slaunch_txt_reset(txt,
> +			"Error failed to find TPM20 event log element\n",
> +			SL_ERROR_TPM_INVALID_LOG20);
> +}
> +
> +static void slaunch_tpm20_extend_event(struct tpm_chip *tpm, void __iomem *txt,
> +				       struct tcg_pcr_event2_head *event)
> +{
> +	u16 *alg_id_field = (u16 *)((u8 *)event +
> +				    sizeof(struct tcg_pcr_event2_head));
> +	struct tpm_digest *digests;
> +	u8 *dptr;
> +	int ret;
> +	u32 i, j;
> +
> +	digests = kcalloc(tpm->nr_allocated_banks, sizeof(*digests),
> +			  GFP_KERNEL);
> +	if (!digests)
> +		slaunch_txt_reset(txt,
> +			"Failed to allocate array of digests\n",
> +			SL_ERROR_GENERIC);
> +
> +	for (i = 0; i < tpm->nr_allocated_banks; i++)
> +		digests[i].alg_id = tpm->allocated_banks[i].alg_id;
> +
> +
> +	/* Early SL code ensured there was a max count of 2 digests */
> +	for (i = 0; i < event->count; i++) {
> +		dptr = (u8 *)alg_id_field + sizeof(u16);
> +
> +		for (j = 0; j < tpm->nr_allocated_banks; j++) {
> +			if (digests[j].alg_id != *alg_id_field)
> +				continue;
> +
> +			switch (digests[j].alg_id) {
> +			case TPM_ALG_SHA256:
> +				memcpy(&digests[j].digest[0], dptr,
> +				       SHA256_DIGEST_SIZE);
> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
> +					SHA256_DIGEST_SIZE + sizeof(u16));
> +				break;
> +			case TPM_ALG_SHA1:
> +				memcpy(&digests[j].digest[0], dptr,
> +				       SHA1_DIGEST_SIZE);
> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
> +					SHA1_DIGEST_SIZE + sizeof(u16));
> +			default:
> +				break;
> +			}
> +		}
> +	}
> +
> +	ret = tpm_pcr_extend(tpm, event->pcr_idx, digests);
> +	if (ret) {
> +		pr_err("Error extending TPM20 PCR, result: %d\n", ret);
> +		slaunch_txt_reset(txt,
> +			"Failed to extend TPM20 PCR\n",
> +			SL_ERROR_TPM_EXTEND);
> +	}
> +
> +	kfree(digests);
> +}
> +
> +static void slaunch_tpm20_extend(struct tpm_chip *tpm, void __iomem *txt)
> +{
> +	struct tcg_pcr_event *event_header;
> +	struct tcg_pcr_event2_head *event;
> +	int start = 0, end = 0, size;
> +
> +	event_header = (struct tcg_pcr_event *)(sl_evtlog.addr +
> +						evtlog20->first_record_offset);
> +
> +	/* Skip first TPM 1.2 event to get to first TPM 2.0 event */
> +	event = (struct tcg_pcr_event2_head *)((u8 *)event_header +
> +						sizeof(struct tcg_pcr_event) +
> +						event_header->event_size);
> +
> +	while ((void  *)event < sl_evtlog.addr + evtlog20->next_record_offset) {
> +		size = __calc_tpm2_event_size(event, event_header, false);
> +		if (!size)
> +			slaunch_txt_reset(txt,
> +				"TPM20 invalid event in event log\n",
> +				SL_ERROR_TPM_INVALID_EVENT);
> +
> +		/*
> +		 * Marker events indicate where the Secure Launch early stub
> +		 * started and ended adding post launch events.
> +		 */
> +		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
> +			end = 1;
> +			break;
> +		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
> +			start = 1;
> +			goto next;
> +		}
> +
> +		if (start)
> +			slaunch_tpm20_extend_event(tpm, txt, event);
> +
> +next:
> +		event = (struct tcg_pcr_event2_head *)((u8 *)event + size);
> +	}
> +
> +	if (!start || !end)
> +		slaunch_txt_reset(txt,
> +			"Missing start or end events for extending TPM20 PCRs\n",
> +			SL_ERROR_TPM_EXTEND);
> +}
> +
> +static void slaunch_tpm12_extend(struct tpm_chip *tpm, void __iomem *txt)
> +{
> +	struct tpm12_event_log_header *event_header;
> +	struct tcg_pcr_event *event;
> +	struct tpm_digest digest;
> +	int start = 0, end = 0;
> +	int size, ret;
> +
> +	event_header = (struct tpm12_event_log_header *)sl_evtlog.addr;
> +	event = (struct tcg_pcr_event *)((u8 *)event_header +
> +				sizeof(struct tpm12_event_log_header));
> +
> +	while ((void  *)event < sl_evtlog.addr + event_header->next_event_offset) {
> +		size = sizeof(struct tcg_pcr_event) + event->event_size;
> +
> +		/*
> +		 * Marker events indicate where the Secure Launch early stub
> +		 * started and ended adding post launch events.
> +		 */
> +		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
> +			end = 1;
> +			break;
> +		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
> +			start = 1;
> +			goto next;
> +		}
> +
> +		if (start) {
> +			memset(&digest.digest[0], 0, TPM_MAX_DIGEST_SIZE);
> +			digest.alg_id = TPM_ALG_SHA1;
> +			memcpy(&digest.digest[0], &event->digest[0],
> +			       SHA1_DIGEST_SIZE);
> +
> +			ret = tpm_pcr_extend(tpm, event->pcr_idx, &digest);
> +			if (ret) {
> +				pr_err("Error extending TPM12 PCR, result: %d\n", ret);
> +				slaunch_txt_reset(txt,
> +					"Failed to extend TPM12 PCR\n",
> +					SL_ERROR_TPM_EXTEND);
> +			}
> +		}
> +
> +next:
> +		event = (struct tcg_pcr_event *)((u8 *)event + size);
> +	}
> +
> +	if (!start || !end)
> +		slaunch_txt_reset(txt,
> +			"Missing start or end events for extending TPM12 PCRs\n",
> +			SL_ERROR_TPM_EXTEND);
> +}
> +
> +static void slaunch_pcr_extend(void __iomem *txt)
> +{
> +	struct tpm_chip *tpm;
> +
> +	tpm = tpm_default_chip();
> +	if (!tpm)
> +		slaunch_txt_reset(txt,
> +			"Could not get default TPM chip\n",
> +			SL_ERROR_TPM_INIT);
> +	if (evtlog20)
> +		slaunch_tpm20_extend(tpm, txt);
> +	else
> +		slaunch_tpm12_extend(tpm, txt);
> +}
> +
> +static int __init slaunch_module_init(void)
> +{
> +	void __iomem *txt;
> +
> +	/* Check to see if Secure Launch happened */
> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
> +	    (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT))
> +		return 0;
> +
> +	txt = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
> +		      PAGE_SIZE);
> +	if (!txt)
> +		panic("Error ioremap of TXT priv registers\n");
> +
> +	/* Only Intel TXT is supported at this point */
> +	slaunch_intel_evtlog(txt);
> +
> +	slaunch_pcr_extend(txt);
> +
> +	iounmap(txt);

I would remove the empty lines in-between the three calls above.

> +
> +	return slaunch_expose_securityfs();
> +}
> +
> +static void __exit slaunch_module_exit(void)
> +{
> +	slaunch_teardown_securityfs();
> +}
> +
> +late_initcall(slaunch_module_init);
> +

I would remove this empty line.

> +__exitcall(slaunch_module_exit);
> -- 
> 1.8.3.1


BR, Jarkko

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

* Re: [PATCH v6 12/14] x86: Secure Launch late initcall platform module
@ 2023-05-10 22:39     ` Jarkko Sakkinen
  0 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-10 22:39 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>
> The Secure Launch platform module is a late init module. During the
> init call, the TPM event log is read and measurements taken in the
> early boot stub code are located. These measurements are extended
> into the TPM PCRs using the mainline TPM kernel driver.
>
> The platform module also registers the securityfs nodes to allow
> access to TXT register fields on Intel along with the fetching of
> and writing events to the late launch TPM log.
>
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  arch/x86/kernel/Makefile   |   1 +
>  arch/x86/kernel/slmodule.c | 520 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 521 insertions(+)
>  create mode 100644 arch/x86/kernel/slmodule.c
>
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index 3d2a33e..ee3fe300 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -73,6 +73,7 @@ obj-$(CONFIG_IA32_EMULATION)	+= tls.o
>  obj-y				+= step.o
>  obj-$(CONFIG_INTEL_TXT)		+= tboot.o
>  obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
> +obj-$(CONFIG_SECURE_LAUNCH)	+= slmodule.o
>  obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
>  obj-y				+= stacktrace.o
>  obj-y				+= cpu/
> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
> new file mode 100644
> index 0000000..70dcff5
> --- /dev/null
> +++ b/arch/x86/kernel/slmodule.c
> @@ -0,0 +1,520 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Secure Launch late validation/setup, securityfs exposure and
> + * finalization support.
> + *
> + * Copyright (c) 2022 Apertus Solutions, LLC
> + * Copyright (c) 2021 Assured Information Security, Inc.
> + * Copyright (c) 2022, Oracle and/or its affiliates.
> + *
> + * Author(s):
> + *     Daniel P. Smith <dpsmith@apertussolutions.com>
> + *     Garnet T. Grimm <grimmg@ainfosec.com>

I'm not sure what the authors list is good for in the days of Git,
and all the tags we have for commit messages.

Instead of this you could just put to the commit:

Co-developed-by: Garnet T. Grimm <grimmg@ainfosec.com>
Signed-off-by: Garnet T. Grimm <grimmg@ainfosec.com>
Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>

See:

https://www.kernel.org/doc/html/latest/process/submitting-patches.html#when-to-use-acked-by-cc-and-co-developed-by

> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/fs.h>
> +#include <linux/init.h>
> +#include <linux/linkage.h>
> +#include <linux/mm.h>
> +#include <linux/io.h>
> +#include <linux/uaccess.h>
> +#include <linux/security.h>
> +#include <linux/memblock.h>
> +#include <asm/segment.h>
> +#include <asm/sections.h>
> +#include <crypto/sha2.h>
> +#include <linux/slr_table.h>
> +#include <linux/slaunch.h>
> +
> +#define DECLARE_TXT_PUB_READ_U(size, fmt, msg_size)			\
> +static ssize_t txt_pub_read_u##size(unsigned int offset,		\
> +		loff_t *read_offset,					\
> +		size_t read_len,					\
> +		char __user *buf)					\

This would really deserve:

/*
 * Explain what DECLARE_TXT_PUB_READ_U is.
 */

> +{									\
> +	void __iomem *txt;						\
> +	char msg_buffer[msg_size];					\

Reverse-christmas tree order.

> +	u##size reg_value = 0;						\
> +	txt = ioremap(TXT_PUB_CONFIG_REGS_BASE,				\
> +			TXT_NR_CONFIG_PAGES * PAGE_SIZE);		\
> +	if (!txt)						\
> +		return -EFAULT;					\
> +	memcpy_fromio(&reg_value, txt + offset, sizeof(u##size));	\
> +	iounmap(txt);							\
> +	snprintf(msg_buffer, msg_size, fmt, reg_value);			\
> +	return simple_read_from_buffer(buf, read_len, read_offset,	\
> +			&msg_buffer, msg_size);				\
> +}
> +
> +DECLARE_TXT_PUB_READ_U(8, "%#04x\n", 6);
> +DECLARE_TXT_PUB_READ_U(32, "%#010x\n", 12);
> +DECLARE_TXT_PUB_READ_U(64, "%#018llx\n", 20);
> +
> +#define DECLARE_TXT_FOPS(reg_name, reg_offset, reg_size)		\
> +static ssize_t txt_##reg_name##_read(struct file *flip,			\
> +		char __user *buf, size_t read_len, loff_t *read_offset)	\
> +{									\
> +	return txt_pub_read_u##reg_size(reg_offset, read_offset,	\
> +			read_len, buf);					\
> +}									\
> +static const struct file_operations reg_name##_ops = {			\
> +	.read = txt_##reg_name##_read,					\
> +}
> +
> +DECLARE_TXT_FOPS(sts, TXT_CR_STS, 64);
> +DECLARE_TXT_FOPS(ests, TXT_CR_ESTS, 8);
> +DECLARE_TXT_FOPS(errorcode, TXT_CR_ERRORCODE, 32);
> +DECLARE_TXT_FOPS(didvid, TXT_CR_DIDVID, 64);
> +DECLARE_TXT_FOPS(e2sts, TXT_CR_E2STS, 64);
> +DECLARE_TXT_FOPS(ver_emif, TXT_CR_VER_EMIF, 32);
> +DECLARE_TXT_FOPS(scratchpad, TXT_CR_SCRATCHPAD, 64);
> +
> +/*
> + * Securityfs exposure
> + */
> +struct memfile {
> +	char *name;
> +	void *addr;
> +	size_t size;
> +};
> +
> +static struct memfile sl_evtlog = {"eventlog", 0, 0};
> +static void *txt_heap;
> +static struct txt_heap_event_log_pointer2_1_element __iomem *evtlog20;
> +static DEFINE_MUTEX(sl_evt_log_mutex);
> +
> +static ssize_t sl_evtlog_read(struct file *file, char __user *buf,
> +			      size_t count, loff_t *pos)
> +{
> +	ssize_t size;
> +
> +	if (!sl_evtlog.addr)
> +		return 0;
> +
> +	mutex_lock(&sl_evt_log_mutex);
> +	size = simple_read_from_buffer(buf, count, pos, sl_evtlog.addr,
> +				       sl_evtlog.size);
> +	mutex_unlock(&sl_evt_log_mutex);
> +
> +	return size;
> +}
> +
> +static ssize_t sl_evtlog_write(struct file *file, const char __user *buf,
> +				size_t datalen, loff_t *ppos)
> +{
> +	ssize_t result;
> +	char *data;
> +
> +	if (!sl_evtlog.addr)
> +		return 0;
> +
> +	/* No partial writes. */
> +	result = -EINVAL;
> +	if (*ppos != 0)
> +		goto out;
> +
> +	data = memdup_user(buf, datalen);
> +	if (IS_ERR(data)) {
> +		result = PTR_ERR(data);
> +		goto out;
> +	}
> +
> +	mutex_lock(&sl_evt_log_mutex);
> +	if (evtlog20)
> +		result = tpm20_log_event(evtlog20, sl_evtlog.addr,
> +					 sl_evtlog.size, datalen, data);
> +	else
> +		result = tpm12_log_event(sl_evtlog.addr, sl_evtlog.size,
> +					 datalen, data);
> +	mutex_unlock(&sl_evt_log_mutex);
> +
> +	kfree(data);
> +out:
> +	return result;
> +}
> +
> +static const struct file_operations sl_evtlog_ops = {
> +	.read = sl_evtlog_read,
> +	.write = sl_evtlog_write,
> +	.llseek	= default_llseek,
> +};
> +
> +struct sfs_file {
> +	const char *name;
> +	const struct file_operations *fops;
> +};
> +
> +#define SL_TXT_ENTRY_COUNT	7
> +static const struct sfs_file sl_txt_files[] = {
> +	{ "sts", &sts_ops },
> +	{ "ests", &ests_ops },
> +	{ "errorcode", &errorcode_ops },
> +	{ "didvid", &didvid_ops },
> +	{ "ver_emif", &ver_emif_ops },
> +	{ "scratchpad", &scratchpad_ops },
> +	{ "e2sts", &e2sts_ops }
> +};
> +
> +/* sysfs file handles */
> +static struct dentry *slaunch_dir;
> +static struct dentry *event_file;
> +static struct dentry *txt_dir;
> +static struct dentry *txt_entries[SL_TXT_ENTRY_COUNT];
> +
> +static long slaunch_expose_securityfs(void)
> +{
> +	long ret = 0;
> +	int i;
> +
> +	slaunch_dir = securityfs_create_dir("slaunch", NULL);
> +	if (IS_ERR(slaunch_dir))
> +		return PTR_ERR(slaunch_dir);
> +
> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> +		txt_dir = securityfs_create_dir("txt", slaunch_dir);
> +		if (IS_ERR(txt_dir)) {
> +			ret = PTR_ERR(txt_dir);
> +			goto remove_slaunch;
> +		}
> +
> +		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++) {
> +			txt_entries[i] = securityfs_create_file(
> +						sl_txt_files[i].name, 0440,
> +						txt_dir, NULL,
> +						sl_txt_files[i].fops);
> +			if (IS_ERR(txt_entries[i])) {
> +				ret = PTR_ERR(txt_entries[i]);
> +				goto remove_files;
> +			}
> +		}
> +
> +	}
> +
> +	if (sl_evtlog.addr > 0) {
> +		event_file = securityfs_create_file(
> +					sl_evtlog.name, 0440,
> +					slaunch_dir, NULL,
> +					&sl_evtlog_ops);
> +		if (IS_ERR(event_file)) {
> +			ret = PTR_ERR(event_file);
> +			goto remove_files;
> +		}
> +	}
> +
> +	return 0;
> +
> +remove_files:
> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> +		while (--i >= 0)
> +			securityfs_remove(txt_entries[i]);
> +		securityfs_remove(txt_dir);
> +	}
> +remove_slaunch:
> +	securityfs_remove(slaunch_dir);
> +
> +	return ret;
> +}
> +
> +static void slaunch_teardown_securityfs(void)
> +{
> +	int i;
> +
> +	securityfs_remove(event_file);
> +	if (sl_evtlog.addr) {
> +		memunmap(sl_evtlog.addr);
> +		sl_evtlog.addr = NULL;
> +	}
> +	sl_evtlog.size = 0;
> +
> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> +		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++)
> +			securityfs_remove(txt_entries[i]);
> +
> +		securityfs_remove(txt_dir);
> +
> +		if (txt_heap) {
> +			memunmap(txt_heap);
> +			txt_heap = NULL;
> +		}
> +	}
> +
> +	securityfs_remove(slaunch_dir);
> +}
> +
> +static void slaunch_intel_evtlog(void __iomem *txt)
> +{
> +	struct slr_entry_log_info *log_info;
> +	struct txt_os_mle_data *params;
> +	struct slr_table *slrt;
> +	void *os_sinit_data;
> +	u64 base, size;
> +
> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
> +
> +	/* now map TXT heap */
> +	txt_heap = memremap(base, size, MEMREMAP_WB);
> +	if (!txt_heap)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap TXT heap\n",
> +			SL_ERROR_HEAP_MAP);
> +
> +	params = (struct txt_os_mle_data *)txt_os_mle_data_start(txt_heap);
> +
> +	/* Get the SLRT and remap it */
> +	slrt = memremap(params->slrt, sizeof(*slrt), MEMREMAP_WB);
> +	if (!slrt)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap SLR Table\n",
> +			SL_ERROR_SLRT_MAP);
> +	size = slrt->size;
> +	memunmap(slrt);
> +
> +	slrt = memremap(params->slrt, size, MEMREMAP_WB);
> +	if (!slrt)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap SLR Table\n",
> +			SL_ERROR_SLRT_MAP);
> +
> +	log_info = (struct slr_entry_log_info *)
> +			slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
> +	if (!log_info)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap SLR Table\n",
> +			SL_ERROR_SLRT_MISSING_ENTRY);
> +
> +	sl_evtlog.size = log_info->size;
> +	sl_evtlog.addr = memremap(log_info->addr, log_info->size,
> +				  MEMREMAP_WB);
> +	if (!sl_evtlog.addr)
> +		slaunch_txt_reset(txt,
> +			"Error failed to memremap TPM event log\n",
> +			SL_ERROR_EVENTLOG_MAP);
> +
> +	memunmap(slrt);
> +
> +	/* Determine if this is TPM 1.2 or 2.0 event log */
> +	if (memcmp(sl_evtlog.addr + sizeof(struct tcg_pcr_event),
> +		    TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
> +		return; /* looks like it is not 2.0 */
> +
> +	/* For TPM 2.0 logs, the extended heap element must be located */
> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
> +
> +	evtlog20 = tpm20_find_log2_1_element(os_sinit_data);
> +
> +	/*
> +	 * If this fails, things are in really bad shape. Any attempt to write
> +	 * events to the log will fail.
> +	 */
> +	if (!evtlog20)
> +		slaunch_txt_reset(txt,
> +			"Error failed to find TPM20 event log element\n",
> +			SL_ERROR_TPM_INVALID_LOG20);
> +}
> +
> +static void slaunch_tpm20_extend_event(struct tpm_chip *tpm, void __iomem *txt,
> +				       struct tcg_pcr_event2_head *event)
> +{
> +	u16 *alg_id_field = (u16 *)((u8 *)event +
> +				    sizeof(struct tcg_pcr_event2_head));
> +	struct tpm_digest *digests;
> +	u8 *dptr;
> +	int ret;
> +	u32 i, j;
> +
> +	digests = kcalloc(tpm->nr_allocated_banks, sizeof(*digests),
> +			  GFP_KERNEL);
> +	if (!digests)
> +		slaunch_txt_reset(txt,
> +			"Failed to allocate array of digests\n",
> +			SL_ERROR_GENERIC);
> +
> +	for (i = 0; i < tpm->nr_allocated_banks; i++)
> +		digests[i].alg_id = tpm->allocated_banks[i].alg_id;
> +
> +
> +	/* Early SL code ensured there was a max count of 2 digests */
> +	for (i = 0; i < event->count; i++) {
> +		dptr = (u8 *)alg_id_field + sizeof(u16);
> +
> +		for (j = 0; j < tpm->nr_allocated_banks; j++) {
> +			if (digests[j].alg_id != *alg_id_field)
> +				continue;
> +
> +			switch (digests[j].alg_id) {
> +			case TPM_ALG_SHA256:
> +				memcpy(&digests[j].digest[0], dptr,
> +				       SHA256_DIGEST_SIZE);
> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
> +					SHA256_DIGEST_SIZE + sizeof(u16));
> +				break;
> +			case TPM_ALG_SHA1:
> +				memcpy(&digests[j].digest[0], dptr,
> +				       SHA1_DIGEST_SIZE);
> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
> +					SHA1_DIGEST_SIZE + sizeof(u16));
> +			default:
> +				break;
> +			}
> +		}
> +	}
> +
> +	ret = tpm_pcr_extend(tpm, event->pcr_idx, digests);
> +	if (ret) {
> +		pr_err("Error extending TPM20 PCR, result: %d\n", ret);
> +		slaunch_txt_reset(txt,
> +			"Failed to extend TPM20 PCR\n",
> +			SL_ERROR_TPM_EXTEND);
> +	}
> +
> +	kfree(digests);
> +}
> +
> +static void slaunch_tpm20_extend(struct tpm_chip *tpm, void __iomem *txt)
> +{
> +	struct tcg_pcr_event *event_header;
> +	struct tcg_pcr_event2_head *event;
> +	int start = 0, end = 0, size;
> +
> +	event_header = (struct tcg_pcr_event *)(sl_evtlog.addr +
> +						evtlog20->first_record_offset);
> +
> +	/* Skip first TPM 1.2 event to get to first TPM 2.0 event */
> +	event = (struct tcg_pcr_event2_head *)((u8 *)event_header +
> +						sizeof(struct tcg_pcr_event) +
> +						event_header->event_size);
> +
> +	while ((void  *)event < sl_evtlog.addr + evtlog20->next_record_offset) {
> +		size = __calc_tpm2_event_size(event, event_header, false);
> +		if (!size)
> +			slaunch_txt_reset(txt,
> +				"TPM20 invalid event in event log\n",
> +				SL_ERROR_TPM_INVALID_EVENT);
> +
> +		/*
> +		 * Marker events indicate where the Secure Launch early stub
> +		 * started and ended adding post launch events.
> +		 */
> +		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
> +			end = 1;
> +			break;
> +		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
> +			start = 1;
> +			goto next;
> +		}
> +
> +		if (start)
> +			slaunch_tpm20_extend_event(tpm, txt, event);
> +
> +next:
> +		event = (struct tcg_pcr_event2_head *)((u8 *)event + size);
> +	}
> +
> +	if (!start || !end)
> +		slaunch_txt_reset(txt,
> +			"Missing start or end events for extending TPM20 PCRs\n",
> +			SL_ERROR_TPM_EXTEND);
> +}
> +
> +static void slaunch_tpm12_extend(struct tpm_chip *tpm, void __iomem *txt)
> +{
> +	struct tpm12_event_log_header *event_header;
> +	struct tcg_pcr_event *event;
> +	struct tpm_digest digest;
> +	int start = 0, end = 0;
> +	int size, ret;
> +
> +	event_header = (struct tpm12_event_log_header *)sl_evtlog.addr;
> +	event = (struct tcg_pcr_event *)((u8 *)event_header +
> +				sizeof(struct tpm12_event_log_header));
> +
> +	while ((void  *)event < sl_evtlog.addr + event_header->next_event_offset) {
> +		size = sizeof(struct tcg_pcr_event) + event->event_size;
> +
> +		/*
> +		 * Marker events indicate where the Secure Launch early stub
> +		 * started and ended adding post launch events.
> +		 */
> +		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
> +			end = 1;
> +			break;
> +		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
> +			start = 1;
> +			goto next;
> +		}
> +
> +		if (start) {
> +			memset(&digest.digest[0], 0, TPM_MAX_DIGEST_SIZE);
> +			digest.alg_id = TPM_ALG_SHA1;
> +			memcpy(&digest.digest[0], &event->digest[0],
> +			       SHA1_DIGEST_SIZE);
> +
> +			ret = tpm_pcr_extend(tpm, event->pcr_idx, &digest);
> +			if (ret) {
> +				pr_err("Error extending TPM12 PCR, result: %d\n", ret);
> +				slaunch_txt_reset(txt,
> +					"Failed to extend TPM12 PCR\n",
> +					SL_ERROR_TPM_EXTEND);
> +			}
> +		}
> +
> +next:
> +		event = (struct tcg_pcr_event *)((u8 *)event + size);
> +	}
> +
> +	if (!start || !end)
> +		slaunch_txt_reset(txt,
> +			"Missing start or end events for extending TPM12 PCRs\n",
> +			SL_ERROR_TPM_EXTEND);
> +}
> +
> +static void slaunch_pcr_extend(void __iomem *txt)
> +{
> +	struct tpm_chip *tpm;
> +
> +	tpm = tpm_default_chip();
> +	if (!tpm)
> +		slaunch_txt_reset(txt,
> +			"Could not get default TPM chip\n",
> +			SL_ERROR_TPM_INIT);
> +	if (evtlog20)
> +		slaunch_tpm20_extend(tpm, txt);
> +	else
> +		slaunch_tpm12_extend(tpm, txt);
> +}
> +
> +static int __init slaunch_module_init(void)
> +{
> +	void __iomem *txt;
> +
> +	/* Check to see if Secure Launch happened */
> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
> +	    (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT))
> +		return 0;
> +
> +	txt = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
> +		      PAGE_SIZE);
> +	if (!txt)
> +		panic("Error ioremap of TXT priv registers\n");
> +
> +	/* Only Intel TXT is supported at this point */
> +	slaunch_intel_evtlog(txt);
> +
> +	slaunch_pcr_extend(txt);
> +
> +	iounmap(txt);

I would remove the empty lines in-between the three calls above.

> +
> +	return slaunch_expose_securityfs();
> +}
> +
> +static void __exit slaunch_module_exit(void)
> +{
> +	slaunch_teardown_securityfs();
> +}
> +
> +late_initcall(slaunch_module_init);
> +

I would remove this empty line.

> +__exitcall(slaunch_module_exit);
> -- 
> 1.8.3.1


BR, Jarkko

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 12/14] x86: Secure Launch late initcall platform module
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-10 22:40     ` Jarkko Sakkinen
  -1 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-10 22:40 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>
> The Secure Launch platform module is a late init module. During the
> init call, the TPM event log is read and measurements taken in the
> early boot stub code are located. These measurements are extended
> into the TPM PCRs using the mainline TPM kernel driver.
>
> The platform module also registers the securityfs nodes to allow
> access to TXT register fields on Intel along with the fetching of
> and writing events to the late launch TPM log.
>
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  arch/x86/kernel/Makefile   |   1 +
>  arch/x86/kernel/slmodule.c | 520 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 521 insertions(+)
>  create mode 100644 arch/x86/kernel/slmodule.c
>
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index 3d2a33e..ee3fe300 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -73,6 +73,7 @@ obj-$(CONFIG_IA32_EMULATION)	+= tls.o
>  obj-y				+= step.o
>  obj-$(CONFIG_INTEL_TXT)		+= tboot.o
>  obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
> +obj-$(CONFIG_SECURE_LAUNCH)	+= slmodule.o
>  obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
>  obj-y				+= stacktrace.o
>  obj-y				+= cpu/
> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
> new file mode 100644
> index 0000000..70dcff5
> --- /dev/null
> +++ b/arch/x86/kernel/slmodule.c
> @@ -0,0 +1,520 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Secure Launch late validation/setup, securityfs exposure and
> + * finalization support.

/* Secure Launch late validation/setup, securityfs exposure and finalization */

79 characters (max length allowed is 100).

BR, Jarkko


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

* Re: [PATCH v6 12/14] x86: Secure Launch late initcall platform module
@ 2023-05-10 22:40     ` Jarkko Sakkinen
  0 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-10 22:40 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>
> The Secure Launch platform module is a late init module. During the
> init call, the TPM event log is read and measurements taken in the
> early boot stub code are located. These measurements are extended
> into the TPM PCRs using the mainline TPM kernel driver.
>
> The platform module also registers the securityfs nodes to allow
> access to TXT register fields on Intel along with the fetching of
> and writing events to the late launch TPM log.
>
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  arch/x86/kernel/Makefile   |   1 +
>  arch/x86/kernel/slmodule.c | 520 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 521 insertions(+)
>  create mode 100644 arch/x86/kernel/slmodule.c
>
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index 3d2a33e..ee3fe300 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -73,6 +73,7 @@ obj-$(CONFIG_IA32_EMULATION)	+= tls.o
>  obj-y				+= step.o
>  obj-$(CONFIG_INTEL_TXT)		+= tboot.o
>  obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
> +obj-$(CONFIG_SECURE_LAUNCH)	+= slmodule.o
>  obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
>  obj-y				+= stacktrace.o
>  obj-y				+= cpu/
> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
> new file mode 100644
> index 0000000..70dcff5
> --- /dev/null
> +++ b/arch/x86/kernel/slmodule.c
> @@ -0,0 +1,520 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Secure Launch late validation/setup, securityfs exposure and
> + * finalization support.

/* Secure Launch late validation/setup, securityfs exposure and finalization */

79 characters (max length allowed is 100).

BR, Jarkko


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 09/14] x86: Secure Launch SMP bringup support
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-10 22:55     ` Jarkko Sakkinen
  -1 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-10 22:55 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
> On Intel, the APs are left in a well documented state after TXT performs
> the late launch. Specifically they cannot have #INIT asserted on them so
> a standard startup via INIT/SIPI/SIPI cannot be performed. Instead the
> early SL stub code parked the APs in a pause/jmp loop waiting for an NMI.
> The modified SMP boot code is called for the Secure Launch case. The
> jump address for the RM piggy entry point is fixed up in the jump where
> the APs are waiting and an NMI IPI is sent to the AP. The AP vectors to
> the Secure Launch entry point in the RM piggy which mimics what the real
> mode code would do then jumps to the standard RM piggy protected mode
> entry point.
>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  arch/x86/include/asm/realmode.h      |  3 ++
>  arch/x86/kernel/smpboot.c            | 86 ++++++++++++++++++++++++++++++++++++
>  arch/x86/realmode/rm/header.S        |  3 ++
>  arch/x86/realmode/rm/trampoline_64.S | 37 ++++++++++++++++
>  4 files changed, 129 insertions(+)
>
> diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
> index f6a1737..576fe62 100644
> --- a/arch/x86/include/asm/realmode.h
> +++ b/arch/x86/include/asm/realmode.h
> @@ -38,6 +38,9 @@ struct real_mode_header {
>  #ifdef CONFIG_X86_64
>  	u32	machine_real_restart_seg;
>  #endif
> +#ifdef CONFIG_SECURE_LAUNCH
> +	u32	sl_trampoline_start32;
> +#endif

Cool I was implementing this relocatable realmode blob back in 2012 :-)

>  };
>  
>  /* This must match data at realmode/rm/trampoline_{32,64}.S */
> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
> index 352f0ce..07d740be 100644
> --- a/arch/x86/kernel/smpboot.c
> +++ b/arch/x86/kernel/smpboot.c
> @@ -57,6 +57,7 @@
>  #include <linux/pgtable.h>
>  #include <linux/overflow.h>
>  #include <linux/stackprotector.h>
> +#include <linux/slaunch.h>
>  
>  #include <asm/acpi.h>
>  #include <asm/cacheinfo.h>
> @@ -1068,6 +1069,83 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_SECURE_LAUNCH
> +
> +static atomic_t first_ap_only = {1};

This should be documented.

> +
> +/*
> + * Called to fix the long jump address for the waiting APs to vector to
> + * the correct startup location in the Secure Launch stub in the rmpiggy.
> + */
> +static int
> +slaunch_fixup_jump_vector(void)

Please put the same line.

> +{
> +	struct sl_ap_wake_info *ap_wake_info;
> +	u32 *ap_jmp_ptr = NULL;
> +
> +	if (!atomic_dec_and_test(&first_ap_only))
> +		return 0;
> +
> +	ap_wake_info = slaunch_get_ap_wake_info();
> +
> +	ap_jmp_ptr = (u32 *)__va(ap_wake_info->ap_wake_block +
> +				 ap_wake_info->ap_jmp_offset);
> +
> +	*ap_jmp_ptr = real_mode_header->sl_trampoline_start32;
> +
> +	pr_debug("TXT AP long jump address updated\n");
> +
> +	return 0;
> +}
> +
> +/*
> + * TXT AP startup is quite different than normal. The APs cannot have #INIT
> + * asserted on them or receive SIPIs. The early Secure Launch code has parked
> + * the APs in a pause loop waiting to receive an NMI. This will wake the APs
> + * and have them jump to the protected mode code in the rmpiggy where the rest
> + * of the SMP boot of the AP will proceed normally.
> + */
> +static int
> +slaunch_wakeup_cpu_from_txt(int cpu, int apicid)

Ditto.


> +{
> +	unsigned long send_status = 0, accept_status = 0;

I would put these to separate lines. Maybe a matter of taste but
it is easier to spot initializations.

> +
> +	/* Only done once */
> +	if (slaunch_fixup_jump_vector())
> +		return -1;
> +
> +	/* Send NMI IPI to idling AP and wake it up */
> +	apic_icr_write(APIC_DM_NMI, apicid);
> +
> +	if (init_udelay == 0)
> +		udelay(10);
> +	else
> +		udelay(300);
> +
> +	send_status = safe_apic_wait_icr_idle();
> +
> +	if (init_udelay == 0)
> +		udelay(10);
> +	else
> +		udelay(300);

Magic numbers and no inline comment.

> +
> +	accept_status = (apic_read(APIC_ESR) & 0xEF);
> +
> +	if (send_status)
> +		pr_err("Secure Launch IPI never delivered???\n");
> +	if (accept_status)
> +		pr_err("Secure Launch IPI delivery error (%lx)\n",
> +			accept_status);
> +
> +	return (send_status | accept_status);
> +}
> +
> +#else
> +
> +#define slaunch_wakeup_cpu_from_txt(cpu, apicid)	0
> +
> +#endif  /* !CONFIG_SECURE_LAUNCH */
> +
>  /*
>   * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
>   * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
> @@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>  	cpumask_clear_cpu(cpu, cpu_initialized_mask);
>  	smp_mb();
>  
> +	/* With Intel TXT, the AP startup is totally different */
> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==
> +	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {
> +		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
> +		goto txt_wake;
> +	}
> +
>  	/*
>  	 * Wake up a CPU in difference cases:
>  	 * - Use a method from the APIC driver if one defined, with wakeup
> @@ -1147,6 +1232,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>  		boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
>  						     cpu0_nmi_registered);
>  
> +txt_wake:
>  	if (!boot_error) {
>  		/*
>  		 * Wait 10s total for first sign of life from AP
> diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
> index 2eb62be..3b5cbcb 100644
> --- a/arch/x86/realmode/rm/header.S
> +++ b/arch/x86/realmode/rm/header.S
> @@ -37,6 +37,9 @@ SYM_DATA_START(real_mode_header)
>  #ifdef CONFIG_X86_64
>  	.long	__KERNEL32_CS
>  #endif
> +#ifdef CONFIG_SECURE_LAUNCH
> +	.long	pa_sl_trampoline_start32
> +#endif
>  SYM_DATA_END(real_mode_header)
>  
>  	/* End signature, used to verify integrity */
> diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
> index e38d61d..8bb4b0d 100644
> --- a/arch/x86/realmode/rm/trampoline_64.S
> +++ b/arch/x86/realmode/rm/trampoline_64.S
> @@ -104,6 +104,43 @@ SYM_CODE_END(sev_es_trampoline_start)
>  
>  	.section ".text32","ax"
>  	.code32
> +#ifdef CONFIG_SECURE_LAUNCH
> +	.balign 4
> +SYM_CODE_START(sl_trampoline_start32)
> +	/*
> +	 * The early secure launch stub AP wakeup code has taken care of all
> +	 * the vagaries of launching out of TXT. This bit just mimics what the
> +	 * 16b entry code does and jumps off to the real startup_32.
> +	 */
> +	cli
> +	wbinvd
> +
> +	/*
> +	 * The %ebx provided is not terribly useful since it is the physical
> +	 * address of tb_trampoline_start and not the base of the image.
> +	 * Use pa_real_mode_base, which is fixed up, to get a run time
> +	 * base register to use for offsets to location that do not have
> +	 * pa_ symbols.
> +	 */
> +	movl    $pa_real_mode_base, %ebx
> +
> +	/*
> +	 * This may seem a little odd but this is what %esp would have had in
> +	 * it on the jmp from real mode because all real mode fixups were done
> +	 * via the code segment. The base is added at the 32b entry.
> +	 */
> +	movl	rm_stack_end, %esp
> +
> +	lgdt    tr_gdt(%ebx)
> +	lidt    tr_idt(%ebx)
> +
> +	movw	$__KERNEL_DS, %dx	# Data segment descriptor
> +
> +	/* Jump to where the 16b code would have jumped */
> +	ljmpl	$__KERNEL32_CS, $pa_startup_32
> +SYM_CODE_END(sl_trampoline_start32)
> +#endif
> +
>  	.balign 4
>  SYM_CODE_START(startup_32)
>  	movl	%edx, %ss
> -- 
> 1.8.3.1


The trampoline_64.S changes look reasonable to me (with a quick look).

BR, Jarkko

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

* Re: [PATCH v6 09/14] x86: Secure Launch SMP bringup support
@ 2023-05-10 22:55     ` Jarkko Sakkinen
  0 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-10 22:55 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
> On Intel, the APs are left in a well documented state after TXT performs
> the late launch. Specifically they cannot have #INIT asserted on them so
> a standard startup via INIT/SIPI/SIPI cannot be performed. Instead the
> early SL stub code parked the APs in a pause/jmp loop waiting for an NMI.
> The modified SMP boot code is called for the Secure Launch case. The
> jump address for the RM piggy entry point is fixed up in the jump where
> the APs are waiting and an NMI IPI is sent to the AP. The AP vectors to
> the Secure Launch entry point in the RM piggy which mimics what the real
> mode code would do then jumps to the standard RM piggy protected mode
> entry point.
>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  arch/x86/include/asm/realmode.h      |  3 ++
>  arch/x86/kernel/smpboot.c            | 86 ++++++++++++++++++++++++++++++++++++
>  arch/x86/realmode/rm/header.S        |  3 ++
>  arch/x86/realmode/rm/trampoline_64.S | 37 ++++++++++++++++
>  4 files changed, 129 insertions(+)
>
> diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
> index f6a1737..576fe62 100644
> --- a/arch/x86/include/asm/realmode.h
> +++ b/arch/x86/include/asm/realmode.h
> @@ -38,6 +38,9 @@ struct real_mode_header {
>  #ifdef CONFIG_X86_64
>  	u32	machine_real_restart_seg;
>  #endif
> +#ifdef CONFIG_SECURE_LAUNCH
> +	u32	sl_trampoline_start32;
> +#endif

Cool I was implementing this relocatable realmode blob back in 2012 :-)

>  };
>  
>  /* This must match data at realmode/rm/trampoline_{32,64}.S */
> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
> index 352f0ce..07d740be 100644
> --- a/arch/x86/kernel/smpboot.c
> +++ b/arch/x86/kernel/smpboot.c
> @@ -57,6 +57,7 @@
>  #include <linux/pgtable.h>
>  #include <linux/overflow.h>
>  #include <linux/stackprotector.h>
> +#include <linux/slaunch.h>
>  
>  #include <asm/acpi.h>
>  #include <asm/cacheinfo.h>
> @@ -1068,6 +1069,83 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_SECURE_LAUNCH
> +
> +static atomic_t first_ap_only = {1};

This should be documented.

> +
> +/*
> + * Called to fix the long jump address for the waiting APs to vector to
> + * the correct startup location in the Secure Launch stub in the rmpiggy.
> + */
> +static int
> +slaunch_fixup_jump_vector(void)

Please put the same line.

> +{
> +	struct sl_ap_wake_info *ap_wake_info;
> +	u32 *ap_jmp_ptr = NULL;
> +
> +	if (!atomic_dec_and_test(&first_ap_only))
> +		return 0;
> +
> +	ap_wake_info = slaunch_get_ap_wake_info();
> +
> +	ap_jmp_ptr = (u32 *)__va(ap_wake_info->ap_wake_block +
> +				 ap_wake_info->ap_jmp_offset);
> +
> +	*ap_jmp_ptr = real_mode_header->sl_trampoline_start32;
> +
> +	pr_debug("TXT AP long jump address updated\n");
> +
> +	return 0;
> +}
> +
> +/*
> + * TXT AP startup is quite different than normal. The APs cannot have #INIT
> + * asserted on them or receive SIPIs. The early Secure Launch code has parked
> + * the APs in a pause loop waiting to receive an NMI. This will wake the APs
> + * and have them jump to the protected mode code in the rmpiggy where the rest
> + * of the SMP boot of the AP will proceed normally.
> + */
> +static int
> +slaunch_wakeup_cpu_from_txt(int cpu, int apicid)

Ditto.


> +{
> +	unsigned long send_status = 0, accept_status = 0;

I would put these to separate lines. Maybe a matter of taste but
it is easier to spot initializations.

> +
> +	/* Only done once */
> +	if (slaunch_fixup_jump_vector())
> +		return -1;
> +
> +	/* Send NMI IPI to idling AP and wake it up */
> +	apic_icr_write(APIC_DM_NMI, apicid);
> +
> +	if (init_udelay == 0)
> +		udelay(10);
> +	else
> +		udelay(300);
> +
> +	send_status = safe_apic_wait_icr_idle();
> +
> +	if (init_udelay == 0)
> +		udelay(10);
> +	else
> +		udelay(300);

Magic numbers and no inline comment.

> +
> +	accept_status = (apic_read(APIC_ESR) & 0xEF);
> +
> +	if (send_status)
> +		pr_err("Secure Launch IPI never delivered???\n");
> +	if (accept_status)
> +		pr_err("Secure Launch IPI delivery error (%lx)\n",
> +			accept_status);
> +
> +	return (send_status | accept_status);
> +}
> +
> +#else
> +
> +#define slaunch_wakeup_cpu_from_txt(cpu, apicid)	0
> +
> +#endif  /* !CONFIG_SECURE_LAUNCH */
> +
>  /*
>   * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
>   * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
> @@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>  	cpumask_clear_cpu(cpu, cpu_initialized_mask);
>  	smp_mb();
>  
> +	/* With Intel TXT, the AP startup is totally different */
> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==
> +	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {
> +		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
> +		goto txt_wake;
> +	}
> +
>  	/*
>  	 * Wake up a CPU in difference cases:
>  	 * - Use a method from the APIC driver if one defined, with wakeup
> @@ -1147,6 +1232,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>  		boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
>  						     cpu0_nmi_registered);
>  
> +txt_wake:
>  	if (!boot_error) {
>  		/*
>  		 * Wait 10s total for first sign of life from AP
> diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
> index 2eb62be..3b5cbcb 100644
> --- a/arch/x86/realmode/rm/header.S
> +++ b/arch/x86/realmode/rm/header.S
> @@ -37,6 +37,9 @@ SYM_DATA_START(real_mode_header)
>  #ifdef CONFIG_X86_64
>  	.long	__KERNEL32_CS
>  #endif
> +#ifdef CONFIG_SECURE_LAUNCH
> +	.long	pa_sl_trampoline_start32
> +#endif
>  SYM_DATA_END(real_mode_header)
>  
>  	/* End signature, used to verify integrity */
> diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
> index e38d61d..8bb4b0d 100644
> --- a/arch/x86/realmode/rm/trampoline_64.S
> +++ b/arch/x86/realmode/rm/trampoline_64.S
> @@ -104,6 +104,43 @@ SYM_CODE_END(sev_es_trampoline_start)
>  
>  	.section ".text32","ax"
>  	.code32
> +#ifdef CONFIG_SECURE_LAUNCH
> +	.balign 4
> +SYM_CODE_START(sl_trampoline_start32)
> +	/*
> +	 * The early secure launch stub AP wakeup code has taken care of all
> +	 * the vagaries of launching out of TXT. This bit just mimics what the
> +	 * 16b entry code does and jumps off to the real startup_32.
> +	 */
> +	cli
> +	wbinvd
> +
> +	/*
> +	 * The %ebx provided is not terribly useful since it is the physical
> +	 * address of tb_trampoline_start and not the base of the image.
> +	 * Use pa_real_mode_base, which is fixed up, to get a run time
> +	 * base register to use for offsets to location that do not have
> +	 * pa_ symbols.
> +	 */
> +	movl    $pa_real_mode_base, %ebx
> +
> +	/*
> +	 * This may seem a little odd but this is what %esp would have had in
> +	 * it on the jmp from real mode because all real mode fixups were done
> +	 * via the code segment. The base is added at the 32b entry.
> +	 */
> +	movl	rm_stack_end, %esp
> +
> +	lgdt    tr_gdt(%ebx)
> +	lidt    tr_idt(%ebx)
> +
> +	movw	$__KERNEL_DS, %dx	# Data segment descriptor
> +
> +	/* Jump to where the 16b code would have jumped */
> +	ljmpl	$__KERNEL32_CS, $pa_startup_32
> +SYM_CODE_END(sl_trampoline_start32)
> +#endif
> +
>  	.balign 4
>  SYM_CODE_START(startup_32)
>  	movl	%edx, %ss
> -- 
> 1.8.3.1


The trampoline_64.S changes look reasonable to me (with a quick look).

BR, Jarkko

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-10 23:02     ` Jarkko Sakkinen
  -1 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-10 23:02 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
> The routine slaunch_setup is called out of the x86 specific setup_arch
> routine during early kernel boot. After determining what platform is
> present, various operations specific to that platform occur. This
> includes finalizing setting for the platform late launch and verifying
> that memory protections are in place.
>
> For TXT, this code also reserves the original compressed kernel setup
> area where the APs were left looping so that this memory cannot be used.
>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  arch/x86/kernel/Makefile   |   1 +
>  arch/x86/kernel/setup.c    |   3 +
>  arch/x86/kernel/slaunch.c  | 497 +++++++++++++++++++++++++++++++++++++++++++++
>  drivers/iommu/intel/dmar.c |   4 +
>  4 files changed, 505 insertions(+)
>  create mode 100644 arch/x86/kernel/slaunch.c
>
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index dd61752..3d2a33e 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -72,6 +72,7 @@ obj-$(CONFIG_X86_32)		+= tls.o
>  obj-$(CONFIG_IA32_EMULATION)	+= tls.o
>  obj-y				+= step.o
>  obj-$(CONFIG_INTEL_TXT)		+= tboot.o
> +obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
>  obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
>  obj-y				+= stacktrace.o
>  obj-y				+= cpu/
> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> index 16babff..592c09e 100644
> --- a/arch/x86/kernel/setup.c
> +++ b/arch/x86/kernel/setup.c
> @@ -21,6 +21,7 @@
>  #include <linux/root_dev.h>
>  #include <linux/hugetlb.h>
>  #include <linux/tboot.h>
> +#include <linux/slaunch.h>

Only because of pure curiosity: what made you choose this location in
the middle for the new include? :-)

>  #include <linux/usb/xhci-dbgp.h>
>  #include <linux/static_call.h>
>  #include <linux/swiotlb.h>
> @@ -1063,6 +1064,8 @@ void __init setup_arch(char **cmdline_p)
>  	early_gart_iommu_check();
>  #endif
>  
> +	slaunch_setup_txt();
> +
>  	/*
>  	 * partially used pages are not usable - thus
>  	 * we are rounding upwards:
> diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
> new file mode 100644
> index 0000000..7dba088
> --- /dev/null
> +++ b/arch/x86/kernel/slaunch.c
> @@ -0,0 +1,497 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Secure Launch late validation/setup and finalization support.
> + *
> + * Copyright (c) 2022, Oracle and/or its affiliates.
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/linkage.h>
> +#include <linux/mm.h>
> +#include <linux/io.h>
> +#include <linux/uaccess.h>
> +#include <linux/security.h>
> +#include <linux/memblock.h>
> +#include <asm/segment.h>
> +#include <asm/sections.h>
> +#include <asm/tlbflush.h>
> +#include <asm/e820/api.h>
> +#include <asm/setup.h>
> +#include <linux/slr_table.h>
> +#include <linux/slaunch.h>
> +
> +static u32 sl_flags;
> +static struct sl_ap_wake_info ap_wake_info;
> +static u64 evtlog_addr;
> +static u32 evtlog_size;
> +static u64 vtd_pmr_lo_size;
> +
> +/* This should be plenty of room */
> +static u8 txt_dmar[PAGE_SIZE] __aligned(16);
> +
> +u32 slaunch_get_flags(void)
> +{
> +	return sl_flags;
> +}
> +EXPORT_SYMBOL(slaunch_get_flags);
> +
> +struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
> +{
> +	return &ap_wake_info;
> +}
> +
> +struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
> +{
> +	/* The DMAR is only stashed and provided via TXT on Intel systems */
> +	if (memcmp(txt_dmar, "DMAR", 4))
> +		return dmar;
> +
> +	return (struct acpi_table_header *)(&txt_dmar[0]);
> +}
> +
> +void __noreturn slaunch_txt_reset(void __iomem *txt,
> +				  const char *msg, u64 error)
> +{
> +	u64 one = 1, val;
> +
> +	pr_err("%s", msg);
> +
> +	/*
> +	 * This performs a TXT reset with a sticky error code. The reads of
> +	 * TXT_CR_E2STS act as barriers.
> +	 */
> +	memcpy_toio(txt + TXT_CR_ERRORCODE, &error, sizeof(error));
> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> +	memcpy_toio(txt + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> +	memcpy_toio(txt + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> +	memcpy_toio(txt + TXT_CR_CMD_RESET, &one, sizeof(one));
> +
> +	for ( ; ; )
> +		asm volatile ("hlt");
> +
> +	unreachable();
> +}
> +
> +/*
> + * The TXT heap is too big to map all at once with early_ioremap
> + * so it is done a table at a time.
> + */
> +static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
> +					     u32 bytes)
> +{
> +	u64 base, size, offset = 0;
> +	void *heap;
> +	int i;
> +
> +	if (type > TXT_SINIT_TABLE_MAX)
> +		slaunch_txt_reset(txt,
> +			"Error invalid table type for early heap walk\n",
> +			SL_ERROR_HEAP_WALK);

Align with 'txt'.

> +
> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
> +
> +	/* Iterate over heap tables looking for table of "type" */
> +	for (i = 0; i < type; i++) {
> +		base += offset;
> +		heap = early_memremap(base, sizeof(u64));
> +		if (!heap)
> +			slaunch_txt_reset(txt,
> +				"Error early_memremap of heap for heap walk\n",
> +				SL_ERROR_HEAP_MAP);
> +
> +		offset = *((u64 *)heap);
> +
> +		/*
> +		 * After the first iteration, any offset of zero is invalid and
> +		 * implies the TXT heap is corrupted.
> +		 */
> +		if (!offset)
> +			slaunch_txt_reset(txt,
> +				"Error invalid 0 offset in heap walk\n",
> +				SL_ERROR_HEAP_ZERO_OFFSET);
> +
> +		early_memunmap(heap, sizeof(u64));
> +	}
> +
> +	/* Skip the size field at the head of each table */
> +	base += sizeof(u64);
> +	heap = early_memremap(base, bytes);
> +	if (!heap)
> +		slaunch_txt_reset(txt,
> +				  "Error early_memremap of heap section\n",
> +				  SL_ERROR_HEAP_MAP);
> +
> +	return heap;
> +}
> +
> +static void __init txt_early_put_heap_table(void *addr, unsigned long size)
> +{
> +	early_memunmap(addr, size);
> +}
> +
> +/*
> + * TXT uses a special set of VTd registers to protect all of memory from DMA
> + * until the IOMMU can be programmed to protect memory. There is the low
> + * memory PMR that can protect all memory up to 4G. The high memory PRM can
> + * be setup to protect all memory beyond 4Gb. Validate that these values cover
> + * what is expected.
> + */
> +static void __init slaunch_verify_pmrs(void __iomem *txt)
> +{
> +	struct txt_os_sinit_data *os_sinit_data;
> +	u32 field_offset, err = 0;
> +	const char *errmsg = "";
> +	unsigned long last_pfn;
> +
> +	field_offset = offsetof(struct txt_os_sinit_data, lcp_po_base);
> +	os_sinit_data = txt_early_get_heap_table(txt, TXT_OS_SINIT_DATA_TABLE,
> +						 field_offset);
> +
> +	/* Save a copy */
> +	vtd_pmr_lo_size = os_sinit_data->vtd_pmr_lo_size;
> +
> +	last_pfn = e820__end_of_ram_pfn();
> +
> +	/*
> +	 * First make sure the hi PMR covers all memory above 4G. In the
> +	 * unlikely case where there is < 4G on the system, the hi PMR will
> +	 * not be set.
> +	 */
> +	if (os_sinit_data->vtd_pmr_hi_base != 0x0ULL) {
> +		if (os_sinit_data->vtd_pmr_hi_base != 0x100000000ULL) {
> +			err = SL_ERROR_HI_PMR_BASE;
> +			errmsg =  "Error hi PMR base\n";
> +			goto out;
> +		}
> +
> +		if (PFN_PHYS(last_pfn) > os_sinit_data->vtd_pmr_hi_base +
> +		    os_sinit_data->vtd_pmr_hi_size) {
> +			err = SL_ERROR_HI_PMR_SIZE;
> +			errmsg = "Error hi PMR size\n";
> +			goto out;
> +		}
> +	}
> +
> +	/*
> +	 * Lo PMR base should always be 0. This was already checked in
> +	 * early stub.
> +	 */
> +
> +	/*
> +	 * Check that if the kernel was loaded below 4G, that it is protected
> +	 * by the lo PMR. Note this is the decompressed kernel. The ACM would
> +	 * have ensured the compressed kernel (the MLE image) was protected.
> +	 */
> +	if ((__pa_symbol(_end) < 0x100000000ULL) &&
> +	    (__pa_symbol(_end) > os_sinit_data->vtd_pmr_lo_size)) {
> +		err = SL_ERROR_LO_PMR_MLE;
> +		errmsg = "Error lo PMR does not cover MLE kernel\n";
> +	}
> +
> +	/*
> +	 * Other regions of interest like boot param, AP wake block, cmdline
> +	 * already checked for PMR coverage in the early stub code.
> +	 */
> +
> +out:
> +	txt_early_put_heap_table(os_sinit_data, field_offset);
> +
> +	if (err)
> +		slaunch_txt_reset(txt, errmsg, err);
> +}
> +
> +static void __init slaunch_txt_reserve_range(u64 base, u64 size)
> +{
> +	int type;
> +
> +	type = e820__get_entry_type(base, base + size - 1);
> +	if (type == E820_TYPE_RAM) {
> +		pr_info("memblock reserve base: %llx size: %llx\n", base, size);
> +		memblock_reserve(base, size);
> +	}
> +}
> +
> +/*
> + * For Intel, certain regions of memory must be marked as reserved by putting
> + * them on the memblock reserved list if they are not already e820 reserved.
> + * This includes:
> + *  - The TXT HEAP
> + *  - The ACM area
> + *  - The TXT private register bank
> + *  - The MDR list sent to the MLE by the ACM (see TXT specification)
> + *  (Normally the above are properly reserved by firmware but if it was not
> + *  done, reserve them now)
> + *  - The AP wake block
> + *  - TPM log external to the TXT heap
> + *
> + * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
> + * the low PMR must be reservered too.
> + */
> +static void __init slaunch_txt_reserve(void __iomem *txt)
> +{
> +	struct txt_sinit_memory_descriptor_record *mdr;
> +	struct txt_sinit_mle_data *sinit_mle_data;
> +	u64 base, size, heap_base, heap_size;
> +	u32 mdrnum, mdroffset, mdrslen;
> +	u32 field_offset, i;
> +	void *mdrs;
> +
> +	base = TXT_PRIV_CONFIG_REGS_BASE;
> +	size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
> +	slaunch_txt_reserve_range(base, size);
> +
> +	memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
> +	memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
> +	slaunch_txt_reserve_range(heap_base, heap_size);
> +
> +	memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
> +	memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
> +	slaunch_txt_reserve_range(base, size);
> +
> +	field_offset = offsetof(struct txt_sinit_mle_data,
> +				sinit_vtd_dmar_table_size);
> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +						  field_offset);
> +
> +	mdrnum = sinit_mle_data->num_of_sinit_mdrs;
> +	mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
> +
> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
> +
> +	if (!mdrnum)
> +		goto nomdr;
> +
> +	mdrslen = mdrnum * sizeof(struct txt_sinit_memory_descriptor_record);
> +
> +	mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +					mdroffset + mdrslen - 8);
> +
> +	mdr = mdrs + mdroffset - 8;
> +
> +	for (i = 0; i < mdrnum; i++, mdr++) {
> +		/* Spec says some entries can have length 0, ignore them */
> +		if (mdr->type > 0 && mdr->length > 0)
> +			slaunch_txt_reserve_range(mdr->address, mdr->length);
> +	}
> +
> +	txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
> +
> +nomdr:
> +	slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
> +				  ap_wake_info.ap_wake_block_size);
> +
> +	/*
> +	 * Earlier checks ensured that the event log was properly situated
> +	 * either inside the TXT heap or outside. This is a check to see if the
> +	 * event log needs to be reserved. If it is in the TXT heap, it is
> +	 * already reserved.
> +	 */
> +	if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
> +		slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
> +
> +	for (i = 0; i < e820_table->nr_entries; i++) {
> +		base = e820_table->entries[i].addr;
> +		size = e820_table->entries[i].size;
> +		if ((base >= vtd_pmr_lo_size) && (base < 0x100000000ULL))
> +			slaunch_txt_reserve_range(base, size);
> +		else if ((base < vtd_pmr_lo_size) &&
> +			 (base + size > vtd_pmr_lo_size))
> +			slaunch_txt_reserve_range(vtd_pmr_lo_size,
> +						  base + size - vtd_pmr_lo_size);
> +	}
> +}
> +
> +/*
> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
> + * It is stored in the TXT heap. Fetch it from there and make it available
> + * to the IOMMU driver.
> + */
> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
> +{
> +	struct txt_sinit_mle_data *sinit_mle_data;
> +	u32 field_offset, dmar_size, dmar_offset;
> +	void *dmar;
> +
> +	memset(&txt_dmar, 0, PAGE_SIZE);
> +
> +	field_offset = offsetof(struct txt_sinit_mle_data,
> +				processor_scrtm_status);
> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +						  field_offset);
> +
> +	dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
> +	dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
> +
> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
> +
> +	if (!dmar_size || !dmar_offset)
> +		slaunch_txt_reset(txt,
> +				  "Error invalid DMAR table values\n",
> +				  SL_ERROR_HEAP_INVALID_DMAR);
> +
> +	if (unlikely(dmar_size > PAGE_SIZE))
> +		slaunch_txt_reset(txt,
> +				  "Error DMAR too big to store\n",
> +				  SL_ERROR_HEAP_DMAR_SIZE);
> +
> +
> +	dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +					dmar_offset + dmar_size - 8);
> +	if (!dmar)
> +		slaunch_txt_reset(txt,
> +				  "Error early_ioremap of DMAR\n",
> +				  SL_ERROR_HEAP_DMAR_MAP);
> +
> +	memcpy(&txt_dmar[0], dmar + dmar_offset - 8, dmar_size);
> +
> +	txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
> +}
> +
> +/*
> + * The location of the safe AP wake code block is stored in the TXT heap.
> + * Fetch needed values here in the early init code for later use in SMP
> + * startup.
> + *
> + * Also get the TPM event log values are in the SLRT and have to be fetched.
> + * They will be put on the memblock reserve list later.
> + */
> +static void __init slaunch_fetch_values(void __iomem *txt)
> +{
> +	struct txt_os_mle_data *os_mle_data;
> +	struct slr_entry_log_info *log_info;
> +	struct slr_table *slrt;
> +	u8 *jmp_offset;
> +	u32 size;
> +
> +	os_mle_data = txt_early_get_heap_table(txt, TXT_OS_MLE_DATA_TABLE,
> +					       sizeof(*os_mle_data));
> +
> +	ap_wake_info.ap_wake_block = os_mle_data->ap_wake_block;
> +	ap_wake_info.ap_wake_block_size = os_mle_data->ap_wake_block_size;
> +
> +	jmp_offset = os_mle_data->mle_scratch + SL_SCRATCH_AP_JMP_OFFSET;
> +	ap_wake_info.ap_jmp_offset = *((u32 *)jmp_offset);
> +
> +	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, sizeof(*slrt));
> +	if (!slrt)
> +		slaunch_txt_reset(txt,
> +			"Error early_memremap of SLRT failed\n",
> +			SL_ERROR_SLRT_MAP);
> +
> +	size = slrt->size;
> +	early_memunmap(slrt, sizeof(*slrt));
> +
> +	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, size);
> +	if (!slrt)
> +		slaunch_txt_reset(txt,
> +			"Error early_memremap of SLRT failed\n",
> +			SL_ERROR_SLRT_MAP);
> +
> +	log_info = (struct slr_entry_log_info *)
> +		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
> +
> +	if (!log_info)
> +		slaunch_txt_reset(txt,
> +				  "SLRT missing logging info entry\n",
> +				  SL_ERROR_SLRT_MISSING_ENTRY);
> +
> +	evtlog_addr = log_info->addr;
> +	evtlog_size = log_info->size;
> +
> +	early_memunmap(slrt, size);
> +
> +	txt_early_put_heap_table(os_mle_data, sizeof(*os_mle_data));
> +}
> +
> +/*
> + * Intel TXT specific late stub setup and validation.
> + */
> +void __init slaunch_setup_txt(void)
> +{
> +	u64 one = TXT_REGVALUE_ONE, val;
> +	void __iomem *txt;
> +
> +	if (!boot_cpu_has(X86_FEATURE_SMX))
> +		return;
> +
> +	/*
> +	 * If booted through secure launch entry point, the loadflags
> +	 * option will be set.
> +	 */
> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
> +		return;
> +
> +	/*
> +	 * See if SENTER was done by reading the status register in the
> +	 * public space. If the public register space cannot be read, TXT may
> +	 * be disabled.
> +	 */
> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +	if (!txt)
> +		return;
> +
> +	memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +
> +	/* SENTER should have been done */
> +	if (!(val & TXT_SENTER_DONE_STS))
> +		panic("Error TXT.STS SENTER_DONE not set\n");
> +
> +	/* SEXIT should have been cleared */
> +	if (val & TXT_SEXIT_DONE_STS)
> +		panic("Error TXT.STS SEXIT_DONE set\n");
> +
> +	/* Now we want to use the private register space */
> +	txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +	if (!txt) {
> +		/* This is really bad, no where to go from here */
> +		panic("Error early_ioremap of TXT priv registers\n");
> +	}
> +
> +	/*
> +	 * Try to read the Intel VID from the TXT private registers to see if
> +	 * TXT measured launch happened properly and the private space is
> +	 * available.
> +	 */
> +	memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
> +	if ((val & 0xffff) != 0x8086) {
> +		/*
> +		 * Can't do a proper TXT reset since it appears something is
> +		 * wrong even though SENTER happened and it should be in SMX
> +		 * mode.
> +		 */
> +		panic("Invalid TXT vendor ID, not in SMX mode\n");
> +	}
> +
> +	/* Set flags so subsequent code knows the status of the launch */
> +	sl_flags |= (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT);
> +
> +	/*
> +	 * Reading the proper DIDVID from the private register space means we
> +	 * are in SMX mode and private registers are open for read/write.
> +	 */
> +
> +	/* On Intel, have to handle TPM localities via TXT */
> +	memcpy_toio(txt + TXT_CR_CMD_SECRETS, &one, sizeof(one));
> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> +	memcpy_toio(txt + TXT_CR_CMD_OPEN_LOCALITY1, &one, sizeof(one));
> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> +
> +	slaunch_fetch_values(txt);
> +
> +	slaunch_verify_pmrs(txt);
> +
> +	slaunch_txt_reserve(txt);
> +
> +	slaunch_copy_dmar_table(txt);
> +
> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +
> +	pr_info("Intel TXT setup complete\n");
> +}
> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
> index a3414af..5d1ac8d 100644
> --- a/drivers/iommu/intel/dmar.c
> +++ b/drivers/iommu/intel/dmar.c
> @@ -28,6 +28,7 @@
>  #include <linux/iommu.h>
>  #include <linux/numa.h>
>  #include <linux/limits.h>
> +#include <linux/slaunch.h>
>  #include <asm/irq_remapping.h>
>  
>  #include "iommu.h"
> @@ -660,6 +661,9 @@ static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar,
>  	 */
>  	dmar_tbl = tboot_get_dmar_table(dmar_tbl);
>  
> +	/* If Secure Launch is active, it has similar logic */
> +	dmar_tbl = slaunch_get_dmar_table(dmar_tbl);
> +
>  	dmar = (struct acpi_table_dmar *)dmar_tbl;
>  	if (!dmar)
>  		return -ENODEV;
> -- 
> 1.8.3.1

Is it possible to test TXT in QEMU? Never done it so that's why I'm
asking.

BR, Jarkko

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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
@ 2023-05-10 23:02     ` Jarkko Sakkinen
  0 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-10 23:02 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
> The routine slaunch_setup is called out of the x86 specific setup_arch
> routine during early kernel boot. After determining what platform is
> present, various operations specific to that platform occur. This
> includes finalizing setting for the platform late launch and verifying
> that memory protections are in place.
>
> For TXT, this code also reserves the original compressed kernel setup
> area where the APs were left looping so that this memory cannot be used.
>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  arch/x86/kernel/Makefile   |   1 +
>  arch/x86/kernel/setup.c    |   3 +
>  arch/x86/kernel/slaunch.c  | 497 +++++++++++++++++++++++++++++++++++++++++++++
>  drivers/iommu/intel/dmar.c |   4 +
>  4 files changed, 505 insertions(+)
>  create mode 100644 arch/x86/kernel/slaunch.c
>
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index dd61752..3d2a33e 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -72,6 +72,7 @@ obj-$(CONFIG_X86_32)		+= tls.o
>  obj-$(CONFIG_IA32_EMULATION)	+= tls.o
>  obj-y				+= step.o
>  obj-$(CONFIG_INTEL_TXT)		+= tboot.o
> +obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
>  obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
>  obj-y				+= stacktrace.o
>  obj-y				+= cpu/
> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> index 16babff..592c09e 100644
> --- a/arch/x86/kernel/setup.c
> +++ b/arch/x86/kernel/setup.c
> @@ -21,6 +21,7 @@
>  #include <linux/root_dev.h>
>  #include <linux/hugetlb.h>
>  #include <linux/tboot.h>
> +#include <linux/slaunch.h>

Only because of pure curiosity: what made you choose this location in
the middle for the new include? :-)

>  #include <linux/usb/xhci-dbgp.h>
>  #include <linux/static_call.h>
>  #include <linux/swiotlb.h>
> @@ -1063,6 +1064,8 @@ void __init setup_arch(char **cmdline_p)
>  	early_gart_iommu_check();
>  #endif
>  
> +	slaunch_setup_txt();
> +
>  	/*
>  	 * partially used pages are not usable - thus
>  	 * we are rounding upwards:
> diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
> new file mode 100644
> index 0000000..7dba088
> --- /dev/null
> +++ b/arch/x86/kernel/slaunch.c
> @@ -0,0 +1,497 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Secure Launch late validation/setup and finalization support.
> + *
> + * Copyright (c) 2022, Oracle and/or its affiliates.
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/linkage.h>
> +#include <linux/mm.h>
> +#include <linux/io.h>
> +#include <linux/uaccess.h>
> +#include <linux/security.h>
> +#include <linux/memblock.h>
> +#include <asm/segment.h>
> +#include <asm/sections.h>
> +#include <asm/tlbflush.h>
> +#include <asm/e820/api.h>
> +#include <asm/setup.h>
> +#include <linux/slr_table.h>
> +#include <linux/slaunch.h>
> +
> +static u32 sl_flags;
> +static struct sl_ap_wake_info ap_wake_info;
> +static u64 evtlog_addr;
> +static u32 evtlog_size;
> +static u64 vtd_pmr_lo_size;
> +
> +/* This should be plenty of room */
> +static u8 txt_dmar[PAGE_SIZE] __aligned(16);
> +
> +u32 slaunch_get_flags(void)
> +{
> +	return sl_flags;
> +}
> +EXPORT_SYMBOL(slaunch_get_flags);
> +
> +struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
> +{
> +	return &ap_wake_info;
> +}
> +
> +struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
> +{
> +	/* The DMAR is only stashed and provided via TXT on Intel systems */
> +	if (memcmp(txt_dmar, "DMAR", 4))
> +		return dmar;
> +
> +	return (struct acpi_table_header *)(&txt_dmar[0]);
> +}
> +
> +void __noreturn slaunch_txt_reset(void __iomem *txt,
> +				  const char *msg, u64 error)
> +{
> +	u64 one = 1, val;
> +
> +	pr_err("%s", msg);
> +
> +	/*
> +	 * This performs a TXT reset with a sticky error code. The reads of
> +	 * TXT_CR_E2STS act as barriers.
> +	 */
> +	memcpy_toio(txt + TXT_CR_ERRORCODE, &error, sizeof(error));
> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> +	memcpy_toio(txt + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> +	memcpy_toio(txt + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> +	memcpy_toio(txt + TXT_CR_CMD_RESET, &one, sizeof(one));
> +
> +	for ( ; ; )
> +		asm volatile ("hlt");
> +
> +	unreachable();
> +}
> +
> +/*
> + * The TXT heap is too big to map all at once with early_ioremap
> + * so it is done a table at a time.
> + */
> +static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
> +					     u32 bytes)
> +{
> +	u64 base, size, offset = 0;
> +	void *heap;
> +	int i;
> +
> +	if (type > TXT_SINIT_TABLE_MAX)
> +		slaunch_txt_reset(txt,
> +			"Error invalid table type for early heap walk\n",
> +			SL_ERROR_HEAP_WALK);

Align with 'txt'.

> +
> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
> +
> +	/* Iterate over heap tables looking for table of "type" */
> +	for (i = 0; i < type; i++) {
> +		base += offset;
> +		heap = early_memremap(base, sizeof(u64));
> +		if (!heap)
> +			slaunch_txt_reset(txt,
> +				"Error early_memremap of heap for heap walk\n",
> +				SL_ERROR_HEAP_MAP);
> +
> +		offset = *((u64 *)heap);
> +
> +		/*
> +		 * After the first iteration, any offset of zero is invalid and
> +		 * implies the TXT heap is corrupted.
> +		 */
> +		if (!offset)
> +			slaunch_txt_reset(txt,
> +				"Error invalid 0 offset in heap walk\n",
> +				SL_ERROR_HEAP_ZERO_OFFSET);
> +
> +		early_memunmap(heap, sizeof(u64));
> +	}
> +
> +	/* Skip the size field at the head of each table */
> +	base += sizeof(u64);
> +	heap = early_memremap(base, bytes);
> +	if (!heap)
> +		slaunch_txt_reset(txt,
> +				  "Error early_memremap of heap section\n",
> +				  SL_ERROR_HEAP_MAP);
> +
> +	return heap;
> +}
> +
> +static void __init txt_early_put_heap_table(void *addr, unsigned long size)
> +{
> +	early_memunmap(addr, size);
> +}
> +
> +/*
> + * TXT uses a special set of VTd registers to protect all of memory from DMA
> + * until the IOMMU can be programmed to protect memory. There is the low
> + * memory PMR that can protect all memory up to 4G. The high memory PRM can
> + * be setup to protect all memory beyond 4Gb. Validate that these values cover
> + * what is expected.
> + */
> +static void __init slaunch_verify_pmrs(void __iomem *txt)
> +{
> +	struct txt_os_sinit_data *os_sinit_data;
> +	u32 field_offset, err = 0;
> +	const char *errmsg = "";
> +	unsigned long last_pfn;
> +
> +	field_offset = offsetof(struct txt_os_sinit_data, lcp_po_base);
> +	os_sinit_data = txt_early_get_heap_table(txt, TXT_OS_SINIT_DATA_TABLE,
> +						 field_offset);
> +
> +	/* Save a copy */
> +	vtd_pmr_lo_size = os_sinit_data->vtd_pmr_lo_size;
> +
> +	last_pfn = e820__end_of_ram_pfn();
> +
> +	/*
> +	 * First make sure the hi PMR covers all memory above 4G. In the
> +	 * unlikely case where there is < 4G on the system, the hi PMR will
> +	 * not be set.
> +	 */
> +	if (os_sinit_data->vtd_pmr_hi_base != 0x0ULL) {
> +		if (os_sinit_data->vtd_pmr_hi_base != 0x100000000ULL) {
> +			err = SL_ERROR_HI_PMR_BASE;
> +			errmsg =  "Error hi PMR base\n";
> +			goto out;
> +		}
> +
> +		if (PFN_PHYS(last_pfn) > os_sinit_data->vtd_pmr_hi_base +
> +		    os_sinit_data->vtd_pmr_hi_size) {
> +			err = SL_ERROR_HI_PMR_SIZE;
> +			errmsg = "Error hi PMR size\n";
> +			goto out;
> +		}
> +	}
> +
> +	/*
> +	 * Lo PMR base should always be 0. This was already checked in
> +	 * early stub.
> +	 */
> +
> +	/*
> +	 * Check that if the kernel was loaded below 4G, that it is protected
> +	 * by the lo PMR. Note this is the decompressed kernel. The ACM would
> +	 * have ensured the compressed kernel (the MLE image) was protected.
> +	 */
> +	if ((__pa_symbol(_end) < 0x100000000ULL) &&
> +	    (__pa_symbol(_end) > os_sinit_data->vtd_pmr_lo_size)) {
> +		err = SL_ERROR_LO_PMR_MLE;
> +		errmsg = "Error lo PMR does not cover MLE kernel\n";
> +	}
> +
> +	/*
> +	 * Other regions of interest like boot param, AP wake block, cmdline
> +	 * already checked for PMR coverage in the early stub code.
> +	 */
> +
> +out:
> +	txt_early_put_heap_table(os_sinit_data, field_offset);
> +
> +	if (err)
> +		slaunch_txt_reset(txt, errmsg, err);
> +}
> +
> +static void __init slaunch_txt_reserve_range(u64 base, u64 size)
> +{
> +	int type;
> +
> +	type = e820__get_entry_type(base, base + size - 1);
> +	if (type == E820_TYPE_RAM) {
> +		pr_info("memblock reserve base: %llx size: %llx\n", base, size);
> +		memblock_reserve(base, size);
> +	}
> +}
> +
> +/*
> + * For Intel, certain regions of memory must be marked as reserved by putting
> + * them on the memblock reserved list if they are not already e820 reserved.
> + * This includes:
> + *  - The TXT HEAP
> + *  - The ACM area
> + *  - The TXT private register bank
> + *  - The MDR list sent to the MLE by the ACM (see TXT specification)
> + *  (Normally the above are properly reserved by firmware but if it was not
> + *  done, reserve them now)
> + *  - The AP wake block
> + *  - TPM log external to the TXT heap
> + *
> + * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
> + * the low PMR must be reservered too.
> + */
> +static void __init slaunch_txt_reserve(void __iomem *txt)
> +{
> +	struct txt_sinit_memory_descriptor_record *mdr;
> +	struct txt_sinit_mle_data *sinit_mle_data;
> +	u64 base, size, heap_base, heap_size;
> +	u32 mdrnum, mdroffset, mdrslen;
> +	u32 field_offset, i;
> +	void *mdrs;
> +
> +	base = TXT_PRIV_CONFIG_REGS_BASE;
> +	size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
> +	slaunch_txt_reserve_range(base, size);
> +
> +	memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
> +	memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
> +	slaunch_txt_reserve_range(heap_base, heap_size);
> +
> +	memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
> +	memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
> +	slaunch_txt_reserve_range(base, size);
> +
> +	field_offset = offsetof(struct txt_sinit_mle_data,
> +				sinit_vtd_dmar_table_size);
> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +						  field_offset);
> +
> +	mdrnum = sinit_mle_data->num_of_sinit_mdrs;
> +	mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
> +
> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
> +
> +	if (!mdrnum)
> +		goto nomdr;
> +
> +	mdrslen = mdrnum * sizeof(struct txt_sinit_memory_descriptor_record);
> +
> +	mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +					mdroffset + mdrslen - 8);
> +
> +	mdr = mdrs + mdroffset - 8;
> +
> +	for (i = 0; i < mdrnum; i++, mdr++) {
> +		/* Spec says some entries can have length 0, ignore them */
> +		if (mdr->type > 0 && mdr->length > 0)
> +			slaunch_txt_reserve_range(mdr->address, mdr->length);
> +	}
> +
> +	txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
> +
> +nomdr:
> +	slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
> +				  ap_wake_info.ap_wake_block_size);
> +
> +	/*
> +	 * Earlier checks ensured that the event log was properly situated
> +	 * either inside the TXT heap or outside. This is a check to see if the
> +	 * event log needs to be reserved. If it is in the TXT heap, it is
> +	 * already reserved.
> +	 */
> +	if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
> +		slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
> +
> +	for (i = 0; i < e820_table->nr_entries; i++) {
> +		base = e820_table->entries[i].addr;
> +		size = e820_table->entries[i].size;
> +		if ((base >= vtd_pmr_lo_size) && (base < 0x100000000ULL))
> +			slaunch_txt_reserve_range(base, size);
> +		else if ((base < vtd_pmr_lo_size) &&
> +			 (base + size > vtd_pmr_lo_size))
> +			slaunch_txt_reserve_range(vtd_pmr_lo_size,
> +						  base + size - vtd_pmr_lo_size);
> +	}
> +}
> +
> +/*
> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
> + * It is stored in the TXT heap. Fetch it from there and make it available
> + * to the IOMMU driver.
> + */
> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
> +{
> +	struct txt_sinit_mle_data *sinit_mle_data;
> +	u32 field_offset, dmar_size, dmar_offset;
> +	void *dmar;
> +
> +	memset(&txt_dmar, 0, PAGE_SIZE);
> +
> +	field_offset = offsetof(struct txt_sinit_mle_data,
> +				processor_scrtm_status);
> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +						  field_offset);
> +
> +	dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
> +	dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
> +
> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
> +
> +	if (!dmar_size || !dmar_offset)
> +		slaunch_txt_reset(txt,
> +				  "Error invalid DMAR table values\n",
> +				  SL_ERROR_HEAP_INVALID_DMAR);
> +
> +	if (unlikely(dmar_size > PAGE_SIZE))
> +		slaunch_txt_reset(txt,
> +				  "Error DMAR too big to store\n",
> +				  SL_ERROR_HEAP_DMAR_SIZE);
> +
> +
> +	dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> +					dmar_offset + dmar_size - 8);
> +	if (!dmar)
> +		slaunch_txt_reset(txt,
> +				  "Error early_ioremap of DMAR\n",
> +				  SL_ERROR_HEAP_DMAR_MAP);
> +
> +	memcpy(&txt_dmar[0], dmar + dmar_offset - 8, dmar_size);
> +
> +	txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
> +}
> +
> +/*
> + * The location of the safe AP wake code block is stored in the TXT heap.
> + * Fetch needed values here in the early init code for later use in SMP
> + * startup.
> + *
> + * Also get the TPM event log values are in the SLRT and have to be fetched.
> + * They will be put on the memblock reserve list later.
> + */
> +static void __init slaunch_fetch_values(void __iomem *txt)
> +{
> +	struct txt_os_mle_data *os_mle_data;
> +	struct slr_entry_log_info *log_info;
> +	struct slr_table *slrt;
> +	u8 *jmp_offset;
> +	u32 size;
> +
> +	os_mle_data = txt_early_get_heap_table(txt, TXT_OS_MLE_DATA_TABLE,
> +					       sizeof(*os_mle_data));
> +
> +	ap_wake_info.ap_wake_block = os_mle_data->ap_wake_block;
> +	ap_wake_info.ap_wake_block_size = os_mle_data->ap_wake_block_size;
> +
> +	jmp_offset = os_mle_data->mle_scratch + SL_SCRATCH_AP_JMP_OFFSET;
> +	ap_wake_info.ap_jmp_offset = *((u32 *)jmp_offset);
> +
> +	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, sizeof(*slrt));
> +	if (!slrt)
> +		slaunch_txt_reset(txt,
> +			"Error early_memremap of SLRT failed\n",
> +			SL_ERROR_SLRT_MAP);
> +
> +	size = slrt->size;
> +	early_memunmap(slrt, sizeof(*slrt));
> +
> +	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, size);
> +	if (!slrt)
> +		slaunch_txt_reset(txt,
> +			"Error early_memremap of SLRT failed\n",
> +			SL_ERROR_SLRT_MAP);
> +
> +	log_info = (struct slr_entry_log_info *)
> +		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
> +
> +	if (!log_info)
> +		slaunch_txt_reset(txt,
> +				  "SLRT missing logging info entry\n",
> +				  SL_ERROR_SLRT_MISSING_ENTRY);
> +
> +	evtlog_addr = log_info->addr;
> +	evtlog_size = log_info->size;
> +
> +	early_memunmap(slrt, size);
> +
> +	txt_early_put_heap_table(os_mle_data, sizeof(*os_mle_data));
> +}
> +
> +/*
> + * Intel TXT specific late stub setup and validation.
> + */
> +void __init slaunch_setup_txt(void)
> +{
> +	u64 one = TXT_REGVALUE_ONE, val;
> +	void __iomem *txt;
> +
> +	if (!boot_cpu_has(X86_FEATURE_SMX))
> +		return;
> +
> +	/*
> +	 * If booted through secure launch entry point, the loadflags
> +	 * option will be set.
> +	 */
> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
> +		return;
> +
> +	/*
> +	 * See if SENTER was done by reading the status register in the
> +	 * public space. If the public register space cannot be read, TXT may
> +	 * be disabled.
> +	 */
> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +	if (!txt)
> +		return;
> +
> +	memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +
> +	/* SENTER should have been done */
> +	if (!(val & TXT_SENTER_DONE_STS))
> +		panic("Error TXT.STS SENTER_DONE not set\n");
> +
> +	/* SEXIT should have been cleared */
> +	if (val & TXT_SEXIT_DONE_STS)
> +		panic("Error TXT.STS SEXIT_DONE set\n");
> +
> +	/* Now we want to use the private register space */
> +	txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +	if (!txt) {
> +		/* This is really bad, no where to go from here */
> +		panic("Error early_ioremap of TXT priv registers\n");
> +	}
> +
> +	/*
> +	 * Try to read the Intel VID from the TXT private registers to see if
> +	 * TXT measured launch happened properly and the private space is
> +	 * available.
> +	 */
> +	memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
> +	if ((val & 0xffff) != 0x8086) {
> +		/*
> +		 * Can't do a proper TXT reset since it appears something is
> +		 * wrong even though SENTER happened and it should be in SMX
> +		 * mode.
> +		 */
> +		panic("Invalid TXT vendor ID, not in SMX mode\n");
> +	}
> +
> +	/* Set flags so subsequent code knows the status of the launch */
> +	sl_flags |= (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT);
> +
> +	/*
> +	 * Reading the proper DIDVID from the private register space means we
> +	 * are in SMX mode and private registers are open for read/write.
> +	 */
> +
> +	/* On Intel, have to handle TPM localities via TXT */
> +	memcpy_toio(txt + TXT_CR_CMD_SECRETS, &one, sizeof(one));
> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> +	memcpy_toio(txt + TXT_CR_CMD_OPEN_LOCALITY1, &one, sizeof(one));
> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> +
> +	slaunch_fetch_values(txt);
> +
> +	slaunch_verify_pmrs(txt);
> +
> +	slaunch_txt_reserve(txt);
> +
> +	slaunch_copy_dmar_table(txt);
> +
> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +
> +	pr_info("Intel TXT setup complete\n");
> +}
> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
> index a3414af..5d1ac8d 100644
> --- a/drivers/iommu/intel/dmar.c
> +++ b/drivers/iommu/intel/dmar.c
> @@ -28,6 +28,7 @@
>  #include <linux/iommu.h>
>  #include <linux/numa.h>
>  #include <linux/limits.h>
> +#include <linux/slaunch.h>
>  #include <asm/irq_remapping.h>
>  
>  #include "iommu.h"
> @@ -660,6 +661,9 @@ static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar,
>  	 */
>  	dmar_tbl = tboot_get_dmar_table(dmar_tbl);
>  
> +	/* If Secure Launch is active, it has similar logic */
> +	dmar_tbl = slaunch_get_dmar_table(dmar_tbl);
> +
>  	dmar = (struct acpi_table_dmar *)dmar_tbl;
>  	if (!dmar)
>  		return -ENODEV;
> -- 
> 1.8.3.1

Is it possible to test TXT in QEMU? Never done it so that's why I'm
asking.

BR, Jarkko

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-10 23:04     ` Jarkko Sakkinen
  -1 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-10 23:04 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
> Introduce the Secure Launch Resource Table which forms the formal
> interface between the pre and post launch code.
>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  include/linux/slr_table.h | 270 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 270 insertions(+)
>  create mode 100644 include/linux/slr_table.h
>
> diff --git a/include/linux/slr_table.h b/include/linux/slr_table.h
> new file mode 100644
> index 0000000..d4b76e5
> --- /dev/null
> +++ b/include/linux/slr_table.h
> @@ -0,0 +1,270 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Secure Launch Resource Table
> + *
> + * Copyright (c) 2023, Oracle and/or its affiliates.
> + */
> +
> +#ifndef _LINUX_SLR_TABLE_H
> +#define _LINUX_SLR_TABLE_H
> +
> +/* Put this in efi.h if it becomes a standard */
> +#define SLR_TABLE_GUID				EFI_GUID(0x877a9b2a, 0x0385, 0x45d1, 0xa0, 0x34, 0x9d, 0xac, 0x9c, 0x9e, 0x56, 0x5f)
> +
> +/* SLR table header values */
> +#define SLR_TABLE_MAGIC		0x4452544d
> +#define SLR_TABLE_REVISION	1
> +
> +/* Current revisions for the policy and UEFI config */
> +#define SLR_POLICY_REVISION		1
> +#define SLR_UEFI_CONFIG_REVISION	1
> +
> +/* SLR defined architectures */
> +#define SLR_INTEL_TXT		1
> +#define SLR_AMD_SKINIT		2
> +
> +/* SLR defined bootloaders */
> +#define SLR_BOOTLOADER_INVALID	0
> +#define SLR_BOOTLOADER_GRUB	1
> +
> +/* Log formats */
> +#define SLR_DRTM_TPM12_LOG	1
> +#define SLR_DRTM_TPM20_LOG	2
> +
> +/* DRTM Policy Entry Flags */
> +#define SLR_POLICY_FLAG_MEASURED	0x1
> +#define SLR_POLICY_IMPLICIT_SIZE	0x2
> +
> +/* Array Lengths */
> +#define TPM_EVENT_INFO_LENGTH		32
> +#define TXT_VARIABLE_MTRRS_LENGTH	32
> +
> +/* Tags */
> +#define SLR_ENTRY_INVALID	0x0000
> +#define SLR_ENTRY_DL_INFO	0x0001
> +#define SLR_ENTRY_LOG_INFO	0x0002
> +#define SLR_ENTRY_ENTRY_POLICY	0x0003
> +#define SLR_ENTRY_INTEL_INFO	0x0004
> +#define SLR_ENTRY_AMD_INFO	0x0005
> +#define SLR_ENTRY_ARM_INFO	0x0006
> +#define SLR_ENTRY_UEFI_INFO	0x0007
> +#define SLR_ENTRY_UEFI_CONFIG	0x0008
> +#define SLR_ENTRY_END		0xffff

"Enums are preferred when defining several related constants."

See:

https://www.kernel.org/doc/html/latest/process/coding-style.html#macros-enums-and-rtl

BR, Jarkko

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-05-10 23:04     ` Jarkko Sakkinen
  0 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-10 23:04 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
> Introduce the Secure Launch Resource Table which forms the formal
> interface between the pre and post launch code.
>
> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> ---
>  include/linux/slr_table.h | 270 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 270 insertions(+)
>  create mode 100644 include/linux/slr_table.h
>
> diff --git a/include/linux/slr_table.h b/include/linux/slr_table.h
> new file mode 100644
> index 0000000..d4b76e5
> --- /dev/null
> +++ b/include/linux/slr_table.h
> @@ -0,0 +1,270 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Secure Launch Resource Table
> + *
> + * Copyright (c) 2023, Oracle and/or its affiliates.
> + */
> +
> +#ifndef _LINUX_SLR_TABLE_H
> +#define _LINUX_SLR_TABLE_H
> +
> +/* Put this in efi.h if it becomes a standard */
> +#define SLR_TABLE_GUID				EFI_GUID(0x877a9b2a, 0x0385, 0x45d1, 0xa0, 0x34, 0x9d, 0xac, 0x9c, 0x9e, 0x56, 0x5f)
> +
> +/* SLR table header values */
> +#define SLR_TABLE_MAGIC		0x4452544d
> +#define SLR_TABLE_REVISION	1
> +
> +/* Current revisions for the policy and UEFI config */
> +#define SLR_POLICY_REVISION		1
> +#define SLR_UEFI_CONFIG_REVISION	1
> +
> +/* SLR defined architectures */
> +#define SLR_INTEL_TXT		1
> +#define SLR_AMD_SKINIT		2
> +
> +/* SLR defined bootloaders */
> +#define SLR_BOOTLOADER_INVALID	0
> +#define SLR_BOOTLOADER_GRUB	1
> +
> +/* Log formats */
> +#define SLR_DRTM_TPM12_LOG	1
> +#define SLR_DRTM_TPM20_LOG	2
> +
> +/* DRTM Policy Entry Flags */
> +#define SLR_POLICY_FLAG_MEASURED	0x1
> +#define SLR_POLICY_IMPLICIT_SIZE	0x2
> +
> +/* Array Lengths */
> +#define TPM_EVENT_INFO_LENGTH		32
> +#define TXT_VARIABLE_MTRRS_LENGTH	32
> +
> +/* Tags */
> +#define SLR_ENTRY_INVALID	0x0000
> +#define SLR_ENTRY_DL_INFO	0x0001
> +#define SLR_ENTRY_LOG_INFO	0x0002
> +#define SLR_ENTRY_ENTRY_POLICY	0x0003
> +#define SLR_ENTRY_INTEL_INFO	0x0004
> +#define SLR_ENTRY_AMD_INFO	0x0005
> +#define SLR_ENTRY_ARM_INFO	0x0006
> +#define SLR_ENTRY_UEFI_INFO	0x0007
> +#define SLR_ENTRY_UEFI_CONFIG	0x0008
> +#define SLR_ENTRY_END		0xffff

"Enums are preferred when defining several related constants."

See:

https://www.kernel.org/doc/html/latest/process/coding-style.html#macros-enums-and-rtl

BR, Jarkko

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-11  3:33     ` Herbert Xu
  -1 siblings, 0 replies; 200+ messages in thread
From: Herbert Xu @ 2023-05-11  3:33 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, ross.philipson, dpsmith, tglx, mingo,
	bp, hpa, ardb, mjg59, James.Bottomley, luto, nivedita,
	kanth.ghatraju, trenchboot-devel

Ross Philipson <ross.philipson@oracle.com> wrote:
>
> +static void __sha_transform(u32 *digest, const char *data)
> +{
> +       u32 ws[SHA1_WORKSPACE_WORDS];
> +
> +       sha1_transform(digest, data, ws);
> +
> +       memzero_explicit(ws, sizeof(ws));
> +}
> +
> +void early_sha1_init(struct sha1_state *sctx)
> +{
> +       sha1_init(sctx->state);
> +       sctx->count = 0;
> +}
> +
> +void early_sha1_update(struct sha1_state *sctx,
> +                      const u8 *data,
> +                      unsigned int len)
> +{
> +       unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
> +
> +       sctx->count += len;
> +
> +       if (likely((partial + len) >= SHA1_BLOCK_SIZE)) {
> +               int blocks;
> +
> +               if (partial) {
> +                       int p = SHA1_BLOCK_SIZE - partial;
> +
> +                       memcpy(sctx->buffer + partial, data, p);
> +                       data += p;
> +                       len -= p;
> +
> +                       __sha_transform(sctx->state, sctx->buffer);
> +               }
> +
> +               blocks = len / SHA1_BLOCK_SIZE;
> +               len %= SHA1_BLOCK_SIZE;
> +
> +               if (blocks) {
> +                       while (blocks--) {
> +                               __sha_transform(sctx->state, data);
> +                               data += SHA1_BLOCK_SIZE;
> +                       }
> +               }
> +               partial = 0;
> +       }
> +
> +       if (len)
> +               memcpy(sctx->buffer + partial, data, len);
> +}
> +
> +void early_sha1_final(struct sha1_state *sctx, u8 *out)
> +{
> +       const int bit_offset = SHA1_BLOCK_SIZE - sizeof(__be64);
> +       unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
> +       __be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
> +       __be32 *digest = (__be32 *)out;
> +       int i;
> +
> +       sctx->buffer[partial++] = 0x80;
> +       if (partial > bit_offset) {
> +               memset(sctx->buffer + partial, 0x0, SHA1_BLOCK_SIZE - partial);
> +               partial = 0;
> +
> +               __sha_transform(sctx->state, sctx->buffer);
> +       }
> +
> +       memset(sctx->buffer + partial, 0x0, bit_offset - partial);
> +       *bits = cpu_to_be64(sctx->count << 3);
> +       __sha_transform(sctx->state, sctx->buffer);
> +
> +       for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
> +               put_unaligned_be32(sctx->state[i], digest++);
> +
> +       *sctx = (struct sha1_state){};
> +}

If we're going to add SHA1 then this should go into lib/crypto
just like SHA2.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-11  3:33     ` Herbert Xu
  0 siblings, 0 replies; 200+ messages in thread
From: Herbert Xu @ 2023-05-11  3:33 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, ross.philipson, dpsmith, tglx, mingo,
	bp, hpa, ardb, mjg59, James.Bottomley, luto, nivedita,
	kanth.ghatraju, trenchboot-devel

Ross Philipson <ross.philipson@oracle.com> wrote:
>
> +static void __sha_transform(u32 *digest, const char *data)
> +{
> +       u32 ws[SHA1_WORKSPACE_WORDS];
> +
> +       sha1_transform(digest, data, ws);
> +
> +       memzero_explicit(ws, sizeof(ws));
> +}
> +
> +void early_sha1_init(struct sha1_state *sctx)
> +{
> +       sha1_init(sctx->state);
> +       sctx->count = 0;
> +}
> +
> +void early_sha1_update(struct sha1_state *sctx,
> +                      const u8 *data,
> +                      unsigned int len)
> +{
> +       unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
> +
> +       sctx->count += len;
> +
> +       if (likely((partial + len) >= SHA1_BLOCK_SIZE)) {
> +               int blocks;
> +
> +               if (partial) {
> +                       int p = SHA1_BLOCK_SIZE - partial;
> +
> +                       memcpy(sctx->buffer + partial, data, p);
> +                       data += p;
> +                       len -= p;
> +
> +                       __sha_transform(sctx->state, sctx->buffer);
> +               }
> +
> +               blocks = len / SHA1_BLOCK_SIZE;
> +               len %= SHA1_BLOCK_SIZE;
> +
> +               if (blocks) {
> +                       while (blocks--) {
> +                               __sha_transform(sctx->state, data);
> +                               data += SHA1_BLOCK_SIZE;
> +                       }
> +               }
> +               partial = 0;
> +       }
> +
> +       if (len)
> +               memcpy(sctx->buffer + partial, data, len);
> +}
> +
> +void early_sha1_final(struct sha1_state *sctx, u8 *out)
> +{
> +       const int bit_offset = SHA1_BLOCK_SIZE - sizeof(__be64);
> +       unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
> +       __be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
> +       __be32 *digest = (__be32 *)out;
> +       int i;
> +
> +       sctx->buffer[partial++] = 0x80;
> +       if (partial > bit_offset) {
> +               memset(sctx->buffer + partial, 0x0, SHA1_BLOCK_SIZE - partial);
> +               partial = 0;
> +
> +               __sha_transform(sctx->state, sctx->buffer);
> +       }
> +
> +       memset(sctx->buffer + partial, 0x0, bit_offset - partial);
> +       *bits = cpu_to_be64(sctx->count << 3);
> +       __sha_transform(sctx->state, sctx->buffer);
> +
> +       for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
> +               put_unaligned_be32(sctx->state[i], digest++);
> +
> +       *sctx = (struct sha1_state){};
> +}

If we're going to add SHA1 then this should go into lib/crypto
just like SHA2.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 09/14] x86: Secure Launch SMP bringup support
  2023-05-10 22:55     ` Jarkko Sakkinen
@ 2023-05-11 16:21       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-11 16:21 UTC (permalink / raw)
  To: Jarkko Sakkinen, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On 5/10/23 18:55, Jarkko Sakkinen wrote:
> On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
>> On Intel, the APs are left in a well documented state after TXT performs
>> the late launch. Specifically they cannot have #INIT asserted on them so
>> a standard startup via INIT/SIPI/SIPI cannot be performed. Instead the
>> early SL stub code parked the APs in a pause/jmp loop waiting for an NMI.
>> The modified SMP boot code is called for the Secure Launch case. The
>> jump address for the RM piggy entry point is fixed up in the jump where
>> the APs are waiting and an NMI IPI is sent to the AP. The AP vectors to
>> the Secure Launch entry point in the RM piggy which mimics what the real
>> mode code would do then jumps to the standard RM piggy protected mode
>> entry point.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   arch/x86/include/asm/realmode.h      |  3 ++
>>   arch/x86/kernel/smpboot.c            | 86 ++++++++++++++++++++++++++++++++++++
>>   arch/x86/realmode/rm/header.S        |  3 ++
>>   arch/x86/realmode/rm/trampoline_64.S | 37 ++++++++++++++++
>>   4 files changed, 129 insertions(+)
>>
>> diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
>> index f6a1737..576fe62 100644
>> --- a/arch/x86/include/asm/realmode.h
>> +++ b/arch/x86/include/asm/realmode.h
>> @@ -38,6 +38,9 @@ struct real_mode_header {
>>   #ifdef CONFIG_X86_64
>>   	u32	machine_real_restart_seg;
>>   #endif
>> +#ifdef CONFIG_SECURE_LAUNCH
>> +	u32	sl_trampoline_start32;
>> +#endif
> 
> Cool I was implementing this relocatable realmode blob back in 2012 :-)

It is fun stuff :)

> 
>>   };
>>   
>>   /* This must match data at realmode/rm/trampoline_{32,64}.S */
>> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
>> index 352f0ce..07d740be 100644
>> --- a/arch/x86/kernel/smpboot.c
>> +++ b/arch/x86/kernel/smpboot.c
>> @@ -57,6 +57,7 @@
>>   #include <linux/pgtable.h>
>>   #include <linux/overflow.h>
>>   #include <linux/stackprotector.h>
>> +#include <linux/slaunch.h>
>>   
>>   #include <asm/acpi.h>
>>   #include <asm/cacheinfo.h>
>> @@ -1068,6 +1069,83 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
>>   	return 0;
>>   }
>>   
>> +#ifdef CONFIG_SECURE_LAUNCH
>> +
>> +static atomic_t first_ap_only = {1};
> 
> This should be documented.

Will do

> 
>> +
>> +/*
>> + * Called to fix the long jump address for the waiting APs to vector to
>> + * the correct startup location in the Secure Launch stub in the rmpiggy.
>> + */
>> +static int
>> +slaunch_fixup_jump_vector(void)
> 
> Please put the same line.

Ack

> 
>> +{
>> +	struct sl_ap_wake_info *ap_wake_info;
>> +	u32 *ap_jmp_ptr = NULL;
>> +
>> +	if (!atomic_dec_and_test(&first_ap_only))
>> +		return 0;
>> +
>> +	ap_wake_info = slaunch_get_ap_wake_info();
>> +
>> +	ap_jmp_ptr = (u32 *)__va(ap_wake_info->ap_wake_block +
>> +				 ap_wake_info->ap_jmp_offset);
>> +
>> +	*ap_jmp_ptr = real_mode_header->sl_trampoline_start32;
>> +
>> +	pr_debug("TXT AP long jump address updated\n");
>> +
>> +	return 0;
>> +}
>> +
>> +/*
>> + * TXT AP startup is quite different than normal. The APs cannot have #INIT
>> + * asserted on them or receive SIPIs. The early Secure Launch code has parked
>> + * the APs in a pause loop waiting to receive an NMI. This will wake the APs
>> + * and have them jump to the protected mode code in the rmpiggy where the rest
>> + * of the SMP boot of the AP will proceed normally.
>> + */
>> +static int
>> +slaunch_wakeup_cpu_from_txt(int cpu, int apicid)
> 
> Ditto.
>

Ack

> 
>> +{
>> +	unsigned long send_status = 0, accept_status = 0;
> 
> I would put these to separate lines. Maybe a matter of taste but
> it is easier to spot initializations.

Sure

> 
>> +
>> +	/* Only done once */
>> +	if (slaunch_fixup_jump_vector())
>> +		return -1;
>> +
>> +	/* Send NMI IPI to idling AP and wake it up */
>> +	apic_icr_write(APIC_DM_NMI, apicid);
>> +
>> +	if (init_udelay == 0)
>> +		udelay(10);
>> +	else
>> +		udelay(300);
>> +
>> +	send_status = safe_apic_wait_icr_idle();
>> +
>> +	if (init_udelay == 0)
>> +		udelay(10);
>> +	else
>> +		udelay(300);
> 
> Magic numbers and no inline comment.

Much of this was copied as is from another function in this module. They 
did not have comments either. I will have to try to track down what 
motivated the delay logic.

> 
>> +
>> +	accept_status = (apic_read(APIC_ESR) & 0xEF);
>> +
>> +	if (send_status)
>> +		pr_err("Secure Launch IPI never delivered???\n");
>> +	if (accept_status)
>> +		pr_err("Secure Launch IPI delivery error (%lx)\n",
>> +			accept_status);
>> +
>> +	return (send_status | accept_status);
>> +}
>> +
>> +#else
>> +
>> +#define slaunch_wakeup_cpu_from_txt(cpu, apicid)	0
>> +
>> +#endif  /* !CONFIG_SECURE_LAUNCH */
>> +
>>   /*
>>    * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
>>    * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
>> @@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>>   	cpumask_clear_cpu(cpu, cpu_initialized_mask);
>>   	smp_mb();
>>   
>> +	/* With Intel TXT, the AP startup is totally different */
>> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==
>> +	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {
>> +		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
>> +		goto txt_wake;
>> +	}
>> +
>>   	/*
>>   	 * Wake up a CPU in difference cases:
>>   	 * - Use a method from the APIC driver if one defined, with wakeup
>> @@ -1147,6 +1232,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>>   		boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
>>   						     cpu0_nmi_registered);
>>   
>> +txt_wake:
>>   	if (!boot_error) {
>>   		/*
>>   		 * Wait 10s total for first sign of life from AP
>> diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
>> index 2eb62be..3b5cbcb 100644
>> --- a/arch/x86/realmode/rm/header.S
>> +++ b/arch/x86/realmode/rm/header.S
>> @@ -37,6 +37,9 @@ SYM_DATA_START(real_mode_header)
>>   #ifdef CONFIG_X86_64
>>   	.long	__KERNEL32_CS
>>   #endif
>> +#ifdef CONFIG_SECURE_LAUNCH
>> +	.long	pa_sl_trampoline_start32
>> +#endif
>>   SYM_DATA_END(real_mode_header)
>>   
>>   	/* End signature, used to verify integrity */
>> diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
>> index e38d61d..8bb4b0d 100644
>> --- a/arch/x86/realmode/rm/trampoline_64.S
>> +++ b/arch/x86/realmode/rm/trampoline_64.S
>> @@ -104,6 +104,43 @@ SYM_CODE_END(sev_es_trampoline_start)
>>   
>>   	.section ".text32","ax"
>>   	.code32
>> +#ifdef CONFIG_SECURE_LAUNCH
>> +	.balign 4
>> +SYM_CODE_START(sl_trampoline_start32)
>> +	/*
>> +	 * The early secure launch stub AP wakeup code has taken care of all
>> +	 * the vagaries of launching out of TXT. This bit just mimics what the
>> +	 * 16b entry code does and jumps off to the real startup_32.
>> +	 */
>> +	cli
>> +	wbinvd
>> +
>> +	/*
>> +	 * The %ebx provided is not terribly useful since it is the physical
>> +	 * address of tb_trampoline_start and not the base of the image.
>> +	 * Use pa_real_mode_base, which is fixed up, to get a run time
>> +	 * base register to use for offsets to location that do not have
>> +	 * pa_ symbols.
>> +	 */
>> +	movl    $pa_real_mode_base, %ebx
>> +
>> +	/*
>> +	 * This may seem a little odd but this is what %esp would have had in
>> +	 * it on the jmp from real mode because all real mode fixups were done
>> +	 * via the code segment. The base is added at the 32b entry.
>> +	 */
>> +	movl	rm_stack_end, %esp
>> +
>> +	lgdt    tr_gdt(%ebx)
>> +	lidt    tr_idt(%ebx)
>> +
>> +	movw	$__KERNEL_DS, %dx	# Data segment descriptor
>> +
>> +	/* Jump to where the 16b code would have jumped */
>> +	ljmpl	$__KERNEL32_CS, $pa_startup_32
>> +SYM_CODE_END(sl_trampoline_start32)
>> +#endif
>> +
>>   	.balign 4
>>   SYM_CODE_START(startup_32)
>>   	movl	%edx, %ss
>> -- 
>> 1.8.3.1
> 
> 
> The trampoline_64.S changes look reasonable to me (with a quick look).
> 
> BR, Jarkko

Thanks for the review,
Ross

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

* Re: [PATCH v6 09/14] x86: Secure Launch SMP bringup support
@ 2023-05-11 16:21       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-11 16:21 UTC (permalink / raw)
  To: Jarkko Sakkinen, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On 5/10/23 18:55, Jarkko Sakkinen wrote:
> On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
>> On Intel, the APs are left in a well documented state after TXT performs
>> the late launch. Specifically they cannot have #INIT asserted on them so
>> a standard startup via INIT/SIPI/SIPI cannot be performed. Instead the
>> early SL stub code parked the APs in a pause/jmp loop waiting for an NMI.
>> The modified SMP boot code is called for the Secure Launch case. The
>> jump address for the RM piggy entry point is fixed up in the jump where
>> the APs are waiting and an NMI IPI is sent to the AP. The AP vectors to
>> the Secure Launch entry point in the RM piggy which mimics what the real
>> mode code would do then jumps to the standard RM piggy protected mode
>> entry point.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   arch/x86/include/asm/realmode.h      |  3 ++
>>   arch/x86/kernel/smpboot.c            | 86 ++++++++++++++++++++++++++++++++++++
>>   arch/x86/realmode/rm/header.S        |  3 ++
>>   arch/x86/realmode/rm/trampoline_64.S | 37 ++++++++++++++++
>>   4 files changed, 129 insertions(+)
>>
>> diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
>> index f6a1737..576fe62 100644
>> --- a/arch/x86/include/asm/realmode.h
>> +++ b/arch/x86/include/asm/realmode.h
>> @@ -38,6 +38,9 @@ struct real_mode_header {
>>   #ifdef CONFIG_X86_64
>>   	u32	machine_real_restart_seg;
>>   #endif
>> +#ifdef CONFIG_SECURE_LAUNCH
>> +	u32	sl_trampoline_start32;
>> +#endif
> 
> Cool I was implementing this relocatable realmode blob back in 2012 :-)

It is fun stuff :)

> 
>>   };
>>   
>>   /* This must match data at realmode/rm/trampoline_{32,64}.S */
>> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
>> index 352f0ce..07d740be 100644
>> --- a/arch/x86/kernel/smpboot.c
>> +++ b/arch/x86/kernel/smpboot.c
>> @@ -57,6 +57,7 @@
>>   #include <linux/pgtable.h>
>>   #include <linux/overflow.h>
>>   #include <linux/stackprotector.h>
>> +#include <linux/slaunch.h>
>>   
>>   #include <asm/acpi.h>
>>   #include <asm/cacheinfo.h>
>> @@ -1068,6 +1069,83 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
>>   	return 0;
>>   }
>>   
>> +#ifdef CONFIG_SECURE_LAUNCH
>> +
>> +static atomic_t first_ap_only = {1};
> 
> This should be documented.

Will do

> 
>> +
>> +/*
>> + * Called to fix the long jump address for the waiting APs to vector to
>> + * the correct startup location in the Secure Launch stub in the rmpiggy.
>> + */
>> +static int
>> +slaunch_fixup_jump_vector(void)
> 
> Please put the same line.

Ack

> 
>> +{
>> +	struct sl_ap_wake_info *ap_wake_info;
>> +	u32 *ap_jmp_ptr = NULL;
>> +
>> +	if (!atomic_dec_and_test(&first_ap_only))
>> +		return 0;
>> +
>> +	ap_wake_info = slaunch_get_ap_wake_info();
>> +
>> +	ap_jmp_ptr = (u32 *)__va(ap_wake_info->ap_wake_block +
>> +				 ap_wake_info->ap_jmp_offset);
>> +
>> +	*ap_jmp_ptr = real_mode_header->sl_trampoline_start32;
>> +
>> +	pr_debug("TXT AP long jump address updated\n");
>> +
>> +	return 0;
>> +}
>> +
>> +/*
>> + * TXT AP startup is quite different than normal. The APs cannot have #INIT
>> + * asserted on them or receive SIPIs. The early Secure Launch code has parked
>> + * the APs in a pause loop waiting to receive an NMI. This will wake the APs
>> + * and have them jump to the protected mode code in the rmpiggy where the rest
>> + * of the SMP boot of the AP will proceed normally.
>> + */
>> +static int
>> +slaunch_wakeup_cpu_from_txt(int cpu, int apicid)
> 
> Ditto.
>

Ack

> 
>> +{
>> +	unsigned long send_status = 0, accept_status = 0;
> 
> I would put these to separate lines. Maybe a matter of taste but
> it is easier to spot initializations.

Sure

> 
>> +
>> +	/* Only done once */
>> +	if (slaunch_fixup_jump_vector())
>> +		return -1;
>> +
>> +	/* Send NMI IPI to idling AP and wake it up */
>> +	apic_icr_write(APIC_DM_NMI, apicid);
>> +
>> +	if (init_udelay == 0)
>> +		udelay(10);
>> +	else
>> +		udelay(300);
>> +
>> +	send_status = safe_apic_wait_icr_idle();
>> +
>> +	if (init_udelay == 0)
>> +		udelay(10);
>> +	else
>> +		udelay(300);
> 
> Magic numbers and no inline comment.

Much of this was copied as is from another function in this module. They 
did not have comments either. I will have to try to track down what 
motivated the delay logic.

> 
>> +
>> +	accept_status = (apic_read(APIC_ESR) & 0xEF);
>> +
>> +	if (send_status)
>> +		pr_err("Secure Launch IPI never delivered???\n");
>> +	if (accept_status)
>> +		pr_err("Secure Launch IPI delivery error (%lx)\n",
>> +			accept_status);
>> +
>> +	return (send_status | accept_status);
>> +}
>> +
>> +#else
>> +
>> +#define slaunch_wakeup_cpu_from_txt(cpu, apicid)	0
>> +
>> +#endif  /* !CONFIG_SECURE_LAUNCH */
>> +
>>   /*
>>    * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
>>    * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
>> @@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>>   	cpumask_clear_cpu(cpu, cpu_initialized_mask);
>>   	smp_mb();
>>   
>> +	/* With Intel TXT, the AP startup is totally different */
>> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==
>> +	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {
>> +		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
>> +		goto txt_wake;
>> +	}
>> +
>>   	/*
>>   	 * Wake up a CPU in difference cases:
>>   	 * - Use a method from the APIC driver if one defined, with wakeup
>> @@ -1147,6 +1232,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>>   		boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
>>   						     cpu0_nmi_registered);
>>   
>> +txt_wake:
>>   	if (!boot_error) {
>>   		/*
>>   		 * Wait 10s total for first sign of life from AP
>> diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
>> index 2eb62be..3b5cbcb 100644
>> --- a/arch/x86/realmode/rm/header.S
>> +++ b/arch/x86/realmode/rm/header.S
>> @@ -37,6 +37,9 @@ SYM_DATA_START(real_mode_header)
>>   #ifdef CONFIG_X86_64
>>   	.long	__KERNEL32_CS
>>   #endif
>> +#ifdef CONFIG_SECURE_LAUNCH
>> +	.long	pa_sl_trampoline_start32
>> +#endif
>>   SYM_DATA_END(real_mode_header)
>>   
>>   	/* End signature, used to verify integrity */
>> diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
>> index e38d61d..8bb4b0d 100644
>> --- a/arch/x86/realmode/rm/trampoline_64.S
>> +++ b/arch/x86/realmode/rm/trampoline_64.S
>> @@ -104,6 +104,43 @@ SYM_CODE_END(sev_es_trampoline_start)
>>   
>>   	.section ".text32","ax"
>>   	.code32
>> +#ifdef CONFIG_SECURE_LAUNCH
>> +	.balign 4
>> +SYM_CODE_START(sl_trampoline_start32)
>> +	/*
>> +	 * The early secure launch stub AP wakeup code has taken care of all
>> +	 * the vagaries of launching out of TXT. This bit just mimics what the
>> +	 * 16b entry code does and jumps off to the real startup_32.
>> +	 */
>> +	cli
>> +	wbinvd
>> +
>> +	/*
>> +	 * The %ebx provided is not terribly useful since it is the physical
>> +	 * address of tb_trampoline_start and not the base of the image.
>> +	 * Use pa_real_mode_base, which is fixed up, to get a run time
>> +	 * base register to use for offsets to location that do not have
>> +	 * pa_ symbols.
>> +	 */
>> +	movl    $pa_real_mode_base, %ebx
>> +
>> +	/*
>> +	 * This may seem a little odd but this is what %esp would have had in
>> +	 * it on the jmp from real mode because all real mode fixups were done
>> +	 * via the code segment. The base is added at the 32b entry.
>> +	 */
>> +	movl	rm_stack_end, %esp
>> +
>> +	lgdt    tr_gdt(%ebx)
>> +	lidt    tr_idt(%ebx)
>> +
>> +	movw	$__KERNEL_DS, %dx	# Data segment descriptor
>> +
>> +	/* Jump to where the 16b code would have jumped */
>> +	ljmpl	$__KERNEL32_CS, $pa_startup_32
>> +SYM_CODE_END(sl_trampoline_start32)
>> +#endif
>> +
>>   	.balign 4
>>   SYM_CODE_START(startup_32)
>>   	movl	%edx, %ss
>> -- 
>> 1.8.3.1
> 
> 
> The trampoline_64.S changes look reasonable to me (with a quick look).
> 
> BR, Jarkko

Thanks for the review,
Ross

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-12 10:47     ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 10:47 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
> +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
> +built with KASLR disabled::

Why does Secure Launch not interoperate with KASLR?

Re: IOMMUs

> +It is recommended that no other command line options should be set to override
> +the defaults above.

What happens if they are? Does doing so change the security posture of 
the system? If so, will the measurements be different in a way that 
demonstrates the system is in an insecure state?


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
@ 2023-05-12 10:47     ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 10:47 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
> +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
> +built with KASLR disabled::

Why does Secure Launch not interoperate with KASLR?

Re: IOMMUs

> +It is recommended that no other command line options should be set to override
> +the defaults above.

What happens if they are? Does doing so change the security posture of 
the system? If so, will the measurements be different in a way that 
demonstrates the system is in an insecure state?


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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-12 10:55     ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 10:55 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:13PM +0000, Ross Philipson wrote:

> +#define SLR_TABLE_MAGIC		0x4452544d

From convention I'd expect this to be 0x534c5254, but not really an 
issue.

> +/* SLR defined bootloaders */
> +#define SLR_BOOTLOADER_INVALID	0
> +#define SLR_BOOTLOADER_GRUB	1

Oof. Having the kernel know about bootloaders has not worked out super 
well for us in the past. If someone writes a new bootloader, are they 
unable to Secure Launch any existing kernels? The pragmatic thing for 
them to do would be to just pretend they're grub, which kind of defeats 
the point of having this definition...

> +} __packed;

Random nit - why are they all packed? Are there circumstances where two 
pieces of code with different assumptions about alignment will be 
looking at a single instance of a table? It doesn't seem likely we're 
going to be doing DRTM in a 32-bit firmware environment while launching 
a 64-bit kernel?

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-05-12 10:55     ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 10:55 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:13PM +0000, Ross Philipson wrote:

> +#define SLR_TABLE_MAGIC		0x4452544d

From convention I'd expect this to be 0x534c5254, but not really an 
issue.

> +/* SLR defined bootloaders */
> +#define SLR_BOOTLOADER_INVALID	0
> +#define SLR_BOOTLOADER_GRUB	1

Oof. Having the kernel know about bootloaders has not worked out super 
well for us in the past. If someone writes a new bootloader, are they 
unable to Secure Launch any existing kernels? The pragmatic thing for 
them to do would be to just pretend they're grub, which kind of defeats 
the point of having this definition...

> +} __packed;

Random nit - why are they all packed? Are there circumstances where two 
pieces of code with different assumptions about alignment will be 
looking at a single instance of a table? It doesn't seem likely we're 
going to be doing DRTM in a 32-bit firmware environment while launching 
a 64-bit kernel?

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

* Re: [PATCH v6 05/14] x86: Secure Launch main header file
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-12 11:00     ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 11:00 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:14PM +0000, Ross Philipson wrote:

> +static inline int tpm12_log_event(void *evtlog_base, u32 evtlog_size,
> +				  u32 event_size, void *event)
> +{
> +	struct tpm12_event_log_header *evtlog =
> +		(struct tpm12_event_log_header *)evtlog_base;
> +
> +	if (memcmp(evtlog->signature, TPM12_EVTLOG_SIGNATURE,
> +		   sizeof(TPM12_EVTLOG_SIGNATURE)))
> +		return -EINVAL;
> +
> +	if (evtlog->container_size > evtlog_size)
> +		return -EINVAL;
> +
> +	if (evtlog->next_event_offset + event_size > evtlog->container_size)
> +		return -E2BIG;
> +
> +	memcpy(evtlog_base + evtlog->next_event_offset, event, event_size);
> +	evtlog->next_event_offset += event_size;
> +
> +	return 0;
> +}
> +
> +static inline int tpm20_log_event(struct txt_heap_event_log_pointer2_1_element *elem,
> +				  void *evtlog_base, u32 evtlog_size,
> +				  u32 event_size, void *event)
> +{
> +	struct tcg_pcr_event *header =
> +		(struct tcg_pcr_event *)evtlog_base;
> +
> +	/* Has to be at least big enough for the signature */
> +	if (header->event_size < sizeof(TCG_SPECID_SIG))
> +		return -EINVAL;
> +
> +	if (memcmp((u8 *)header + sizeof(struct tcg_pcr_event),
> +		   TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
> +		return -EINVAL;
> +
> +	if (elem->allocated_event_container_size > evtlog_size)
> +		return -EINVAL;
> +
> +	if (elem->next_record_offset + event_size >
> +	    elem->allocated_event_container_size)
> +		return -E2BIG;
> +
> +	memcpy(evtlog_base + elem->next_record_offset, event, event_size);
> +	elem->next_record_offset += event_size;
> +
> +	return 0;
> +}
> +

These seem like they'd potentially be useful outside the context of SL, 
maybe put them in a more generic location? Very much a nice to have, not 
a blocker from my side.

> +/*
> + * External functions avalailable in mainline kernel.

Nit: "available"


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 05/14] x86: Secure Launch main header file
@ 2023-05-12 11:00     ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 11:00 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:14PM +0000, Ross Philipson wrote:

> +static inline int tpm12_log_event(void *evtlog_base, u32 evtlog_size,
> +				  u32 event_size, void *event)
> +{
> +	struct tpm12_event_log_header *evtlog =
> +		(struct tpm12_event_log_header *)evtlog_base;
> +
> +	if (memcmp(evtlog->signature, TPM12_EVTLOG_SIGNATURE,
> +		   sizeof(TPM12_EVTLOG_SIGNATURE)))
> +		return -EINVAL;
> +
> +	if (evtlog->container_size > evtlog_size)
> +		return -EINVAL;
> +
> +	if (evtlog->next_event_offset + event_size > evtlog->container_size)
> +		return -E2BIG;
> +
> +	memcpy(evtlog_base + evtlog->next_event_offset, event, event_size);
> +	evtlog->next_event_offset += event_size;
> +
> +	return 0;
> +}
> +
> +static inline int tpm20_log_event(struct txt_heap_event_log_pointer2_1_element *elem,
> +				  void *evtlog_base, u32 evtlog_size,
> +				  u32 event_size, void *event)
> +{
> +	struct tcg_pcr_event *header =
> +		(struct tcg_pcr_event *)evtlog_base;
> +
> +	/* Has to be at least big enough for the signature */
> +	if (header->event_size < sizeof(TCG_SPECID_SIG))
> +		return -EINVAL;
> +
> +	if (memcmp((u8 *)header + sizeof(struct tcg_pcr_event),
> +		   TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
> +		return -EINVAL;
> +
> +	if (elem->allocated_event_container_size > evtlog_size)
> +		return -EINVAL;
> +
> +	if (elem->next_record_offset + event_size >
> +	    elem->allocated_event_container_size)
> +		return -E2BIG;
> +
> +	memcpy(evtlog_base + elem->next_record_offset, event, event_size);
> +	elem->next_record_offset += event_size;
> +
> +	return 0;
> +}
> +

These seem like they'd potentially be useful outside the context of SL, 
maybe put them in a more generic location? Very much a nice to have, not 
a blocker from my side.

> +/*
> + * External functions avalailable in mainline kernel.

Nit: "available"


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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-10  1:21     ` Eric Biggers
@ 2023-05-12 11:04       ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 11:04 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp,
	hpa, ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:

> SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> now?

TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also 
at the whim of the firmware in terms of whether the SHA-2 banks are 
enabled. But even if the SHA-2 banks are enabled, if you suddenly stop 
extending the SHA-1 banks, a malicious actor can later turn up and 
extend whatever they want into them and present a SHA-1-only 
attestation. Ideally whatever is handling that attestation should know 
whether or not to expect an attestation with SHA-2, but the easiest way 
to maintain security is to always extend all banks.
 

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-12 11:04       ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 11:04 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp,
	hpa, ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:

> SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> now?

TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also 
at the whim of the firmware in terms of whether the SHA-2 banks are 
enabled. But even if the SHA-2 banks are enabled, if you suddenly stop 
extending the SHA-1 banks, a malicious actor can later turn up and 
extend whatever they want into them and present a SHA-1-only 
attestation. Ideally whatever is handling that attestation should know 
whether or not to expect an attestation with SHA-2, but the easiest way 
to maintain security is to always extend all banks.
 

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-12 11:04       ` Matthew Garrett
@ 2023-05-12 11:18         ` Ard Biesheuvel
  -1 siblings, 0 replies; 200+ messages in thread
From: Ard Biesheuvel @ 2023-05-12 11:18 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Eric Biggers, Ross Philipson, linux-kernel, x86, linux-integrity,
	linux-doc, linux-crypto, iommu, kexec, linux-efi, dpsmith, tglx,
	mingo, bp, hpa, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, 12 May 2023 at 13:04, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>
> On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:
>
> > SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> > now?
>
> TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also
> at the whim of the firmware in terms of whether the SHA-2 banks are
> enabled. But even if the SHA-2 banks are enabled, if you suddenly stop
> extending the SHA-1 banks, a malicious actor can later turn up and
> extend whatever they want into them and present a SHA-1-only
> attestation. Ideally whatever is handling that attestation should know
> whether or not to expect an attestation with SHA-2, but the easiest way
> to maintain security is to always extend all banks.
>

Wouldn't it make more sense to measure some terminating event into the
SHA-1 banks instead?

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-12 11:18         ` Ard Biesheuvel
  0 siblings, 0 replies; 200+ messages in thread
From: Ard Biesheuvel @ 2023-05-12 11:18 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Eric Biggers, Ross Philipson, linux-kernel, x86, linux-integrity,
	linux-doc, linux-crypto, iommu, kexec, linux-efi, dpsmith, tglx,
	mingo, bp, hpa, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, 12 May 2023 at 13:04, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>
> On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:
>
> > SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> > now?
>
> TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also
> at the whim of the firmware in terms of whether the SHA-2 banks are
> enabled. But even if the SHA-2 banks are enabled, if you suddenly stop
> extending the SHA-1 banks, a malicious actor can later turn up and
> extend whatever they want into them and present a SHA-1-only
> attestation. Ideally whatever is handling that attestation should know
> whether or not to expect an attestation with SHA-2, but the easiest way
> to maintain security is to always extend all banks.
>

Wouldn't it make more sense to measure some terminating event into the
SHA-1 banks instead?

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-12 11:26     ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 11:26 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:16PM +0000, Ross Philipson wrote:

> +static void sl_find_event_log(struct slr_table *slrt)

If this is called after the EFI stub then we're presumably 
post-ExitBootServices and we're copied the TPM event log into a 
configuration table so it's available to the runtime kernel. That also 
means that we should be adding all further measurements to the Final 
Events Table rather than the initial event log. How's that handled here, 
both in terms of ensuring further events (generated by firmware or by 
us) get added to the right place, and in terms of ensuring the event 
logs the kernel has later on were covered appropriately? Or is the SL 
event log an entirely different thing that can be merged in later 
because it only covers the DRTM PCRs?

> +static void sl_extend_setup_data(struct slr_policy_entry *entry)
> +{
> +	struct setup_data *data;
> +
> +	/*
> +	 * Measuring the boot params measured the fixed e820 memory map.
> +	 * Measure any setup_data entries including e820 extended entries.
> +	 */
> +	data = (struct setup_data *)(unsigned long)entry->entity;
> +	while (data)
> +		data = sl_handle_setup_data(data, entry);
> +}

Is e820 sufficient here? There are cases where we use the EFI memory map 
directly (sorry), but I don't know if any of them are relevant to DRTM 
outcomes.

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-05-12 11:26     ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 11:26 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:16PM +0000, Ross Philipson wrote:

> +static void sl_find_event_log(struct slr_table *slrt)

If this is called after the EFI stub then we're presumably 
post-ExitBootServices and we're copied the TPM event log into a 
configuration table so it's available to the runtime kernel. That also 
means that we should be adding all further measurements to the Final 
Events Table rather than the initial event log. How's that handled here, 
both in terms of ensuring further events (generated by firmware or by 
us) get added to the right place, and in terms of ensuring the event 
logs the kernel has later on were covered appropriately? Or is the SL 
event log an entirely different thing that can be merged in later 
because it only covers the DRTM PCRs?

> +static void sl_extend_setup_data(struct slr_policy_entry *entry)
> +{
> +	struct setup_data *data;
> +
> +	/*
> +	 * Measuring the boot params measured the fixed e820 memory map.
> +	 * Measure any setup_data entries including e820 extended entries.
> +	 */
> +	data = (struct setup_data *)(unsigned long)entry->entity;
> +	while (data)
> +		data = sl_handle_setup_data(data, entry);
> +}

Is e820 sufficient here? There are cases where we use the EFI memory map 
directly (sorry), but I don't know if any of them are relevant to DRTM 
outcomes.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-12 11:18         ` Ard Biesheuvel
@ 2023-05-12 11:28           ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 11:28 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Eric Biggers, Ross Philipson, linux-kernel, x86, linux-integrity,
	linux-doc, linux-crypto, iommu, kexec, linux-efi, dpsmith, tglx,
	mingo, bp, hpa, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, May 12, 2023 at 01:18:45PM +0200, Ard Biesheuvel wrote:
> On Fri, 12 May 2023 at 13:04, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> >
> > On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:
> >
> > > SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> > > now?
> >
> > TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also
> > at the whim of the firmware in terms of whether the SHA-2 banks are
> > enabled. But even if the SHA-2 banks are enabled, if you suddenly stop
> > extending the SHA-1 banks, a malicious actor can later turn up and
> > extend whatever they want into them and present a SHA-1-only
> > attestation. Ideally whatever is handling that attestation should know
> > whether or not to expect an attestation with SHA-2, but the easiest way
> > to maintain security is to always extend all banks.
> >
> 
> Wouldn't it make more sense to measure some terminating event into the
> SHA-1 banks instead?

Unless we assert that SHA-1 events are unsupported, it seems a bit odd 
to force a policy on people who have both banks enabled. People with 
mixed fleets are potentially going to be dealing with SHA-1 measurements 
for a while yet, and while there's obviously a security benefit in using 
SHA-2 instead it'd be irritating to have to maintain two attestation 
policies.

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-12 11:28           ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 11:28 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Eric Biggers, Ross Philipson, linux-kernel, x86, linux-integrity,
	linux-doc, linux-crypto, iommu, kexec, linux-efi, dpsmith, tglx,
	mingo, bp, hpa, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, May 12, 2023 at 01:18:45PM +0200, Ard Biesheuvel wrote:
> On Fri, 12 May 2023 at 13:04, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> >
> > On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:
> >
> > > SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> > > now?
> >
> > TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also
> > at the whim of the firmware in terms of whether the SHA-2 banks are
> > enabled. But even if the SHA-2 banks are enabled, if you suddenly stop
> > extending the SHA-1 banks, a malicious actor can later turn up and
> > extend whatever they want into them and present a SHA-1-only
> > attestation. Ideally whatever is handling that attestation should know
> > whether or not to expect an attestation with SHA-2, but the easiest way
> > to maintain security is to always extend all banks.
> >
> 
> Wouldn't it make more sense to measure some terminating event into the
> SHA-1 banks instead?

Unless we assert that SHA-1 events are unsupported, it seems a bit odd 
to force a policy on people who have both banks enabled. People with 
mixed fleets are potentially going to be dealing with SHA-1 measurements 
for a while yet, and while there's obviously a security benefit in using 
SHA-2 instead it'd be irritating to have to maintain two attestation 
policies.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 11/14] reboot: Secure Launch SEXIT support on reboot paths
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-12 11:40     ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 11:40 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:20PM +0000, Ross Philipson wrote:
> If the MLE kernel is being powered off, rebooted or halted,
> then SEXIT must be called. Note that the SEXIT GETSEC leaf
> can only be called after a machine_shutdown() has been done on
> these paths. The machine_shutdown() is not called on a few paths
> like when poweroff action does not have a poweroff callback (into
> ACPI code) or when an emergency reset is done. In these cases,
> just the TXT registers are finalized but SEXIT is skipped.

What are the consequences of SEXIT not being called, and why is it ok to 
skip it in these circumstances?

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

* Re: [PATCH v6 11/14] reboot: Secure Launch SEXIT support on reboot paths
@ 2023-05-12 11:40     ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 11:40 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:20PM +0000, Ross Philipson wrote:
> If the MLE kernel is being powered off, rebooted or halted,
> then SEXIT must be called. Note that the SEXIT GETSEC leaf
> can only be called after a machine_shutdown() has been done on
> these paths. The machine_shutdown() is not called on a few paths
> like when poweroff action does not have a poweroff callback (into
> ACPI code) or when an emergency reset is done. In these cases,
> just the TXT registers are finalized but SEXIT is skipped.

What are the consequences of SEXIT not being called, and why is it ok to 
skip it in these circumstances?

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 13/14] tpm: Allow locality 2 to be set when initializing the TPM for Secure Launch
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-12 11:43     ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 11:43 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:22PM +0000, Ross Philipson wrote:
> The Secure Launch MLE environment uses PCRs that are only accessible from
> the DRTM locality 2. By default the TPM drivers always initialize the
> locality to 0. When a Secure Launch is in progress, initialize the
> locality to 2.

This looks correct in itself, but looking at the CRB driver code I don't 
think locality support is actually implemented. Are there any SL systems 
using CRB?

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

* Re: [PATCH v6 13/14] tpm: Allow locality 2 to be set when initializing the TPM for Secure Launch
@ 2023-05-12 11:43     ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 11:43 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04, 2023 at 02:50:22PM +0000, Ross Philipson wrote:
> The Secure Launch MLE environment uses PCRs that are only accessible from
> the DRTM locality 2. By default the TPM drivers always initialize the
> locality to 0. When a Secure Launch is in progress, initialize the
> locality to 2.

This looks correct in itself, but looking at the CRB driver code I don't 
think locality support is actually implemented. Are there any SL systems 
using CRB?

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-12 11:28           ` Matthew Garrett
@ 2023-05-12 11:58             ` Ard Biesheuvel
  -1 siblings, 0 replies; 200+ messages in thread
From: Ard Biesheuvel @ 2023-05-12 11:58 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Eric Biggers, Ross Philipson, linux-kernel, x86, linux-integrity,
	linux-doc, linux-crypto, iommu, kexec, linux-efi, dpsmith, tglx,
	mingo, bp, hpa, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, 12 May 2023 at 13:28, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>
> On Fri, May 12, 2023 at 01:18:45PM +0200, Ard Biesheuvel wrote:
> > On Fri, 12 May 2023 at 13:04, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> > >
> > > On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:
> > >
> > > > SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> > > > now?
> > >
> > > TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also
> > > at the whim of the firmware in terms of whether the SHA-2 banks are
> > > enabled. But even if the SHA-2 banks are enabled, if you suddenly stop
> > > extending the SHA-1 banks, a malicious actor can later turn up and
> > > extend whatever they want into them and present a SHA-1-only
> > > attestation. Ideally whatever is handling that attestation should know
> > > whether or not to expect an attestation with SHA-2, but the easiest way
> > > to maintain security is to always extend all banks.
> > >
> >
> > Wouldn't it make more sense to measure some terminating event into the
> > SHA-1 banks instead?
>
> Unless we assert that SHA-1 events are unsupported, it seems a bit odd
> to force a policy on people who have both banks enabled. People with
> mixed fleets are potentially going to be dealing with SHA-1 measurements
> for a while yet, and while there's obviously a security benefit in using
> SHA-2 instead it'd be irritating to have to maintain two attestation
> policies.

I understand why that matters from an operational perspective.

However, we are dealing with brand new code being proposed for Linux
mainline, and so this is our only chance to push back on this, as
otherwise, we will have to maintain it for a very long time.

IOW, D-RTM does not exist today in Linux, and it is up to us to define
what it will look like. From that perspective, it is downright
preposterous to even consider supporting SHA-1, given that SHA-1 by
itself gives none of the guarantees that D-RTM aims to provide. If
reducing your TCB is important enough to warrant switching to this
implementation of D-RTM, surely you can upgrade your attestation
policies as well.

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-12 11:58             ` Ard Biesheuvel
  0 siblings, 0 replies; 200+ messages in thread
From: Ard Biesheuvel @ 2023-05-12 11:58 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Eric Biggers, Ross Philipson, linux-kernel, x86, linux-integrity,
	linux-doc, linux-crypto, iommu, kexec, linux-efi, dpsmith, tglx,
	mingo, bp, hpa, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, 12 May 2023 at 13:28, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>
> On Fri, May 12, 2023 at 01:18:45PM +0200, Ard Biesheuvel wrote:
> > On Fri, 12 May 2023 at 13:04, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> > >
> > > On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:
> > >
> > > > SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> > > > now?
> > >
> > > TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also
> > > at the whim of the firmware in terms of whether the SHA-2 banks are
> > > enabled. But even if the SHA-2 banks are enabled, if you suddenly stop
> > > extending the SHA-1 banks, a malicious actor can later turn up and
> > > extend whatever they want into them and present a SHA-1-only
> > > attestation. Ideally whatever is handling that attestation should know
> > > whether or not to expect an attestation with SHA-2, but the easiest way
> > > to maintain security is to always extend all banks.
> > >
> >
> > Wouldn't it make more sense to measure some terminating event into the
> > SHA-1 banks instead?
>
> Unless we assert that SHA-1 events are unsupported, it seems a bit odd
> to force a policy on people who have both banks enabled. People with
> mixed fleets are potentially going to be dealing with SHA-1 measurements
> for a while yet, and while there's obviously a security benefit in using
> SHA-2 instead it'd be irritating to have to maintain two attestation
> policies.

I understand why that matters from an operational perspective.

However, we are dealing with brand new code being proposed for Linux
mainline, and so this is our only chance to push back on this, as
otherwise, we will have to maintain it for a very long time.

IOW, D-RTM does not exist today in Linux, and it is up to us to define
what it will look like. From that perspective, it is downright
preposterous to even consider supporting SHA-1, given that SHA-1 by
itself gives none of the guarantees that D-RTM aims to provide. If
reducing your TCB is important enough to warrant switching to this
implementation of D-RTM, surely you can upgrade your attestation
policies as well.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-12 11:58             ` Ard Biesheuvel
@ 2023-05-12 12:24               ` Andrew Cooper
  -1 siblings, 0 replies; 200+ messages in thread
From: Andrew Cooper @ 2023-05-12 12:24 UTC (permalink / raw)
  To: Ard Biesheuvel, Matthew Garrett
  Cc: Eric Biggers, Ross Philipson, linux-kernel, x86, linux-integrity,
	linux-doc, linux-crypto, iommu, kexec, linux-efi, dpsmith, tglx,
	mingo, bp, hpa, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 12/05/2023 12:58 pm, Ard Biesheuvel wrote:
> On Fri, 12 May 2023 at 13:28, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>> On Fri, May 12, 2023 at 01:18:45PM +0200, Ard Biesheuvel wrote:
>>> On Fri, 12 May 2023 at 13:04, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>>>> On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:
>>>>
>>>>> SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
>>>>> now?
>>>> TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also
>>>> at the whim of the firmware in terms of whether the SHA-2 banks are
>>>> enabled. But even if the SHA-2 banks are enabled, if you suddenly stop
>>>> extending the SHA-1 banks, a malicious actor can later turn up and
>>>> extend whatever they want into them and present a SHA-1-only
>>>> attestation. Ideally whatever is handling that attestation should know
>>>> whether or not to expect an attestation with SHA-2, but the easiest way
>>>> to maintain security is to always extend all banks.
>>>>
>>> Wouldn't it make more sense to measure some terminating event into the
>>> SHA-1 banks instead?
>> Unless we assert that SHA-1 events are unsupported, it seems a bit odd
>> to force a policy on people who have both banks enabled. People with
>> mixed fleets are potentially going to be dealing with SHA-1 measurements
>> for a while yet, and while there's obviously a security benefit in using
>> SHA-2 instead it'd be irritating to have to maintain two attestation
>> policies.
> I understand why that matters from an operational perspective.
>
> However, we are dealing with brand new code being proposed for Linux
> mainline, and so this is our only chance to push back on this, as
> otherwise, we will have to maintain it for a very long time.
>
> IOW, D-RTM does not exist today in Linux, and it is up to us to define
> what it will look like. From that perspective, it is downright
> preposterous to even consider supporting SHA-1, given that SHA-1 by
> itself gives none of the guarantees that D-RTM aims to provide. If
> reducing your TCB is important enough to warrant switching to this
> implementation of D-RTM, surely you can upgrade your attestation
> policies as well.

You're suggesting that because Linux has been slow to take D-RTM over
the past decade, you're going to intentionally break people with older
hardware just because you don't feel like using an older algorithm?

That's about the worst possible reason to not take support.

There really are people in the world with older TPM 1.2 systems where
this D-RTM using SHA1 only is an improvement over using the incumbent tboot.

~Andrew

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-12 12:24               ` Andrew Cooper
  0 siblings, 0 replies; 200+ messages in thread
From: Andrew Cooper @ 2023-05-12 12:24 UTC (permalink / raw)
  To: Ard Biesheuvel, Matthew Garrett
  Cc: Eric Biggers, Ross Philipson, linux-kernel, x86, linux-integrity,
	linux-doc, linux-crypto, iommu, kexec, linux-efi, dpsmith, tglx,
	mingo, bp, hpa, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 12/05/2023 12:58 pm, Ard Biesheuvel wrote:
> On Fri, 12 May 2023 at 13:28, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>> On Fri, May 12, 2023 at 01:18:45PM +0200, Ard Biesheuvel wrote:
>>> On Fri, 12 May 2023 at 13:04, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>>>> On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:
>>>>
>>>>> SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
>>>>> now?
>>>> TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also
>>>> at the whim of the firmware in terms of whether the SHA-2 banks are
>>>> enabled. But even if the SHA-2 banks are enabled, if you suddenly stop
>>>> extending the SHA-1 banks, a malicious actor can later turn up and
>>>> extend whatever they want into them and present a SHA-1-only
>>>> attestation. Ideally whatever is handling that attestation should know
>>>> whether or not to expect an attestation with SHA-2, but the easiest way
>>>> to maintain security is to always extend all banks.
>>>>
>>> Wouldn't it make more sense to measure some terminating event into the
>>> SHA-1 banks instead?
>> Unless we assert that SHA-1 events are unsupported, it seems a bit odd
>> to force a policy on people who have both banks enabled. People with
>> mixed fleets are potentially going to be dealing with SHA-1 measurements
>> for a while yet, and while there's obviously a security benefit in using
>> SHA-2 instead it'd be irritating to have to maintain two attestation
>> policies.
> I understand why that matters from an operational perspective.
>
> However, we are dealing with brand new code being proposed for Linux
> mainline, and so this is our only chance to push back on this, as
> otherwise, we will have to maintain it for a very long time.
>
> IOW, D-RTM does not exist today in Linux, and it is up to us to define
> what it will look like. From that perspective, it is downright
> preposterous to even consider supporting SHA-1, given that SHA-1 by
> itself gives none of the guarantees that D-RTM aims to provide. If
> reducing your TCB is important enough to warrant switching to this
> implementation of D-RTM, surely you can upgrade your attestation
> policies as well.

You're suggesting that because Linux has been slow to take D-RTM over
the past decade, you're going to intentionally break people with older
hardware just because you don't feel like using an older algorithm?

That's about the worst possible reason to not take support.

There really are people in the world with older TPM 1.2 systems where
this D-RTM using SHA1 only is an improvement over using the incumbent tboot.

~Andrew

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-12 13:19     ` Thomas Gleixner
  -1 siblings, 0 replies; 200+ messages in thread
From: Thomas Gleixner @ 2023-05-12 13:19 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
> +KASLR Configuration
> +-------------------
> +
> +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
> +built with KASLR disabled::

Why?

> +  "Processor type and features" -->
> +      "Build a relocatable kernel" -->
> +          "Randomize the address of the kernel image (KASLR) [ ]"
> +
> +This unsets the Kconfig value CONFIG_RANDOMIZE_BASE.
> +
> +If not possible, KASLR must be disabled on the kernel command line when doing
> +a Secure Launch as follows::
> +
> +  nokaslr

So what happens if KASLR is enabled in Kconfig and not disabled on the
command line?

> +IOMMU Configuration
> +-------------------
> +
> +When doing a Secure Launch, the IOMMU should always be enabled and the drivers
> +loaded. However, IOMMU passthrough mode should never be used. This leaves the
> +MLE completely exposed to DMA after the PMR's [2]_ are disabled. The current default
> +mode is to use IOMMU in lazy translated mode but strict translated mode is the preferred
> +IOMMU mode and this should be selected in the build configuration::
> +
> +  "Device Drivers" -->
> +      "IOMMU Hardware Support" -->
> +          "IOMMU default domain type" -->
> +              "(X) Translated - Strict"
> +
> +In addition, the Intel IOMMU should be on by default. The following sets this as the
> +default in the build configuration::
> +
> +  "Device Drivers" -->
> +      "IOMMU Hardware Support" -->
> +          "Support for Intel IOMMU using DMA Remapping Devices [*]"
> +
> +and::
> +
> +  "Device Drivers" -->
> +      "IOMMU Hardware Support" -->
> +          "Support for Intel IOMMU using DMA Remapping Devices [*]" -->
> +              "Enable Intel DMA Remapping Devices by default  [*]"
> +
> +It is recommended that no other command line options should be set to override
> +the defaults above.

Is any of this validated and are proper warnings emitted or is it just
recommended and left to the user to do the right thing?

Thanks,

        tglx

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
@ 2023-05-12 13:19     ` Thomas Gleixner
  0 siblings, 0 replies; 200+ messages in thread
From: Thomas Gleixner @ 2023-05-12 13:19 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
> +KASLR Configuration
> +-------------------
> +
> +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
> +built with KASLR disabled::

Why?

> +  "Processor type and features" -->
> +      "Build a relocatable kernel" -->
> +          "Randomize the address of the kernel image (KASLR) [ ]"
> +
> +This unsets the Kconfig value CONFIG_RANDOMIZE_BASE.
> +
> +If not possible, KASLR must be disabled on the kernel command line when doing
> +a Secure Launch as follows::
> +
> +  nokaslr

So what happens if KASLR is enabled in Kconfig and not disabled on the
command line?

> +IOMMU Configuration
> +-------------------
> +
> +When doing a Secure Launch, the IOMMU should always be enabled and the drivers
> +loaded. However, IOMMU passthrough mode should never be used. This leaves the
> +MLE completely exposed to DMA after the PMR's [2]_ are disabled. The current default
> +mode is to use IOMMU in lazy translated mode but strict translated mode is the preferred
> +IOMMU mode and this should be selected in the build configuration::
> +
> +  "Device Drivers" -->
> +      "IOMMU Hardware Support" -->
> +          "IOMMU default domain type" -->
> +              "(X) Translated - Strict"
> +
> +In addition, the Intel IOMMU should be on by default. The following sets this as the
> +default in the build configuration::
> +
> +  "Device Drivers" -->
> +      "IOMMU Hardware Support" -->
> +          "Support for Intel IOMMU using DMA Remapping Devices [*]"
> +
> +and::
> +
> +  "Device Drivers" -->
> +      "IOMMU Hardware Support" -->
> +          "Support for Intel IOMMU using DMA Remapping Devices [*]" -->
> +              "Enable Intel DMA Remapping Devices by default  [*]"
> +
> +It is recommended that no other command line options should be set to override
> +the defaults above.

Is any of this validated and are proper warnings emitted or is it just
recommended and left to the user to do the right thing?

Thanks,

        tglx

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-12 11:28           ` Matthew Garrett
@ 2023-05-12 13:24             ` Thomas Gleixner
  -1 siblings, 0 replies; 200+ messages in thread
From: Thomas Gleixner @ 2023-05-12 13:24 UTC (permalink / raw)
  To: Matthew Garrett, Ard Biesheuvel
  Cc: Eric Biggers, Ross Philipson, linux-kernel, x86, linux-integrity,
	linux-doc, linux-crypto, iommu, kexec, linux-efi, dpsmith, mingo,
	bp, hpa, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, May 12 2023 at 12:28, Matthew Garrett wrote:
> On Fri, May 12, 2023 at 01:18:45PM +0200, Ard Biesheuvel wrote:
>> On Fri, 12 May 2023 at 13:04, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>> >
>> > On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:
>> >
>> > > SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
>> > > now?
>> >
>> > TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also
>> > at the whim of the firmware in terms of whether the SHA-2 banks are
>> > enabled. But even if the SHA-2 banks are enabled, if you suddenly stop
>> > extending the SHA-1 banks, a malicious actor can later turn up and
>> > extend whatever they want into them and present a SHA-1-only
>> > attestation. Ideally whatever is handling that attestation should know
>> > whether or not to expect an attestation with SHA-2, but the easiest way
>> > to maintain security is to always extend all banks.
>> >
>> 
>> Wouldn't it make more sense to measure some terminating event into the
>> SHA-1 banks instead?
>
> Unless we assert that SHA-1 events are unsupported, it seems a bit odd 
> to force a policy on people who have both banks enabled. People with 
> mixed fleets are potentially going to be dealing with SHA-1 measurements 
> for a while yet, and while there's obviously a security benefit in using 
> SHA-2 instead it'd be irritating to have to maintain two attestation 
> policies.

Why?

If you have a mixed fleet then it's not too much asked to provide two
data sets. On a TPM2 system you can enforce SHA-2 and only fallback to
SHA-1 on TPM 1.2 hardware. No?

Thanks,

        tglx

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-12 13:24             ` Thomas Gleixner
  0 siblings, 0 replies; 200+ messages in thread
From: Thomas Gleixner @ 2023-05-12 13:24 UTC (permalink / raw)
  To: Matthew Garrett, Ard Biesheuvel
  Cc: Eric Biggers, Ross Philipson, linux-kernel, x86, linux-integrity,
	linux-doc, linux-crypto, iommu, kexec, linux-efi, dpsmith, mingo,
	bp, hpa, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, May 12 2023 at 12:28, Matthew Garrett wrote:
> On Fri, May 12, 2023 at 01:18:45PM +0200, Ard Biesheuvel wrote:
>> On Fri, 12 May 2023 at 13:04, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>> >
>> > On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:
>> >
>> > > SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
>> > > now?
>> >
>> > TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also
>> > at the whim of the firmware in terms of whether the SHA-2 banks are
>> > enabled. But even if the SHA-2 banks are enabled, if you suddenly stop
>> > extending the SHA-1 banks, a malicious actor can later turn up and
>> > extend whatever they want into them and present a SHA-1-only
>> > attestation. Ideally whatever is handling that attestation should know
>> > whether or not to expect an attestation with SHA-2, but the easiest way
>> > to maintain security is to always extend all banks.
>> >
>> 
>> Wouldn't it make more sense to measure some terminating event into the
>> SHA-1 banks instead?
>
> Unless we assert that SHA-1 events are unsupported, it seems a bit odd 
> to force a policy on people who have both banks enabled. People with 
> mixed fleets are potentially going to be dealing with SHA-1 measurements 
> for a while yet, and while there's obviously a security benefit in using 
> SHA-2 instead it'd be irritating to have to maintain two attestation 
> policies.

Why?

If you have a mixed fleet then it's not too much asked to provide two
data sets. On a TPM2 system you can enforce SHA-2 and only fallback to
SHA-1 on TPM 1.2 hardware. No?

Thanks,

        tglx

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-12 15:44     ` Thomas Gleixner
  -1 siblings, 0 replies; 200+ messages in thread
From: Thomas Gleixner @ 2023-05-12 15:44 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
> The routine slaunch_setup is called out of the x86 specific setup_arch

Can you please make functions visible in changelogs by appending (),
i.e. setup_arch() ?

See https://www.kernel.org/doc/html/latest/process/maintainer-tip.html
for further hints.

> +static u32 sl_flags;
> +static struct sl_ap_wake_info ap_wake_info;
> +static u64 evtlog_addr;
> +static u32 evtlog_size;
> +static u64 vtd_pmr_lo_size;

Is any of this modifyable after boot? If not then this wants to be
annotated with __ro_after_init.

> +/* This should be plenty of room */
> +static u8 txt_dmar[PAGE_SIZE] __aligned(16);
> +
> +u32 slaunch_get_flags(void)
> +{
> +	return sl_flags;
> +}
> +EXPORT_SYMBOL(slaunch_get_flags);

What needs this export? If there is a reason then please EXPORT_SYMBOL_GPL()

> +struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
> +{
> +	return &ap_wake_info;
> +}

If you return a pointer, then there is not much of point for encapsulating.

> +struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)

Some explanation on public visible functions would be really useful.

> +{
> +	/* The DMAR is only stashed and provided via TXT on Intel systems */

-ENOPARSE.

> +	if (memcmp(txt_dmar, "DMAR", 4))
> +		return dmar;
> +
> +	return (struct acpi_table_header *)(&txt_dmar[0]);

s/&txt_dmar[0]/txt_dmar/ No?

> +}

> +void __noreturn slaunch_txt_reset(void __iomem *txt,
> +				  const char *msg, u64 error)

Please avoid these line breaks. We lifted the 80 character limit quite
some time ago.

> +
> +	/* Iterate over heap tables looking for table of "type" */
> +	for (i = 0; i < type; i++) {
> +		base += offset;
> +		heap = early_memremap(base, sizeof(u64));
> +		if (!heap)
> +			slaunch_txt_reset(txt,
> +				"Error early_memremap of heap for heap walk\n",
> +				SL_ERROR_HEAP_MAP);

This is horrible to read.

		if (!heap) {
			slaunch_txt_reset(txt, "Error early_memremap of heap for heap walk\n",
                        		  SL_ERROR_HEAP_MAP);
                }

See documentation about bracket rules.

> +
> +/*
> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
> + * It is stored in the TXT heap. Fetch it from there and make it available
> + * to the IOMMU driver.
> + */
> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
> +{
> +	struct txt_sinit_mle_data *sinit_mle_data;
> +	u32 field_offset, dmar_size, dmar_offset;
> +	void *dmar;
> +
> +	memset(&txt_dmar, 0, PAGE_SIZE);

txt_dmar is statically allocated so it's already zero, no?

> +/*
> + * Intel TXT specific late stub setup and validation.
> + */
> +void __init slaunch_setup_txt(void)
> +{
> +	u64 one = TXT_REGVALUE_ONE, val;
> +	void __iomem *txt;
> +
> +	if (!boot_cpu_has(X86_FEATURE_SMX))
> +		return;
> +
> +	/*
> +	 * If booted through secure launch entry point, the loadflags
> +	 * option will be set.
> +	 */
> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
> +		return;
> +
> +	/*
> +	 * See if SENTER was done by reading the status register in the
> +	 * public space. If the public register space cannot be read, TXT may
> +	 * be disabled.
> +	 */
> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +	if (!txt)
> +		return;

Wait. You have established above that SMX is available and the boot has
set the SLAUNCH flag.

So if that ioremap() fails then there is an issue with the fixmaps.

How is returning here sensible? The system will just die later on in the
worst case with some undecodable issue.

Thanks,

        tglx

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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
@ 2023-05-12 15:44     ` Thomas Gleixner
  0 siblings, 0 replies; 200+ messages in thread
From: Thomas Gleixner @ 2023-05-12 15:44 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
> The routine slaunch_setup is called out of the x86 specific setup_arch

Can you please make functions visible in changelogs by appending (),
i.e. setup_arch() ?

See https://www.kernel.org/doc/html/latest/process/maintainer-tip.html
for further hints.

> +static u32 sl_flags;
> +static struct sl_ap_wake_info ap_wake_info;
> +static u64 evtlog_addr;
> +static u32 evtlog_size;
> +static u64 vtd_pmr_lo_size;

Is any of this modifyable after boot? If not then this wants to be
annotated with __ro_after_init.

> +/* This should be plenty of room */
> +static u8 txt_dmar[PAGE_SIZE] __aligned(16);
> +
> +u32 slaunch_get_flags(void)
> +{
> +	return sl_flags;
> +}
> +EXPORT_SYMBOL(slaunch_get_flags);

What needs this export? If there is a reason then please EXPORT_SYMBOL_GPL()

> +struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
> +{
> +	return &ap_wake_info;
> +}

If you return a pointer, then there is not much of point for encapsulating.

> +struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)

Some explanation on public visible functions would be really useful.

> +{
> +	/* The DMAR is only stashed and provided via TXT on Intel systems */

-ENOPARSE.

> +	if (memcmp(txt_dmar, "DMAR", 4))
> +		return dmar;
> +
> +	return (struct acpi_table_header *)(&txt_dmar[0]);

s/&txt_dmar[0]/txt_dmar/ No?

> +}

> +void __noreturn slaunch_txt_reset(void __iomem *txt,
> +				  const char *msg, u64 error)

Please avoid these line breaks. We lifted the 80 character limit quite
some time ago.

> +
> +	/* Iterate over heap tables looking for table of "type" */
> +	for (i = 0; i < type; i++) {
> +		base += offset;
> +		heap = early_memremap(base, sizeof(u64));
> +		if (!heap)
> +			slaunch_txt_reset(txt,
> +				"Error early_memremap of heap for heap walk\n",
> +				SL_ERROR_HEAP_MAP);

This is horrible to read.

		if (!heap) {
			slaunch_txt_reset(txt, "Error early_memremap of heap for heap walk\n",
                        		  SL_ERROR_HEAP_MAP);
                }

See documentation about bracket rules.

> +
> +/*
> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
> + * It is stored in the TXT heap. Fetch it from there and make it available
> + * to the IOMMU driver.
> + */
> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
> +{
> +	struct txt_sinit_mle_data *sinit_mle_data;
> +	u32 field_offset, dmar_size, dmar_offset;
> +	void *dmar;
> +
> +	memset(&txt_dmar, 0, PAGE_SIZE);

txt_dmar is statically allocated so it's already zero, no?

> +/*
> + * Intel TXT specific late stub setup and validation.
> + */
> +void __init slaunch_setup_txt(void)
> +{
> +	u64 one = TXT_REGVALUE_ONE, val;
> +	void __iomem *txt;
> +
> +	if (!boot_cpu_has(X86_FEATURE_SMX))
> +		return;
> +
> +	/*
> +	 * If booted through secure launch entry point, the loadflags
> +	 * option will be set.
> +	 */
> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
> +		return;
> +
> +	/*
> +	 * See if SENTER was done by reading the status register in the
> +	 * public space. If the public register space cannot be read, TXT may
> +	 * be disabled.
> +	 */
> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> +	if (!txt)
> +		return;

Wait. You have established above that SMX is available and the boot has
set the SLAUNCH flag.

So if that ioremap() fails then there is an issue with the fixmaps.

How is returning here sensible? The system will just die later on in the
worst case with some undecodable issue.

Thanks,

        tglx

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 12/14] x86: Secure Launch late initcall platform module
  2023-05-10 22:39     ` Jarkko Sakkinen
@ 2023-05-12 15:53       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-12 15:53 UTC (permalink / raw)
  To: Jarkko Sakkinen, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel, Ross Philipson

On 5/10/23 18:39, Jarkko Sakkinen wrote:
> On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
>> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>>
>> The Secure Launch platform module is a late init module. During the
>> init call, the TPM event log is read and measurements taken in the
>> early boot stub code are located. These measurements are extended
>> into the TPM PCRs using the mainline TPM kernel driver.
>>
>> The platform module also registers the securityfs nodes to allow
>> access to TXT register fields on Intel along with the fetching of
>> and writing events to the late launch TPM log.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
>> Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   arch/x86/kernel/Makefile   |   1 +
>>   arch/x86/kernel/slmodule.c | 520 +++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 521 insertions(+)
>>   create mode 100644 arch/x86/kernel/slmodule.c
>>
>> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
>> index 3d2a33e..ee3fe300 100644
>> --- a/arch/x86/kernel/Makefile
>> +++ b/arch/x86/kernel/Makefile
>> @@ -73,6 +73,7 @@ obj-$(CONFIG_IA32_EMULATION)	+= tls.o
>>   obj-y				+= step.o
>>   obj-$(CONFIG_INTEL_TXT)		+= tboot.o
>>   obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
>> +obj-$(CONFIG_SECURE_LAUNCH)	+= slmodule.o
>>   obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
>>   obj-y				+= stacktrace.o
>>   obj-y				+= cpu/
>> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
>> new file mode 100644
>> index 0000000..70dcff5
>> --- /dev/null
>> +++ b/arch/x86/kernel/slmodule.c
>> @@ -0,0 +1,520 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Secure Launch late validation/setup, securityfs exposure and
>> + * finalization support.
>> + *
>> + * Copyright (c) 2022 Apertus Solutions, LLC
>> + * Copyright (c) 2021 Assured Information Security, Inc.
>> + * Copyright (c) 2022, Oracle and/or its affiliates.
>> + *
>> + * Author(s):
>> + *     Daniel P. Smith <dpsmith@apertussolutions.com>
>> + *     Garnet T. Grimm <grimmg@ainfosec.com>
> 
> I'm not sure what the authors list is good for in the days of Git,
> and all the tags we have for commit messages.
> 
> Instead of this you could just put to the commit:
> 
> Co-developed-by: Garnet T. Grimm <grimmg@ainfosec.com>
> Signed-off-by: Garnet T. Grimm <grimmg@ainfosec.com>
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> 
> See:
> 
> https://www.kernel.org/doc/html/latest/process/submitting-patches.html#when-to-use-acked-by-cc-and-co-developed-by

Yes we will fix all that. And everything else you pointed out in this 
review.

Thanks

> 
>> + */
>> +
>> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>> +
>> +#include <linux/fs.h>
>> +#include <linux/init.h>
>> +#include <linux/linkage.h>
>> +#include <linux/mm.h>
>> +#include <linux/io.h>
>> +#include <linux/uaccess.h>
>> +#include <linux/security.h>
>> +#include <linux/memblock.h>
>> +#include <asm/segment.h>
>> +#include <asm/sections.h>
>> +#include <crypto/sha2.h>
>> +#include <linux/slr_table.h>
>> +#include <linux/slaunch.h>
>> +
>> +#define DECLARE_TXT_PUB_READ_U(size, fmt, msg_size)			\
>> +static ssize_t txt_pub_read_u##size(unsigned int offset,		\
>> +		loff_t *read_offset,					\
>> +		size_t read_len,					\
>> +		char __user *buf)					\
> 
> This would really deserve:
> 
> /*
>   * Explain what DECLARE_TXT_PUB_READ_U is.
>   */
> 
>> +{									\
>> +	void __iomem *txt;						\
>> +	char msg_buffer[msg_size];					\
> 
> Reverse-christmas tree order.
> 
>> +	u##size reg_value = 0;						\
>> +	txt = ioremap(TXT_PUB_CONFIG_REGS_BASE,				\
>> +			TXT_NR_CONFIG_PAGES * PAGE_SIZE);		\
>> +	if (!txt)						\
>> +		return -EFAULT;					\
>> +	memcpy_fromio(&reg_value, txt + offset, sizeof(u##size));	\
>> +	iounmap(txt);							\
>> +	snprintf(msg_buffer, msg_size, fmt, reg_value);			\
>> +	return simple_read_from_buffer(buf, read_len, read_offset,	\
>> +			&msg_buffer, msg_size);				\
>> +}
>> +
>> +DECLARE_TXT_PUB_READ_U(8, "%#04x\n", 6);
>> +DECLARE_TXT_PUB_READ_U(32, "%#010x\n", 12);
>> +DECLARE_TXT_PUB_READ_U(64, "%#018llx\n", 20);
>> +
>> +#define DECLARE_TXT_FOPS(reg_name, reg_offset, reg_size)		\
>> +static ssize_t txt_##reg_name##_read(struct file *flip,			\
>> +		char __user *buf, size_t read_len, loff_t *read_offset)	\
>> +{									\
>> +	return txt_pub_read_u##reg_size(reg_offset, read_offset,	\
>> +			read_len, buf);					\
>> +}									\
>> +static const struct file_operations reg_name##_ops = {			\
>> +	.read = txt_##reg_name##_read,					\
>> +}
>> +
>> +DECLARE_TXT_FOPS(sts, TXT_CR_STS, 64);
>> +DECLARE_TXT_FOPS(ests, TXT_CR_ESTS, 8);
>> +DECLARE_TXT_FOPS(errorcode, TXT_CR_ERRORCODE, 32);
>> +DECLARE_TXT_FOPS(didvid, TXT_CR_DIDVID, 64);
>> +DECLARE_TXT_FOPS(e2sts, TXT_CR_E2STS, 64);
>> +DECLARE_TXT_FOPS(ver_emif, TXT_CR_VER_EMIF, 32);
>> +DECLARE_TXT_FOPS(scratchpad, TXT_CR_SCRATCHPAD, 64);
>> +
>> +/*
>> + * Securityfs exposure
>> + */
>> +struct memfile {
>> +	char *name;
>> +	void *addr;
>> +	size_t size;
>> +};
>> +
>> +static struct memfile sl_evtlog = {"eventlog", 0, 0};
>> +static void *txt_heap;
>> +static struct txt_heap_event_log_pointer2_1_element __iomem *evtlog20;
>> +static DEFINE_MUTEX(sl_evt_log_mutex);
>> +
>> +static ssize_t sl_evtlog_read(struct file *file, char __user *buf,
>> +			      size_t count, loff_t *pos)
>> +{
>> +	ssize_t size;
>> +
>> +	if (!sl_evtlog.addr)
>> +		return 0;
>> +
>> +	mutex_lock(&sl_evt_log_mutex);
>> +	size = simple_read_from_buffer(buf, count, pos, sl_evtlog.addr,
>> +				       sl_evtlog.size);
>> +	mutex_unlock(&sl_evt_log_mutex);
>> +
>> +	return size;
>> +}
>> +
>> +static ssize_t sl_evtlog_write(struct file *file, const char __user *buf,
>> +				size_t datalen, loff_t *ppos)
>> +{
>> +	ssize_t result;
>> +	char *data;
>> +
>> +	if (!sl_evtlog.addr)
>> +		return 0;
>> +
>> +	/* No partial writes. */
>> +	result = -EINVAL;
>> +	if (*ppos != 0)
>> +		goto out;
>> +
>> +	data = memdup_user(buf, datalen);
>> +	if (IS_ERR(data)) {
>> +		result = PTR_ERR(data);
>> +		goto out;
>> +	}
>> +
>> +	mutex_lock(&sl_evt_log_mutex);
>> +	if (evtlog20)
>> +		result = tpm20_log_event(evtlog20, sl_evtlog.addr,
>> +					 sl_evtlog.size, datalen, data);
>> +	else
>> +		result = tpm12_log_event(sl_evtlog.addr, sl_evtlog.size,
>> +					 datalen, data);
>> +	mutex_unlock(&sl_evt_log_mutex);
>> +
>> +	kfree(data);
>> +out:
>> +	return result;
>> +}
>> +
>> +static const struct file_operations sl_evtlog_ops = {
>> +	.read = sl_evtlog_read,
>> +	.write = sl_evtlog_write,
>> +	.llseek	= default_llseek,
>> +};
>> +
>> +struct sfs_file {
>> +	const char *name;
>> +	const struct file_operations *fops;
>> +};
>> +
>> +#define SL_TXT_ENTRY_COUNT	7
>> +static const struct sfs_file sl_txt_files[] = {
>> +	{ "sts", &sts_ops },
>> +	{ "ests", &ests_ops },
>> +	{ "errorcode", &errorcode_ops },
>> +	{ "didvid", &didvid_ops },
>> +	{ "ver_emif", &ver_emif_ops },
>> +	{ "scratchpad", &scratchpad_ops },
>> +	{ "e2sts", &e2sts_ops }
>> +};
>> +
>> +/* sysfs file handles */
>> +static struct dentry *slaunch_dir;
>> +static struct dentry *event_file;
>> +static struct dentry *txt_dir;
>> +static struct dentry *txt_entries[SL_TXT_ENTRY_COUNT];
>> +
>> +static long slaunch_expose_securityfs(void)
>> +{
>> +	long ret = 0;
>> +	int i;
>> +
>> +	slaunch_dir = securityfs_create_dir("slaunch", NULL);
>> +	if (IS_ERR(slaunch_dir))
>> +		return PTR_ERR(slaunch_dir);
>> +
>> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
>> +		txt_dir = securityfs_create_dir("txt", slaunch_dir);
>> +		if (IS_ERR(txt_dir)) {
>> +			ret = PTR_ERR(txt_dir);
>> +			goto remove_slaunch;
>> +		}
>> +
>> +		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++) {
>> +			txt_entries[i] = securityfs_create_file(
>> +						sl_txt_files[i].name, 0440,
>> +						txt_dir, NULL,
>> +						sl_txt_files[i].fops);
>> +			if (IS_ERR(txt_entries[i])) {
>> +				ret = PTR_ERR(txt_entries[i]);
>> +				goto remove_files;
>> +			}
>> +		}
>> +
>> +	}
>> +
>> +	if (sl_evtlog.addr > 0) {
>> +		event_file = securityfs_create_file(
>> +					sl_evtlog.name, 0440,
>> +					slaunch_dir, NULL,
>> +					&sl_evtlog_ops);
>> +		if (IS_ERR(event_file)) {
>> +			ret = PTR_ERR(event_file);
>> +			goto remove_files;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +
>> +remove_files:
>> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
>> +		while (--i >= 0)
>> +			securityfs_remove(txt_entries[i]);
>> +		securityfs_remove(txt_dir);
>> +	}
>> +remove_slaunch:
>> +	securityfs_remove(slaunch_dir);
>> +
>> +	return ret;
>> +}
>> +
>> +static void slaunch_teardown_securityfs(void)
>> +{
>> +	int i;
>> +
>> +	securityfs_remove(event_file);
>> +	if (sl_evtlog.addr) {
>> +		memunmap(sl_evtlog.addr);
>> +		sl_evtlog.addr = NULL;
>> +	}
>> +	sl_evtlog.size = 0;
>> +
>> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
>> +		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++)
>> +			securityfs_remove(txt_entries[i]);
>> +
>> +		securityfs_remove(txt_dir);
>> +
>> +		if (txt_heap) {
>> +			memunmap(txt_heap);
>> +			txt_heap = NULL;
>> +		}
>> +	}
>> +
>> +	securityfs_remove(slaunch_dir);
>> +}
>> +
>> +static void slaunch_intel_evtlog(void __iomem *txt)
>> +{
>> +	struct slr_entry_log_info *log_info;
>> +	struct txt_os_mle_data *params;
>> +	struct slr_table *slrt;
>> +	void *os_sinit_data;
>> +	u64 base, size;
>> +
>> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
>> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
>> +
>> +	/* now map TXT heap */
>> +	txt_heap = memremap(base, size, MEMREMAP_WB);
>> +	if (!txt_heap)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap TXT heap\n",
>> +			SL_ERROR_HEAP_MAP);
>> +
>> +	params = (struct txt_os_mle_data *)txt_os_mle_data_start(txt_heap);
>> +
>> +	/* Get the SLRT and remap it */
>> +	slrt = memremap(params->slrt, sizeof(*slrt), MEMREMAP_WB);
>> +	if (!slrt)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap SLR Table\n",
>> +			SL_ERROR_SLRT_MAP);
>> +	size = slrt->size;
>> +	memunmap(slrt);
>> +
>> +	slrt = memremap(params->slrt, size, MEMREMAP_WB);
>> +	if (!slrt)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap SLR Table\n",
>> +			SL_ERROR_SLRT_MAP);
>> +
>> +	log_info = (struct slr_entry_log_info *)
>> +			slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
>> +	if (!log_info)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap SLR Table\n",
>> +			SL_ERROR_SLRT_MISSING_ENTRY);
>> +
>> +	sl_evtlog.size = log_info->size;
>> +	sl_evtlog.addr = memremap(log_info->addr, log_info->size,
>> +				  MEMREMAP_WB);
>> +	if (!sl_evtlog.addr)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap TPM event log\n",
>> +			SL_ERROR_EVENTLOG_MAP);
>> +
>> +	memunmap(slrt);
>> +
>> +	/* Determine if this is TPM 1.2 or 2.0 event log */
>> +	if (memcmp(sl_evtlog.addr + sizeof(struct tcg_pcr_event),
>> +		    TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
>> +		return; /* looks like it is not 2.0 */
>> +
>> +	/* For TPM 2.0 logs, the extended heap element must be located */
>> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
>> +
>> +	evtlog20 = tpm20_find_log2_1_element(os_sinit_data);
>> +
>> +	/*
>> +	 * If this fails, things are in really bad shape. Any attempt to write
>> +	 * events to the log will fail.
>> +	 */
>> +	if (!evtlog20)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to find TPM20 event log element\n",
>> +			SL_ERROR_TPM_INVALID_LOG20);
>> +}
>> +
>> +static void slaunch_tpm20_extend_event(struct tpm_chip *tpm, void __iomem *txt,
>> +				       struct tcg_pcr_event2_head *event)
>> +{
>> +	u16 *alg_id_field = (u16 *)((u8 *)event +
>> +				    sizeof(struct tcg_pcr_event2_head));
>> +	struct tpm_digest *digests;
>> +	u8 *dptr;
>> +	int ret;
>> +	u32 i, j;
>> +
>> +	digests = kcalloc(tpm->nr_allocated_banks, sizeof(*digests),
>> +			  GFP_KERNEL);
>> +	if (!digests)
>> +		slaunch_txt_reset(txt,
>> +			"Failed to allocate array of digests\n",
>> +			SL_ERROR_GENERIC);
>> +
>> +	for (i = 0; i < tpm->nr_allocated_banks; i++)
>> +		digests[i].alg_id = tpm->allocated_banks[i].alg_id;
>> +
>> +
>> +	/* Early SL code ensured there was a max count of 2 digests */
>> +	for (i = 0; i < event->count; i++) {
>> +		dptr = (u8 *)alg_id_field + sizeof(u16);
>> +
>> +		for (j = 0; j < tpm->nr_allocated_banks; j++) {
>> +			if (digests[j].alg_id != *alg_id_field)
>> +				continue;
>> +
>> +			switch (digests[j].alg_id) {
>> +			case TPM_ALG_SHA256:
>> +				memcpy(&digests[j].digest[0], dptr,
>> +				       SHA256_DIGEST_SIZE);
>> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
>> +					SHA256_DIGEST_SIZE + sizeof(u16));
>> +				break;
>> +			case TPM_ALG_SHA1:
>> +				memcpy(&digests[j].digest[0], dptr,
>> +				       SHA1_DIGEST_SIZE);
>> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
>> +					SHA1_DIGEST_SIZE + sizeof(u16));
>> +			default:
>> +				break;
>> +			}
>> +		}
>> +	}
>> +
>> +	ret = tpm_pcr_extend(tpm, event->pcr_idx, digests);
>> +	if (ret) {
>> +		pr_err("Error extending TPM20 PCR, result: %d\n", ret);
>> +		slaunch_txt_reset(txt,
>> +			"Failed to extend TPM20 PCR\n",
>> +			SL_ERROR_TPM_EXTEND);
>> +	}
>> +
>> +	kfree(digests);
>> +}
>> +
>> +static void slaunch_tpm20_extend(struct tpm_chip *tpm, void __iomem *txt)
>> +{
>> +	struct tcg_pcr_event *event_header;
>> +	struct tcg_pcr_event2_head *event;
>> +	int start = 0, end = 0, size;
>> +
>> +	event_header = (struct tcg_pcr_event *)(sl_evtlog.addr +
>> +						evtlog20->first_record_offset);
>> +
>> +	/* Skip first TPM 1.2 event to get to first TPM 2.0 event */
>> +	event = (struct tcg_pcr_event2_head *)((u8 *)event_header +
>> +						sizeof(struct tcg_pcr_event) +
>> +						event_header->event_size);
>> +
>> +	while ((void  *)event < sl_evtlog.addr + evtlog20->next_record_offset) {
>> +		size = __calc_tpm2_event_size(event, event_header, false);
>> +		if (!size)
>> +			slaunch_txt_reset(txt,
>> +				"TPM20 invalid event in event log\n",
>> +				SL_ERROR_TPM_INVALID_EVENT);
>> +
>> +		/*
>> +		 * Marker events indicate where the Secure Launch early stub
>> +		 * started and ended adding post launch events.
>> +		 */
>> +		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
>> +			end = 1;
>> +			break;
>> +		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
>> +			start = 1;
>> +			goto next;
>> +		}
>> +
>> +		if (start)
>> +			slaunch_tpm20_extend_event(tpm, txt, event);
>> +
>> +next:
>> +		event = (struct tcg_pcr_event2_head *)((u8 *)event + size);
>> +	}
>> +
>> +	if (!start || !end)
>> +		slaunch_txt_reset(txt,
>> +			"Missing start or end events for extending TPM20 PCRs\n",
>> +			SL_ERROR_TPM_EXTEND);
>> +}
>> +
>> +static void slaunch_tpm12_extend(struct tpm_chip *tpm, void __iomem *txt)
>> +{
>> +	struct tpm12_event_log_header *event_header;
>> +	struct tcg_pcr_event *event;
>> +	struct tpm_digest digest;
>> +	int start = 0, end = 0;
>> +	int size, ret;
>> +
>> +	event_header = (struct tpm12_event_log_header *)sl_evtlog.addr;
>> +	event = (struct tcg_pcr_event *)((u8 *)event_header +
>> +				sizeof(struct tpm12_event_log_header));
>> +
>> +	while ((void  *)event < sl_evtlog.addr + event_header->next_event_offset) {
>> +		size = sizeof(struct tcg_pcr_event) + event->event_size;
>> +
>> +		/*
>> +		 * Marker events indicate where the Secure Launch early stub
>> +		 * started and ended adding post launch events.
>> +		 */
>> +		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
>> +			end = 1;
>> +			break;
>> +		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
>> +			start = 1;
>> +			goto next;
>> +		}
>> +
>> +		if (start) {
>> +			memset(&digest.digest[0], 0, TPM_MAX_DIGEST_SIZE);
>> +			digest.alg_id = TPM_ALG_SHA1;
>> +			memcpy(&digest.digest[0], &event->digest[0],
>> +			       SHA1_DIGEST_SIZE);
>> +
>> +			ret = tpm_pcr_extend(tpm, event->pcr_idx, &digest);
>> +			if (ret) {
>> +				pr_err("Error extending TPM12 PCR, result: %d\n", ret);
>> +				slaunch_txt_reset(txt,
>> +					"Failed to extend TPM12 PCR\n",
>> +					SL_ERROR_TPM_EXTEND);
>> +			}
>> +		}
>> +
>> +next:
>> +		event = (struct tcg_pcr_event *)((u8 *)event + size);
>> +	}
>> +
>> +	if (!start || !end)
>> +		slaunch_txt_reset(txt,
>> +			"Missing start or end events for extending TPM12 PCRs\n",
>> +			SL_ERROR_TPM_EXTEND);
>> +}
>> +
>> +static void slaunch_pcr_extend(void __iomem *txt)
>> +{
>> +	struct tpm_chip *tpm;
>> +
>> +	tpm = tpm_default_chip();
>> +	if (!tpm)
>> +		slaunch_txt_reset(txt,
>> +			"Could not get default TPM chip\n",
>> +			SL_ERROR_TPM_INIT);
>> +	if (evtlog20)
>> +		slaunch_tpm20_extend(tpm, txt);
>> +	else
>> +		slaunch_tpm12_extend(tpm, txt);
>> +}
>> +
>> +static int __init slaunch_module_init(void)
>> +{
>> +	void __iomem *txt;
>> +
>> +	/* Check to see if Secure Launch happened */
>> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
>> +	    (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT))
>> +		return 0;
>> +
>> +	txt = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
>> +		      PAGE_SIZE);
>> +	if (!txt)
>> +		panic("Error ioremap of TXT priv registers\n");
>> +
>> +	/* Only Intel TXT is supported at this point */
>> +	slaunch_intel_evtlog(txt);
>> +
>> +	slaunch_pcr_extend(txt);
>> +
>> +	iounmap(txt);
> 
> I would remove the empty lines in-between the three calls above.
> 
>> +
>> +	return slaunch_expose_securityfs();
>> +}
>> +
>> +static void __exit slaunch_module_exit(void)
>> +{
>> +	slaunch_teardown_securityfs();
>> +}
>> +
>> +late_initcall(slaunch_module_init);
>> +
> 
> I would remove this empty line.
> 
>> +__exitcall(slaunch_module_exit);
>> -- 
>> 1.8.3.1
> 
> 
> BR, Jarkko


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

* Re: [PATCH v6 12/14] x86: Secure Launch late initcall platform module
@ 2023-05-12 15:53       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-12 15:53 UTC (permalink / raw)
  To: Jarkko Sakkinen, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel, Ross Philipson

On 5/10/23 18:39, Jarkko Sakkinen wrote:
> On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
>> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>>
>> The Secure Launch platform module is a late init module. During the
>> init call, the TPM event log is read and measurements taken in the
>> early boot stub code are located. These measurements are extended
>> into the TPM PCRs using the mainline TPM kernel driver.
>>
>> The platform module also registers the securityfs nodes to allow
>> access to TXT register fields on Intel along with the fetching of
>> and writing events to the late launch TPM log.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
>> Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   arch/x86/kernel/Makefile   |   1 +
>>   arch/x86/kernel/slmodule.c | 520 +++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 521 insertions(+)
>>   create mode 100644 arch/x86/kernel/slmodule.c
>>
>> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
>> index 3d2a33e..ee3fe300 100644
>> --- a/arch/x86/kernel/Makefile
>> +++ b/arch/x86/kernel/Makefile
>> @@ -73,6 +73,7 @@ obj-$(CONFIG_IA32_EMULATION)	+= tls.o
>>   obj-y				+= step.o
>>   obj-$(CONFIG_INTEL_TXT)		+= tboot.o
>>   obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
>> +obj-$(CONFIG_SECURE_LAUNCH)	+= slmodule.o
>>   obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
>>   obj-y				+= stacktrace.o
>>   obj-y				+= cpu/
>> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
>> new file mode 100644
>> index 0000000..70dcff5
>> --- /dev/null
>> +++ b/arch/x86/kernel/slmodule.c
>> @@ -0,0 +1,520 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Secure Launch late validation/setup, securityfs exposure and
>> + * finalization support.
>> + *
>> + * Copyright (c) 2022 Apertus Solutions, LLC
>> + * Copyright (c) 2021 Assured Information Security, Inc.
>> + * Copyright (c) 2022, Oracle and/or its affiliates.
>> + *
>> + * Author(s):
>> + *     Daniel P. Smith <dpsmith@apertussolutions.com>
>> + *     Garnet T. Grimm <grimmg@ainfosec.com>
> 
> I'm not sure what the authors list is good for in the days of Git,
> and all the tags we have for commit messages.
> 
> Instead of this you could just put to the commit:
> 
> Co-developed-by: Garnet T. Grimm <grimmg@ainfosec.com>
> Signed-off-by: Garnet T. Grimm <grimmg@ainfosec.com>
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> 
> See:
> 
> https://www.kernel.org/doc/html/latest/process/submitting-patches.html#when-to-use-acked-by-cc-and-co-developed-by

Yes we will fix all that. And everything else you pointed out in this 
review.

Thanks

> 
>> + */
>> +
>> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>> +
>> +#include <linux/fs.h>
>> +#include <linux/init.h>
>> +#include <linux/linkage.h>
>> +#include <linux/mm.h>
>> +#include <linux/io.h>
>> +#include <linux/uaccess.h>
>> +#include <linux/security.h>
>> +#include <linux/memblock.h>
>> +#include <asm/segment.h>
>> +#include <asm/sections.h>
>> +#include <crypto/sha2.h>
>> +#include <linux/slr_table.h>
>> +#include <linux/slaunch.h>
>> +
>> +#define DECLARE_TXT_PUB_READ_U(size, fmt, msg_size)			\
>> +static ssize_t txt_pub_read_u##size(unsigned int offset,		\
>> +		loff_t *read_offset,					\
>> +		size_t read_len,					\
>> +		char __user *buf)					\
> 
> This would really deserve:
> 
> /*
>   * Explain what DECLARE_TXT_PUB_READ_U is.
>   */
> 
>> +{									\
>> +	void __iomem *txt;						\
>> +	char msg_buffer[msg_size];					\
> 
> Reverse-christmas tree order.
> 
>> +	u##size reg_value = 0;						\
>> +	txt = ioremap(TXT_PUB_CONFIG_REGS_BASE,				\
>> +			TXT_NR_CONFIG_PAGES * PAGE_SIZE);		\
>> +	if (!txt)						\
>> +		return -EFAULT;					\
>> +	memcpy_fromio(&reg_value, txt + offset, sizeof(u##size));	\
>> +	iounmap(txt);							\
>> +	snprintf(msg_buffer, msg_size, fmt, reg_value);			\
>> +	return simple_read_from_buffer(buf, read_len, read_offset,	\
>> +			&msg_buffer, msg_size);				\
>> +}
>> +
>> +DECLARE_TXT_PUB_READ_U(8, "%#04x\n", 6);
>> +DECLARE_TXT_PUB_READ_U(32, "%#010x\n", 12);
>> +DECLARE_TXT_PUB_READ_U(64, "%#018llx\n", 20);
>> +
>> +#define DECLARE_TXT_FOPS(reg_name, reg_offset, reg_size)		\
>> +static ssize_t txt_##reg_name##_read(struct file *flip,			\
>> +		char __user *buf, size_t read_len, loff_t *read_offset)	\
>> +{									\
>> +	return txt_pub_read_u##reg_size(reg_offset, read_offset,	\
>> +			read_len, buf);					\
>> +}									\
>> +static const struct file_operations reg_name##_ops = {			\
>> +	.read = txt_##reg_name##_read,					\
>> +}
>> +
>> +DECLARE_TXT_FOPS(sts, TXT_CR_STS, 64);
>> +DECLARE_TXT_FOPS(ests, TXT_CR_ESTS, 8);
>> +DECLARE_TXT_FOPS(errorcode, TXT_CR_ERRORCODE, 32);
>> +DECLARE_TXT_FOPS(didvid, TXT_CR_DIDVID, 64);
>> +DECLARE_TXT_FOPS(e2sts, TXT_CR_E2STS, 64);
>> +DECLARE_TXT_FOPS(ver_emif, TXT_CR_VER_EMIF, 32);
>> +DECLARE_TXT_FOPS(scratchpad, TXT_CR_SCRATCHPAD, 64);
>> +
>> +/*
>> + * Securityfs exposure
>> + */
>> +struct memfile {
>> +	char *name;
>> +	void *addr;
>> +	size_t size;
>> +};
>> +
>> +static struct memfile sl_evtlog = {"eventlog", 0, 0};
>> +static void *txt_heap;
>> +static struct txt_heap_event_log_pointer2_1_element __iomem *evtlog20;
>> +static DEFINE_MUTEX(sl_evt_log_mutex);
>> +
>> +static ssize_t sl_evtlog_read(struct file *file, char __user *buf,
>> +			      size_t count, loff_t *pos)
>> +{
>> +	ssize_t size;
>> +
>> +	if (!sl_evtlog.addr)
>> +		return 0;
>> +
>> +	mutex_lock(&sl_evt_log_mutex);
>> +	size = simple_read_from_buffer(buf, count, pos, sl_evtlog.addr,
>> +				       sl_evtlog.size);
>> +	mutex_unlock(&sl_evt_log_mutex);
>> +
>> +	return size;
>> +}
>> +
>> +static ssize_t sl_evtlog_write(struct file *file, const char __user *buf,
>> +				size_t datalen, loff_t *ppos)
>> +{
>> +	ssize_t result;
>> +	char *data;
>> +
>> +	if (!sl_evtlog.addr)
>> +		return 0;
>> +
>> +	/* No partial writes. */
>> +	result = -EINVAL;
>> +	if (*ppos != 0)
>> +		goto out;
>> +
>> +	data = memdup_user(buf, datalen);
>> +	if (IS_ERR(data)) {
>> +		result = PTR_ERR(data);
>> +		goto out;
>> +	}
>> +
>> +	mutex_lock(&sl_evt_log_mutex);
>> +	if (evtlog20)
>> +		result = tpm20_log_event(evtlog20, sl_evtlog.addr,
>> +					 sl_evtlog.size, datalen, data);
>> +	else
>> +		result = tpm12_log_event(sl_evtlog.addr, sl_evtlog.size,
>> +					 datalen, data);
>> +	mutex_unlock(&sl_evt_log_mutex);
>> +
>> +	kfree(data);
>> +out:
>> +	return result;
>> +}
>> +
>> +static const struct file_operations sl_evtlog_ops = {
>> +	.read = sl_evtlog_read,
>> +	.write = sl_evtlog_write,
>> +	.llseek	= default_llseek,
>> +};
>> +
>> +struct sfs_file {
>> +	const char *name;
>> +	const struct file_operations *fops;
>> +};
>> +
>> +#define SL_TXT_ENTRY_COUNT	7
>> +static const struct sfs_file sl_txt_files[] = {
>> +	{ "sts", &sts_ops },
>> +	{ "ests", &ests_ops },
>> +	{ "errorcode", &errorcode_ops },
>> +	{ "didvid", &didvid_ops },
>> +	{ "ver_emif", &ver_emif_ops },
>> +	{ "scratchpad", &scratchpad_ops },
>> +	{ "e2sts", &e2sts_ops }
>> +};
>> +
>> +/* sysfs file handles */
>> +static struct dentry *slaunch_dir;
>> +static struct dentry *event_file;
>> +static struct dentry *txt_dir;
>> +static struct dentry *txt_entries[SL_TXT_ENTRY_COUNT];
>> +
>> +static long slaunch_expose_securityfs(void)
>> +{
>> +	long ret = 0;
>> +	int i;
>> +
>> +	slaunch_dir = securityfs_create_dir("slaunch", NULL);
>> +	if (IS_ERR(slaunch_dir))
>> +		return PTR_ERR(slaunch_dir);
>> +
>> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
>> +		txt_dir = securityfs_create_dir("txt", slaunch_dir);
>> +		if (IS_ERR(txt_dir)) {
>> +			ret = PTR_ERR(txt_dir);
>> +			goto remove_slaunch;
>> +		}
>> +
>> +		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++) {
>> +			txt_entries[i] = securityfs_create_file(
>> +						sl_txt_files[i].name, 0440,
>> +						txt_dir, NULL,
>> +						sl_txt_files[i].fops);
>> +			if (IS_ERR(txt_entries[i])) {
>> +				ret = PTR_ERR(txt_entries[i]);
>> +				goto remove_files;
>> +			}
>> +		}
>> +
>> +	}
>> +
>> +	if (sl_evtlog.addr > 0) {
>> +		event_file = securityfs_create_file(
>> +					sl_evtlog.name, 0440,
>> +					slaunch_dir, NULL,
>> +					&sl_evtlog_ops);
>> +		if (IS_ERR(event_file)) {
>> +			ret = PTR_ERR(event_file);
>> +			goto remove_files;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +
>> +remove_files:
>> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
>> +		while (--i >= 0)
>> +			securityfs_remove(txt_entries[i]);
>> +		securityfs_remove(txt_dir);
>> +	}
>> +remove_slaunch:
>> +	securityfs_remove(slaunch_dir);
>> +
>> +	return ret;
>> +}
>> +
>> +static void slaunch_teardown_securityfs(void)
>> +{
>> +	int i;
>> +
>> +	securityfs_remove(event_file);
>> +	if (sl_evtlog.addr) {
>> +		memunmap(sl_evtlog.addr);
>> +		sl_evtlog.addr = NULL;
>> +	}
>> +	sl_evtlog.size = 0;
>> +
>> +	if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
>> +		for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++)
>> +			securityfs_remove(txt_entries[i]);
>> +
>> +		securityfs_remove(txt_dir);
>> +
>> +		if (txt_heap) {
>> +			memunmap(txt_heap);
>> +			txt_heap = NULL;
>> +		}
>> +	}
>> +
>> +	securityfs_remove(slaunch_dir);
>> +}
>> +
>> +static void slaunch_intel_evtlog(void __iomem *txt)
>> +{
>> +	struct slr_entry_log_info *log_info;
>> +	struct txt_os_mle_data *params;
>> +	struct slr_table *slrt;
>> +	void *os_sinit_data;
>> +	u64 base, size;
>> +
>> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
>> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
>> +
>> +	/* now map TXT heap */
>> +	txt_heap = memremap(base, size, MEMREMAP_WB);
>> +	if (!txt_heap)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap TXT heap\n",
>> +			SL_ERROR_HEAP_MAP);
>> +
>> +	params = (struct txt_os_mle_data *)txt_os_mle_data_start(txt_heap);
>> +
>> +	/* Get the SLRT and remap it */
>> +	slrt = memremap(params->slrt, sizeof(*slrt), MEMREMAP_WB);
>> +	if (!slrt)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap SLR Table\n",
>> +			SL_ERROR_SLRT_MAP);
>> +	size = slrt->size;
>> +	memunmap(slrt);
>> +
>> +	slrt = memremap(params->slrt, size, MEMREMAP_WB);
>> +	if (!slrt)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap SLR Table\n",
>> +			SL_ERROR_SLRT_MAP);
>> +
>> +	log_info = (struct slr_entry_log_info *)
>> +			slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
>> +	if (!log_info)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap SLR Table\n",
>> +			SL_ERROR_SLRT_MISSING_ENTRY);
>> +
>> +	sl_evtlog.size = log_info->size;
>> +	sl_evtlog.addr = memremap(log_info->addr, log_info->size,
>> +				  MEMREMAP_WB);
>> +	if (!sl_evtlog.addr)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to memremap TPM event log\n",
>> +			SL_ERROR_EVENTLOG_MAP);
>> +
>> +	memunmap(slrt);
>> +
>> +	/* Determine if this is TPM 1.2 or 2.0 event log */
>> +	if (memcmp(sl_evtlog.addr + sizeof(struct tcg_pcr_event),
>> +		    TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
>> +		return; /* looks like it is not 2.0 */
>> +
>> +	/* For TPM 2.0 logs, the extended heap element must be located */
>> +	os_sinit_data = txt_os_sinit_data_start(txt_heap);
>> +
>> +	evtlog20 = tpm20_find_log2_1_element(os_sinit_data);
>> +
>> +	/*
>> +	 * If this fails, things are in really bad shape. Any attempt to write
>> +	 * events to the log will fail.
>> +	 */
>> +	if (!evtlog20)
>> +		slaunch_txt_reset(txt,
>> +			"Error failed to find TPM20 event log element\n",
>> +			SL_ERROR_TPM_INVALID_LOG20);
>> +}
>> +
>> +static void slaunch_tpm20_extend_event(struct tpm_chip *tpm, void __iomem *txt,
>> +				       struct tcg_pcr_event2_head *event)
>> +{
>> +	u16 *alg_id_field = (u16 *)((u8 *)event +
>> +				    sizeof(struct tcg_pcr_event2_head));
>> +	struct tpm_digest *digests;
>> +	u8 *dptr;
>> +	int ret;
>> +	u32 i, j;
>> +
>> +	digests = kcalloc(tpm->nr_allocated_banks, sizeof(*digests),
>> +			  GFP_KERNEL);
>> +	if (!digests)
>> +		slaunch_txt_reset(txt,
>> +			"Failed to allocate array of digests\n",
>> +			SL_ERROR_GENERIC);
>> +
>> +	for (i = 0; i < tpm->nr_allocated_banks; i++)
>> +		digests[i].alg_id = tpm->allocated_banks[i].alg_id;
>> +
>> +
>> +	/* Early SL code ensured there was a max count of 2 digests */
>> +	for (i = 0; i < event->count; i++) {
>> +		dptr = (u8 *)alg_id_field + sizeof(u16);
>> +
>> +		for (j = 0; j < tpm->nr_allocated_banks; j++) {
>> +			if (digests[j].alg_id != *alg_id_field)
>> +				continue;
>> +
>> +			switch (digests[j].alg_id) {
>> +			case TPM_ALG_SHA256:
>> +				memcpy(&digests[j].digest[0], dptr,
>> +				       SHA256_DIGEST_SIZE);
>> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
>> +					SHA256_DIGEST_SIZE + sizeof(u16));
>> +				break;
>> +			case TPM_ALG_SHA1:
>> +				memcpy(&digests[j].digest[0], dptr,
>> +				       SHA1_DIGEST_SIZE);
>> +				alg_id_field = (u16 *)((u8 *)alg_id_field +
>> +					SHA1_DIGEST_SIZE + sizeof(u16));
>> +			default:
>> +				break;
>> +			}
>> +		}
>> +	}
>> +
>> +	ret = tpm_pcr_extend(tpm, event->pcr_idx, digests);
>> +	if (ret) {
>> +		pr_err("Error extending TPM20 PCR, result: %d\n", ret);
>> +		slaunch_txt_reset(txt,
>> +			"Failed to extend TPM20 PCR\n",
>> +			SL_ERROR_TPM_EXTEND);
>> +	}
>> +
>> +	kfree(digests);
>> +}
>> +
>> +static void slaunch_tpm20_extend(struct tpm_chip *tpm, void __iomem *txt)
>> +{
>> +	struct tcg_pcr_event *event_header;
>> +	struct tcg_pcr_event2_head *event;
>> +	int start = 0, end = 0, size;
>> +
>> +	event_header = (struct tcg_pcr_event *)(sl_evtlog.addr +
>> +						evtlog20->first_record_offset);
>> +
>> +	/* Skip first TPM 1.2 event to get to first TPM 2.0 event */
>> +	event = (struct tcg_pcr_event2_head *)((u8 *)event_header +
>> +						sizeof(struct tcg_pcr_event) +
>> +						event_header->event_size);
>> +
>> +	while ((void  *)event < sl_evtlog.addr + evtlog20->next_record_offset) {
>> +		size = __calc_tpm2_event_size(event, event_header, false);
>> +		if (!size)
>> +			slaunch_txt_reset(txt,
>> +				"TPM20 invalid event in event log\n",
>> +				SL_ERROR_TPM_INVALID_EVENT);
>> +
>> +		/*
>> +		 * Marker events indicate where the Secure Launch early stub
>> +		 * started and ended adding post launch events.
>> +		 */
>> +		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
>> +			end = 1;
>> +			break;
>> +		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
>> +			start = 1;
>> +			goto next;
>> +		}
>> +
>> +		if (start)
>> +			slaunch_tpm20_extend_event(tpm, txt, event);
>> +
>> +next:
>> +		event = (struct tcg_pcr_event2_head *)((u8 *)event + size);
>> +	}
>> +
>> +	if (!start || !end)
>> +		slaunch_txt_reset(txt,
>> +			"Missing start or end events for extending TPM20 PCRs\n",
>> +			SL_ERROR_TPM_EXTEND);
>> +}
>> +
>> +static void slaunch_tpm12_extend(struct tpm_chip *tpm, void __iomem *txt)
>> +{
>> +	struct tpm12_event_log_header *event_header;
>> +	struct tcg_pcr_event *event;
>> +	struct tpm_digest digest;
>> +	int start = 0, end = 0;
>> +	int size, ret;
>> +
>> +	event_header = (struct tpm12_event_log_header *)sl_evtlog.addr;
>> +	event = (struct tcg_pcr_event *)((u8 *)event_header +
>> +				sizeof(struct tpm12_event_log_header));
>> +
>> +	while ((void  *)event < sl_evtlog.addr + event_header->next_event_offset) {
>> +		size = sizeof(struct tcg_pcr_event) + event->event_size;
>> +
>> +		/*
>> +		 * Marker events indicate where the Secure Launch early stub
>> +		 * started and ended adding post launch events.
>> +		 */
>> +		if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
>> +			end = 1;
>> +			break;
>> +		} else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
>> +			start = 1;
>> +			goto next;
>> +		}
>> +
>> +		if (start) {
>> +			memset(&digest.digest[0], 0, TPM_MAX_DIGEST_SIZE);
>> +			digest.alg_id = TPM_ALG_SHA1;
>> +			memcpy(&digest.digest[0], &event->digest[0],
>> +			       SHA1_DIGEST_SIZE);
>> +
>> +			ret = tpm_pcr_extend(tpm, event->pcr_idx, &digest);
>> +			if (ret) {
>> +				pr_err("Error extending TPM12 PCR, result: %d\n", ret);
>> +				slaunch_txt_reset(txt,
>> +					"Failed to extend TPM12 PCR\n",
>> +					SL_ERROR_TPM_EXTEND);
>> +			}
>> +		}
>> +
>> +next:
>> +		event = (struct tcg_pcr_event *)((u8 *)event + size);
>> +	}
>> +
>> +	if (!start || !end)
>> +		slaunch_txt_reset(txt,
>> +			"Missing start or end events for extending TPM12 PCRs\n",
>> +			SL_ERROR_TPM_EXTEND);
>> +}
>> +
>> +static void slaunch_pcr_extend(void __iomem *txt)
>> +{
>> +	struct tpm_chip *tpm;
>> +
>> +	tpm = tpm_default_chip();
>> +	if (!tpm)
>> +		slaunch_txt_reset(txt,
>> +			"Could not get default TPM chip\n",
>> +			SL_ERROR_TPM_INIT);
>> +	if (evtlog20)
>> +		slaunch_tpm20_extend(tpm, txt);
>> +	else
>> +		slaunch_tpm12_extend(tpm, txt);
>> +}
>> +
>> +static int __init slaunch_module_init(void)
>> +{
>> +	void __iomem *txt;
>> +
>> +	/* Check to see if Secure Launch happened */
>> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
>> +	    (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT))
>> +		return 0;
>> +
>> +	txt = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
>> +		      PAGE_SIZE);
>> +	if (!txt)
>> +		panic("Error ioremap of TXT priv registers\n");
>> +
>> +	/* Only Intel TXT is supported at this point */
>> +	slaunch_intel_evtlog(txt);
>> +
>> +	slaunch_pcr_extend(txt);
>> +
>> +	iounmap(txt);
> 
> I would remove the empty lines in-between the three calls above.
> 
>> +
>> +	return slaunch_expose_securityfs();
>> +}
>> +
>> +static void __exit slaunch_module_exit(void)
>> +{
>> +	slaunch_teardown_securityfs();
>> +}
>> +
>> +late_initcall(slaunch_module_init);
>> +
> 
> I would remove this empty line.
> 
>> +__exitcall(slaunch_module_exit);
>> -- 
>> 1.8.3.1
> 
> 
> BR, Jarkko


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 12/14] x86: Secure Launch late initcall platform module
  2023-05-10 22:40     ` Jarkko Sakkinen
@ 2023-05-12 15:54       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-12 15:54 UTC (permalink / raw)
  To: Jarkko Sakkinen, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel, Ross Philipson

On 5/10/23 18:40, Jarkko Sakkinen wrote:
> On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
>> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>>
>> The Secure Launch platform module is a late init module. During the
>> init call, the TPM event log is read and measurements taken in the
>> early boot stub code are located. These measurements are extended
>> into the TPM PCRs using the mainline TPM kernel driver.
>>
>> The platform module also registers the securityfs nodes to allow
>> access to TXT register fields on Intel along with the fetching of
>> and writing events to the late launch TPM log.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
>> Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   arch/x86/kernel/Makefile   |   1 +
>>   arch/x86/kernel/slmodule.c | 520 +++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 521 insertions(+)
>>   create mode 100644 arch/x86/kernel/slmodule.c
>>
>> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
>> index 3d2a33e..ee3fe300 100644
>> --- a/arch/x86/kernel/Makefile
>> +++ b/arch/x86/kernel/Makefile
>> @@ -73,6 +73,7 @@ obj-$(CONFIG_IA32_EMULATION)	+= tls.o
>>   obj-y				+= step.o
>>   obj-$(CONFIG_INTEL_TXT)		+= tboot.o
>>   obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
>> +obj-$(CONFIG_SECURE_LAUNCH)	+= slmodule.o
>>   obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
>>   obj-y				+= stacktrace.o
>>   obj-y				+= cpu/
>> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
>> new file mode 100644
>> index 0000000..70dcff5
>> --- /dev/null
>> +++ b/arch/x86/kernel/slmodule.c
>> @@ -0,0 +1,520 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Secure Launch late validation/setup, securityfs exposure and
>> + * finalization support.
> 
> /* Secure Launch late validation/setup, securityfs exposure and finalization */
> 
> 79 characters (max length allowed is 100).

Yup will fix.

> 
> BR, Jarkko
> 


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

* Re: [PATCH v6 12/14] x86: Secure Launch late initcall platform module
@ 2023-05-12 15:54       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-12 15:54 UTC (permalink / raw)
  To: Jarkko Sakkinen, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel, Ross Philipson

On 5/10/23 18:40, Jarkko Sakkinen wrote:
> On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
>> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>>
>> The Secure Launch platform module is a late init module. During the
>> init call, the TPM event log is read and measurements taken in the
>> early boot stub code are located. These measurements are extended
>> into the TPM PCRs using the mainline TPM kernel driver.
>>
>> The platform module also registers the securityfs nodes to allow
>> access to TXT register fields on Intel along with the fetching of
>> and writing events to the late launch TPM log.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
>> Signed-off-by: garnetgrimm <grimmg@ainfosec.com>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   arch/x86/kernel/Makefile   |   1 +
>>   arch/x86/kernel/slmodule.c | 520 +++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 521 insertions(+)
>>   create mode 100644 arch/x86/kernel/slmodule.c
>>
>> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
>> index 3d2a33e..ee3fe300 100644
>> --- a/arch/x86/kernel/Makefile
>> +++ b/arch/x86/kernel/Makefile
>> @@ -73,6 +73,7 @@ obj-$(CONFIG_IA32_EMULATION)	+= tls.o
>>   obj-y				+= step.o
>>   obj-$(CONFIG_INTEL_TXT)		+= tboot.o
>>   obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
>> +obj-$(CONFIG_SECURE_LAUNCH)	+= slmodule.o
>>   obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
>>   obj-y				+= stacktrace.o
>>   obj-y				+= cpu/
>> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
>> new file mode 100644
>> index 0000000..70dcff5
>> --- /dev/null
>> +++ b/arch/x86/kernel/slmodule.c
>> @@ -0,0 +1,520 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Secure Launch late validation/setup, securityfs exposure and
>> + * finalization support.
> 
> /* Secure Launch late validation/setup, securityfs exposure and finalization */
> 
> 79 characters (max length allowed is 100).

Yup will fix.

> 
> BR, Jarkko
> 


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
  2023-05-10 23:02     ` Jarkko Sakkinen
@ 2023-05-12 15:58       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-12 15:58 UTC (permalink / raw)
  To: Jarkko Sakkinen, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel, Ross Philipson

On 5/10/23 19:02, Jarkko Sakkinen wrote:
> On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
>> The routine slaunch_setup is called out of the x86 specific setup_arch
>> routine during early kernel boot. After determining what platform is
>> present, various operations specific to that platform occur. This
>> includes finalizing setting for the platform late launch and verifying
>> that memory protections are in place.
>>
>> For TXT, this code also reserves the original compressed kernel setup
>> area where the APs were left looping so that this memory cannot be used.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   arch/x86/kernel/Makefile   |   1 +
>>   arch/x86/kernel/setup.c    |   3 +
>>   arch/x86/kernel/slaunch.c  | 497 +++++++++++++++++++++++++++++++++++++++++++++
>>   drivers/iommu/intel/dmar.c |   4 +
>>   4 files changed, 505 insertions(+)
>>   create mode 100644 arch/x86/kernel/slaunch.c
>>
>> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
>> index dd61752..3d2a33e 100644
>> --- a/arch/x86/kernel/Makefile
>> +++ b/arch/x86/kernel/Makefile
>> @@ -72,6 +72,7 @@ obj-$(CONFIG_X86_32)		+= tls.o
>>   obj-$(CONFIG_IA32_EMULATION)	+= tls.o
>>   obj-y				+= step.o
>>   obj-$(CONFIG_INTEL_TXT)		+= tboot.o
>> +obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
>>   obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
>>   obj-y				+= stacktrace.o
>>   obj-y				+= cpu/
>> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
>> index 16babff..592c09e 100644
>> --- a/arch/x86/kernel/setup.c
>> +++ b/arch/x86/kernel/setup.c
>> @@ -21,6 +21,7 @@
>>   #include <linux/root_dev.h>
>>   #include <linux/hugetlb.h>
>>   #include <linux/tboot.h>
>> +#include <linux/slaunch.h>
> 
> Only because of pure curiosity: what made you choose this location in
> the middle for the new include? :-)

Only because Secure Launch is like TBOOT. No other real reason.

> 
>>   #include <linux/usb/xhci-dbgp.h>
>>   #include <linux/static_call.h>
>>   #include <linux/swiotlb.h>
>> @@ -1063,6 +1064,8 @@ void __init setup_arch(char **cmdline_p)
>>   	early_gart_iommu_check();
>>   #endif
>>   
>> +	slaunch_setup_txt();
>> +
>>   	/*
>>   	 * partially used pages are not usable - thus
>>   	 * we are rounding upwards:
>> diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
>> new file mode 100644
>> index 0000000..7dba088
>> --- /dev/null
>> +++ b/arch/x86/kernel/slaunch.c
>> @@ -0,0 +1,497 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Secure Launch late validation/setup and finalization support.
>> + *
>> + * Copyright (c) 2022, Oracle and/or its affiliates.
>> + */
>> +
>> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>> +
>> +#include <linux/linkage.h>
>> +#include <linux/mm.h>
>> +#include <linux/io.h>
>> +#include <linux/uaccess.h>
>> +#include <linux/security.h>
>> +#include <linux/memblock.h>
>> +#include <asm/segment.h>
>> +#include <asm/sections.h>
>> +#include <asm/tlbflush.h>
>> +#include <asm/e820/api.h>
>> +#include <asm/setup.h>
>> +#include <linux/slr_table.h>
>> +#include <linux/slaunch.h>
>> +
>> +static u32 sl_flags;
>> +static struct sl_ap_wake_info ap_wake_info;
>> +static u64 evtlog_addr;
>> +static u32 evtlog_size;
>> +static u64 vtd_pmr_lo_size;
>> +
>> +/* This should be plenty of room */
>> +static u8 txt_dmar[PAGE_SIZE] __aligned(16);
>> +
>> +u32 slaunch_get_flags(void)
>> +{
>> +	return sl_flags;
>> +}
>> +EXPORT_SYMBOL(slaunch_get_flags);
>> +
>> +struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
>> +{
>> +	return &ap_wake_info;
>> +}
>> +
>> +struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
>> +{
>> +	/* The DMAR is only stashed and provided via TXT on Intel systems */
>> +	if (memcmp(txt_dmar, "DMAR", 4))
>> +		return dmar;
>> +
>> +	return (struct acpi_table_header *)(&txt_dmar[0]);
>> +}
>> +
>> +void __noreturn slaunch_txt_reset(void __iomem *txt,
>> +				  const char *msg, u64 error)
>> +{
>> +	u64 one = 1, val;
>> +
>> +	pr_err("%s", msg);
>> +
>> +	/*
>> +	 * This performs a TXT reset with a sticky error code. The reads of
>> +	 * TXT_CR_E2STS act as barriers.
>> +	 */
>> +	memcpy_toio(txt + TXT_CR_ERRORCODE, &error, sizeof(error));
>> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
>> +	memcpy_toio(txt + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
>> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
>> +	memcpy_toio(txt + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
>> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
>> +	memcpy_toio(txt + TXT_CR_CMD_RESET, &one, sizeof(one));
>> +
>> +	for ( ; ; )
>> +		asm volatile ("hlt");
>> +
>> +	unreachable();
>> +}
>> +
>> +/*
>> + * The TXT heap is too big to map all at once with early_ioremap
>> + * so it is done a table at a time.
>> + */
>> +static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
>> +					     u32 bytes)
>> +{
>> +	u64 base, size, offset = 0;
>> +	void *heap;
>> +	int i;
>> +
>> +	if (type > TXT_SINIT_TABLE_MAX)
>> +		slaunch_txt_reset(txt,
>> +			"Error invalid table type for early heap walk\n",
>> +			SL_ERROR_HEAP_WALK);
> 
> Align with 'txt'.

Ack

> 
>> +
>> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
>> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
>> +
>> +	/* Iterate over heap tables looking for table of "type" */
>> +	for (i = 0; i < type; i++) {
>> +		base += offset;
>> +		heap = early_memremap(base, sizeof(u64));
>> +		if (!heap)
>> +			slaunch_txt_reset(txt,
>> +				"Error early_memremap of heap for heap walk\n",
>> +				SL_ERROR_HEAP_MAP);
>> +
>> +		offset = *((u64 *)heap);
>> +
>> +		/*
>> +		 * After the first iteration, any offset of zero is invalid and
>> +		 * implies the TXT heap is corrupted.
>> +		 */
>> +		if (!offset)
>> +			slaunch_txt_reset(txt,
>> +				"Error invalid 0 offset in heap walk\n",
>> +				SL_ERROR_HEAP_ZERO_OFFSET);
>> +
>> +		early_memunmap(heap, sizeof(u64));
>> +	}
>> +
>> +	/* Skip the size field at the head of each table */
>> +	base += sizeof(u64);
>> +	heap = early_memremap(base, bytes);
>> +	if (!heap)
>> +		slaunch_txt_reset(txt,
>> +				  "Error early_memremap of heap section\n",
>> +				  SL_ERROR_HEAP_MAP);
>> +
>> +	return heap;
>> +}
>> +
>> +static void __init txt_early_put_heap_table(void *addr, unsigned long size)
>> +{
>> +	early_memunmap(addr, size);
>> +}
>> +
>> +/*
>> + * TXT uses a special set of VTd registers to protect all of memory from DMA
>> + * until the IOMMU can be programmed to protect memory. There is the low
>> + * memory PMR that can protect all memory up to 4G. The high memory PRM can
>> + * be setup to protect all memory beyond 4Gb. Validate that these values cover
>> + * what is expected.
>> + */
>> +static void __init slaunch_verify_pmrs(void __iomem *txt)
>> +{
>> +	struct txt_os_sinit_data *os_sinit_data;
>> +	u32 field_offset, err = 0;
>> +	const char *errmsg = "";
>> +	unsigned long last_pfn;
>> +
>> +	field_offset = offsetof(struct txt_os_sinit_data, lcp_po_base);
>> +	os_sinit_data = txt_early_get_heap_table(txt, TXT_OS_SINIT_DATA_TABLE,
>> +						 field_offset);
>> +
>> +	/* Save a copy */
>> +	vtd_pmr_lo_size = os_sinit_data->vtd_pmr_lo_size;
>> +
>> +	last_pfn = e820__end_of_ram_pfn();
>> +
>> +	/*
>> +	 * First make sure the hi PMR covers all memory above 4G. In the
>> +	 * unlikely case where there is < 4G on the system, the hi PMR will
>> +	 * not be set.
>> +	 */
>> +	if (os_sinit_data->vtd_pmr_hi_base != 0x0ULL) {
>> +		if (os_sinit_data->vtd_pmr_hi_base != 0x100000000ULL) {
>> +			err = SL_ERROR_HI_PMR_BASE;
>> +			errmsg =  "Error hi PMR base\n";
>> +			goto out;
>> +		}
>> +
>> +		if (PFN_PHYS(last_pfn) > os_sinit_data->vtd_pmr_hi_base +
>> +		    os_sinit_data->vtd_pmr_hi_size) {
>> +			err = SL_ERROR_HI_PMR_SIZE;
>> +			errmsg = "Error hi PMR size\n";
>> +			goto out;
>> +		}
>> +	}
>> +
>> +	/*
>> +	 * Lo PMR base should always be 0. This was already checked in
>> +	 * early stub.
>> +	 */
>> +
>> +	/*
>> +	 * Check that if the kernel was loaded below 4G, that it is protected
>> +	 * by the lo PMR. Note this is the decompressed kernel. The ACM would
>> +	 * have ensured the compressed kernel (the MLE image) was protected.
>> +	 */
>> +	if ((__pa_symbol(_end) < 0x100000000ULL) &&
>> +	    (__pa_symbol(_end) > os_sinit_data->vtd_pmr_lo_size)) {
>> +		err = SL_ERROR_LO_PMR_MLE;
>> +		errmsg = "Error lo PMR does not cover MLE kernel\n";
>> +	}
>> +
>> +	/*
>> +	 * Other regions of interest like boot param, AP wake block, cmdline
>> +	 * already checked for PMR coverage in the early stub code.
>> +	 */
>> +
>> +out:
>> +	txt_early_put_heap_table(os_sinit_data, field_offset);
>> +
>> +	if (err)
>> +		slaunch_txt_reset(txt, errmsg, err);
>> +}
>> +
>> +static void __init slaunch_txt_reserve_range(u64 base, u64 size)
>> +{
>> +	int type;
>> +
>> +	type = e820__get_entry_type(base, base + size - 1);
>> +	if (type == E820_TYPE_RAM) {
>> +		pr_info("memblock reserve base: %llx size: %llx\n", base, size);
>> +		memblock_reserve(base, size);
>> +	}
>> +}
>> +
>> +/*
>> + * For Intel, certain regions of memory must be marked as reserved by putting
>> + * them on the memblock reserved list if they are not already e820 reserved.
>> + * This includes:
>> + *  - The TXT HEAP
>> + *  - The ACM area
>> + *  - The TXT private register bank
>> + *  - The MDR list sent to the MLE by the ACM (see TXT specification)
>> + *  (Normally the above are properly reserved by firmware but if it was not
>> + *  done, reserve them now)
>> + *  - The AP wake block
>> + *  - TPM log external to the TXT heap
>> + *
>> + * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
>> + * the low PMR must be reservered too.
>> + */
>> +static void __init slaunch_txt_reserve(void __iomem *txt)
>> +{
>> +	struct txt_sinit_memory_descriptor_record *mdr;
>> +	struct txt_sinit_mle_data *sinit_mle_data;
>> +	u64 base, size, heap_base, heap_size;
>> +	u32 mdrnum, mdroffset, mdrslen;
>> +	u32 field_offset, i;
>> +	void *mdrs;
>> +
>> +	base = TXT_PRIV_CONFIG_REGS_BASE;
>> +	size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
>> +	slaunch_txt_reserve_range(base, size);
>> +
>> +	memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
>> +	memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
>> +	slaunch_txt_reserve_range(heap_base, heap_size);
>> +
>> +	memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
>> +	memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
>> +	slaunch_txt_reserve_range(base, size);
>> +
>> +	field_offset = offsetof(struct txt_sinit_mle_data,
>> +				sinit_vtd_dmar_table_size);
>> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +						  field_offset);
>> +
>> +	mdrnum = sinit_mle_data->num_of_sinit_mdrs;
>> +	mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
>> +
>> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
>> +
>> +	if (!mdrnum)
>> +		goto nomdr;
>> +
>> +	mdrslen = mdrnum * sizeof(struct txt_sinit_memory_descriptor_record);
>> +
>> +	mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +					mdroffset + mdrslen - 8);
>> +
>> +	mdr = mdrs + mdroffset - 8;
>> +
>> +	for (i = 0; i < mdrnum; i++, mdr++) {
>> +		/* Spec says some entries can have length 0, ignore them */
>> +		if (mdr->type > 0 && mdr->length > 0)
>> +			slaunch_txt_reserve_range(mdr->address, mdr->length);
>> +	}
>> +
>> +	txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
>> +
>> +nomdr:
>> +	slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
>> +				  ap_wake_info.ap_wake_block_size);
>> +
>> +	/*
>> +	 * Earlier checks ensured that the event log was properly situated
>> +	 * either inside the TXT heap or outside. This is a check to see if the
>> +	 * event log needs to be reserved. If it is in the TXT heap, it is
>> +	 * already reserved.
>> +	 */
>> +	if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
>> +		slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
>> +
>> +	for (i = 0; i < e820_table->nr_entries; i++) {
>> +		base = e820_table->entries[i].addr;
>> +		size = e820_table->entries[i].size;
>> +		if ((base >= vtd_pmr_lo_size) && (base < 0x100000000ULL))
>> +			slaunch_txt_reserve_range(base, size);
>> +		else if ((base < vtd_pmr_lo_size) &&
>> +			 (base + size > vtd_pmr_lo_size))
>> +			slaunch_txt_reserve_range(vtd_pmr_lo_size,
>> +						  base + size - vtd_pmr_lo_size);
>> +	}
>> +}
>> +
>> +/*
>> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
>> + * It is stored in the TXT heap. Fetch it from there and make it available
>> + * to the IOMMU driver.
>> + */
>> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
>> +{
>> +	struct txt_sinit_mle_data *sinit_mle_data;
>> +	u32 field_offset, dmar_size, dmar_offset;
>> +	void *dmar;
>> +
>> +	memset(&txt_dmar, 0, PAGE_SIZE);
>> +
>> +	field_offset = offsetof(struct txt_sinit_mle_data,
>> +				processor_scrtm_status);
>> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +						  field_offset);
>> +
>> +	dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
>> +	dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
>> +
>> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
>> +
>> +	if (!dmar_size || !dmar_offset)
>> +		slaunch_txt_reset(txt,
>> +				  "Error invalid DMAR table values\n",
>> +				  SL_ERROR_HEAP_INVALID_DMAR);
>> +
>> +	if (unlikely(dmar_size > PAGE_SIZE))
>> +		slaunch_txt_reset(txt,
>> +				  "Error DMAR too big to store\n",
>> +				  SL_ERROR_HEAP_DMAR_SIZE);
>> +
>> +
>> +	dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +					dmar_offset + dmar_size - 8);
>> +	if (!dmar)
>> +		slaunch_txt_reset(txt,
>> +				  "Error early_ioremap of DMAR\n",
>> +				  SL_ERROR_HEAP_DMAR_MAP);
>> +
>> +	memcpy(&txt_dmar[0], dmar + dmar_offset - 8, dmar_size);
>> +
>> +	txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
>> +}
>> +
>> +/*
>> + * The location of the safe AP wake code block is stored in the TXT heap.
>> + * Fetch needed values here in the early init code for later use in SMP
>> + * startup.
>> + *
>> + * Also get the TPM event log values are in the SLRT and have to be fetched.
>> + * They will be put on the memblock reserve list later.
>> + */
>> +static void __init slaunch_fetch_values(void __iomem *txt)
>> +{
>> +	struct txt_os_mle_data *os_mle_data;
>> +	struct slr_entry_log_info *log_info;
>> +	struct slr_table *slrt;
>> +	u8 *jmp_offset;
>> +	u32 size;
>> +
>> +	os_mle_data = txt_early_get_heap_table(txt, TXT_OS_MLE_DATA_TABLE,
>> +					       sizeof(*os_mle_data));
>> +
>> +	ap_wake_info.ap_wake_block = os_mle_data->ap_wake_block;
>> +	ap_wake_info.ap_wake_block_size = os_mle_data->ap_wake_block_size;
>> +
>> +	jmp_offset = os_mle_data->mle_scratch + SL_SCRATCH_AP_JMP_OFFSET;
>> +	ap_wake_info.ap_jmp_offset = *((u32 *)jmp_offset);
>> +
>> +	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, sizeof(*slrt));
>> +	if (!slrt)
>> +		slaunch_txt_reset(txt,
>> +			"Error early_memremap of SLRT failed\n",
>> +			SL_ERROR_SLRT_MAP);
>> +
>> +	size = slrt->size;
>> +	early_memunmap(slrt, sizeof(*slrt));
>> +
>> +	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, size);
>> +	if (!slrt)
>> +		slaunch_txt_reset(txt,
>> +			"Error early_memremap of SLRT failed\n",
>> +			SL_ERROR_SLRT_MAP);
>> +
>> +	log_info = (struct slr_entry_log_info *)
>> +		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
>> +
>> +	if (!log_info)
>> +		slaunch_txt_reset(txt,
>> +				  "SLRT missing logging info entry\n",
>> +				  SL_ERROR_SLRT_MISSING_ENTRY);
>> +
>> +	evtlog_addr = log_info->addr;
>> +	evtlog_size = log_info->size;
>> +
>> +	early_memunmap(slrt, size);
>> +
>> +	txt_early_put_heap_table(os_mle_data, sizeof(*os_mle_data));
>> +}
>> +
>> +/*
>> + * Intel TXT specific late stub setup and validation.
>> + */
>> +void __init slaunch_setup_txt(void)
>> +{
>> +	u64 one = TXT_REGVALUE_ONE, val;
>> +	void __iomem *txt;
>> +
>> +	if (!boot_cpu_has(X86_FEATURE_SMX))
>> +		return;
>> +
>> +	/*
>> +	 * If booted through secure launch entry point, the loadflags
>> +	 * option will be set.
>> +	 */
>> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
>> +		return;
>> +
>> +	/*
>> +	 * See if SENTER was done by reading the status register in the
>> +	 * public space. If the public register space cannot be read, TXT may
>> +	 * be disabled.
>> +	 */
>> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
>> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +	if (!txt)
>> +		return;
>> +
>> +	memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
>> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +
>> +	/* SENTER should have been done */
>> +	if (!(val & TXT_SENTER_DONE_STS))
>> +		panic("Error TXT.STS SENTER_DONE not set\n");
>> +
>> +	/* SEXIT should have been cleared */
>> +	if (val & TXT_SEXIT_DONE_STS)
>> +		panic("Error TXT.STS SEXIT_DONE set\n");
>> +
>> +	/* Now we want to use the private register space */
>> +	txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
>> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +	if (!txt) {
>> +		/* This is really bad, no where to go from here */
>> +		panic("Error early_ioremap of TXT priv registers\n");
>> +	}
>> +
>> +	/*
>> +	 * Try to read the Intel VID from the TXT private registers to see if
>> +	 * TXT measured launch happened properly and the private space is
>> +	 * available.
>> +	 */
>> +	memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
>> +	if ((val & 0xffff) != 0x8086) {
>> +		/*
>> +		 * Can't do a proper TXT reset since it appears something is
>> +		 * wrong even though SENTER happened and it should be in SMX
>> +		 * mode.
>> +		 */
>> +		panic("Invalid TXT vendor ID, not in SMX mode\n");
>> +	}
>> +
>> +	/* Set flags so subsequent code knows the status of the launch */
>> +	sl_flags |= (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT);
>> +
>> +	/*
>> +	 * Reading the proper DIDVID from the private register space means we
>> +	 * are in SMX mode and private registers are open for read/write.
>> +	 */
>> +
>> +	/* On Intel, have to handle TPM localities via TXT */
>> +	memcpy_toio(txt + TXT_CR_CMD_SECRETS, &one, sizeof(one));
>> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
>> +	memcpy_toio(txt + TXT_CR_CMD_OPEN_LOCALITY1, &one, sizeof(one));
>> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
>> +
>> +	slaunch_fetch_values(txt);
>> +
>> +	slaunch_verify_pmrs(txt);
>> +
>> +	slaunch_txt_reserve(txt);
>> +
>> +	slaunch_copy_dmar_table(txt);
>> +
>> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +
>> +	pr_info("Intel TXT setup complete\n");
>> +}
>> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
>> index a3414af..5d1ac8d 100644
>> --- a/drivers/iommu/intel/dmar.c
>> +++ b/drivers/iommu/intel/dmar.c
>> @@ -28,6 +28,7 @@
>>   #include <linux/iommu.h>
>>   #include <linux/numa.h>
>>   #include <linux/limits.h>
>> +#include <linux/slaunch.h>
>>   #include <asm/irq_remapping.h>
>>   
>>   #include "iommu.h"
>> @@ -660,6 +661,9 @@ static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar,
>>   	 */
>>   	dmar_tbl = tboot_get_dmar_table(dmar_tbl);
>>   
>> +	/* If Secure Launch is active, it has similar logic */
>> +	dmar_tbl = slaunch_get_dmar_table(dmar_tbl);
>> +
>>   	dmar = (struct acpi_table_dmar *)dmar_tbl;
>>   	if (!dmar)
>>   		return -ENODEV;
>> -- 
>> 1.8.3.1
> 
> Is it possible to test TXT in QEMU? Never done it so that's why I'm
> asking.

I would be if emulation of the GETSEC leaf functions were added to QEMU. 
AFAIK there is no public implementation of this at present.

Thanks
Ross

> 
> BR, Jarkko
> 


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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
@ 2023-05-12 15:58       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-12 15:58 UTC (permalink / raw)
  To: Jarkko Sakkinen, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel, Ross Philipson

On 5/10/23 19:02, Jarkko Sakkinen wrote:
> On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
>> The routine slaunch_setup is called out of the x86 specific setup_arch
>> routine during early kernel boot. After determining what platform is
>> present, various operations specific to that platform occur. This
>> includes finalizing setting for the platform late launch and verifying
>> that memory protections are in place.
>>
>> For TXT, this code also reserves the original compressed kernel setup
>> area where the APs were left looping so that this memory cannot be used.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   arch/x86/kernel/Makefile   |   1 +
>>   arch/x86/kernel/setup.c    |   3 +
>>   arch/x86/kernel/slaunch.c  | 497 +++++++++++++++++++++++++++++++++++++++++++++
>>   drivers/iommu/intel/dmar.c |   4 +
>>   4 files changed, 505 insertions(+)
>>   create mode 100644 arch/x86/kernel/slaunch.c
>>
>> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
>> index dd61752..3d2a33e 100644
>> --- a/arch/x86/kernel/Makefile
>> +++ b/arch/x86/kernel/Makefile
>> @@ -72,6 +72,7 @@ obj-$(CONFIG_X86_32)		+= tls.o
>>   obj-$(CONFIG_IA32_EMULATION)	+= tls.o
>>   obj-y				+= step.o
>>   obj-$(CONFIG_INTEL_TXT)		+= tboot.o
>> +obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
>>   obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
>>   obj-y				+= stacktrace.o
>>   obj-y				+= cpu/
>> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
>> index 16babff..592c09e 100644
>> --- a/arch/x86/kernel/setup.c
>> +++ b/arch/x86/kernel/setup.c
>> @@ -21,6 +21,7 @@
>>   #include <linux/root_dev.h>
>>   #include <linux/hugetlb.h>
>>   #include <linux/tboot.h>
>> +#include <linux/slaunch.h>
> 
> Only because of pure curiosity: what made you choose this location in
> the middle for the new include? :-)

Only because Secure Launch is like TBOOT. No other real reason.

> 
>>   #include <linux/usb/xhci-dbgp.h>
>>   #include <linux/static_call.h>
>>   #include <linux/swiotlb.h>
>> @@ -1063,6 +1064,8 @@ void __init setup_arch(char **cmdline_p)
>>   	early_gart_iommu_check();
>>   #endif
>>   
>> +	slaunch_setup_txt();
>> +
>>   	/*
>>   	 * partially used pages are not usable - thus
>>   	 * we are rounding upwards:
>> diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
>> new file mode 100644
>> index 0000000..7dba088
>> --- /dev/null
>> +++ b/arch/x86/kernel/slaunch.c
>> @@ -0,0 +1,497 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Secure Launch late validation/setup and finalization support.
>> + *
>> + * Copyright (c) 2022, Oracle and/or its affiliates.
>> + */
>> +
>> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>> +
>> +#include <linux/linkage.h>
>> +#include <linux/mm.h>
>> +#include <linux/io.h>
>> +#include <linux/uaccess.h>
>> +#include <linux/security.h>
>> +#include <linux/memblock.h>
>> +#include <asm/segment.h>
>> +#include <asm/sections.h>
>> +#include <asm/tlbflush.h>
>> +#include <asm/e820/api.h>
>> +#include <asm/setup.h>
>> +#include <linux/slr_table.h>
>> +#include <linux/slaunch.h>
>> +
>> +static u32 sl_flags;
>> +static struct sl_ap_wake_info ap_wake_info;
>> +static u64 evtlog_addr;
>> +static u32 evtlog_size;
>> +static u64 vtd_pmr_lo_size;
>> +
>> +/* This should be plenty of room */
>> +static u8 txt_dmar[PAGE_SIZE] __aligned(16);
>> +
>> +u32 slaunch_get_flags(void)
>> +{
>> +	return sl_flags;
>> +}
>> +EXPORT_SYMBOL(slaunch_get_flags);
>> +
>> +struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
>> +{
>> +	return &ap_wake_info;
>> +}
>> +
>> +struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
>> +{
>> +	/* The DMAR is only stashed and provided via TXT on Intel systems */
>> +	if (memcmp(txt_dmar, "DMAR", 4))
>> +		return dmar;
>> +
>> +	return (struct acpi_table_header *)(&txt_dmar[0]);
>> +}
>> +
>> +void __noreturn slaunch_txt_reset(void __iomem *txt,
>> +				  const char *msg, u64 error)
>> +{
>> +	u64 one = 1, val;
>> +
>> +	pr_err("%s", msg);
>> +
>> +	/*
>> +	 * This performs a TXT reset with a sticky error code. The reads of
>> +	 * TXT_CR_E2STS act as barriers.
>> +	 */
>> +	memcpy_toio(txt + TXT_CR_ERRORCODE, &error, sizeof(error));
>> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
>> +	memcpy_toio(txt + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
>> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
>> +	memcpy_toio(txt + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
>> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
>> +	memcpy_toio(txt + TXT_CR_CMD_RESET, &one, sizeof(one));
>> +
>> +	for ( ; ; )
>> +		asm volatile ("hlt");
>> +
>> +	unreachable();
>> +}
>> +
>> +/*
>> + * The TXT heap is too big to map all at once with early_ioremap
>> + * so it is done a table at a time.
>> + */
>> +static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
>> +					     u32 bytes)
>> +{
>> +	u64 base, size, offset = 0;
>> +	void *heap;
>> +	int i;
>> +
>> +	if (type > TXT_SINIT_TABLE_MAX)
>> +		slaunch_txt_reset(txt,
>> +			"Error invalid table type for early heap walk\n",
>> +			SL_ERROR_HEAP_WALK);
> 
> Align with 'txt'.

Ack

> 
>> +
>> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
>> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
>> +
>> +	/* Iterate over heap tables looking for table of "type" */
>> +	for (i = 0; i < type; i++) {
>> +		base += offset;
>> +		heap = early_memremap(base, sizeof(u64));
>> +		if (!heap)
>> +			slaunch_txt_reset(txt,
>> +				"Error early_memremap of heap for heap walk\n",
>> +				SL_ERROR_HEAP_MAP);
>> +
>> +		offset = *((u64 *)heap);
>> +
>> +		/*
>> +		 * After the first iteration, any offset of zero is invalid and
>> +		 * implies the TXT heap is corrupted.
>> +		 */
>> +		if (!offset)
>> +			slaunch_txt_reset(txt,
>> +				"Error invalid 0 offset in heap walk\n",
>> +				SL_ERROR_HEAP_ZERO_OFFSET);
>> +
>> +		early_memunmap(heap, sizeof(u64));
>> +	}
>> +
>> +	/* Skip the size field at the head of each table */
>> +	base += sizeof(u64);
>> +	heap = early_memremap(base, bytes);
>> +	if (!heap)
>> +		slaunch_txt_reset(txt,
>> +				  "Error early_memremap of heap section\n",
>> +				  SL_ERROR_HEAP_MAP);
>> +
>> +	return heap;
>> +}
>> +
>> +static void __init txt_early_put_heap_table(void *addr, unsigned long size)
>> +{
>> +	early_memunmap(addr, size);
>> +}
>> +
>> +/*
>> + * TXT uses a special set of VTd registers to protect all of memory from DMA
>> + * until the IOMMU can be programmed to protect memory. There is the low
>> + * memory PMR that can protect all memory up to 4G. The high memory PRM can
>> + * be setup to protect all memory beyond 4Gb. Validate that these values cover
>> + * what is expected.
>> + */
>> +static void __init slaunch_verify_pmrs(void __iomem *txt)
>> +{
>> +	struct txt_os_sinit_data *os_sinit_data;
>> +	u32 field_offset, err = 0;
>> +	const char *errmsg = "";
>> +	unsigned long last_pfn;
>> +
>> +	field_offset = offsetof(struct txt_os_sinit_data, lcp_po_base);
>> +	os_sinit_data = txt_early_get_heap_table(txt, TXT_OS_SINIT_DATA_TABLE,
>> +						 field_offset);
>> +
>> +	/* Save a copy */
>> +	vtd_pmr_lo_size = os_sinit_data->vtd_pmr_lo_size;
>> +
>> +	last_pfn = e820__end_of_ram_pfn();
>> +
>> +	/*
>> +	 * First make sure the hi PMR covers all memory above 4G. In the
>> +	 * unlikely case where there is < 4G on the system, the hi PMR will
>> +	 * not be set.
>> +	 */
>> +	if (os_sinit_data->vtd_pmr_hi_base != 0x0ULL) {
>> +		if (os_sinit_data->vtd_pmr_hi_base != 0x100000000ULL) {
>> +			err = SL_ERROR_HI_PMR_BASE;
>> +			errmsg =  "Error hi PMR base\n";
>> +			goto out;
>> +		}
>> +
>> +		if (PFN_PHYS(last_pfn) > os_sinit_data->vtd_pmr_hi_base +
>> +		    os_sinit_data->vtd_pmr_hi_size) {
>> +			err = SL_ERROR_HI_PMR_SIZE;
>> +			errmsg = "Error hi PMR size\n";
>> +			goto out;
>> +		}
>> +	}
>> +
>> +	/*
>> +	 * Lo PMR base should always be 0. This was already checked in
>> +	 * early stub.
>> +	 */
>> +
>> +	/*
>> +	 * Check that if the kernel was loaded below 4G, that it is protected
>> +	 * by the lo PMR. Note this is the decompressed kernel. The ACM would
>> +	 * have ensured the compressed kernel (the MLE image) was protected.
>> +	 */
>> +	if ((__pa_symbol(_end) < 0x100000000ULL) &&
>> +	    (__pa_symbol(_end) > os_sinit_data->vtd_pmr_lo_size)) {
>> +		err = SL_ERROR_LO_PMR_MLE;
>> +		errmsg = "Error lo PMR does not cover MLE kernel\n";
>> +	}
>> +
>> +	/*
>> +	 * Other regions of interest like boot param, AP wake block, cmdline
>> +	 * already checked for PMR coverage in the early stub code.
>> +	 */
>> +
>> +out:
>> +	txt_early_put_heap_table(os_sinit_data, field_offset);
>> +
>> +	if (err)
>> +		slaunch_txt_reset(txt, errmsg, err);
>> +}
>> +
>> +static void __init slaunch_txt_reserve_range(u64 base, u64 size)
>> +{
>> +	int type;
>> +
>> +	type = e820__get_entry_type(base, base + size - 1);
>> +	if (type == E820_TYPE_RAM) {
>> +		pr_info("memblock reserve base: %llx size: %llx\n", base, size);
>> +		memblock_reserve(base, size);
>> +	}
>> +}
>> +
>> +/*
>> + * For Intel, certain regions of memory must be marked as reserved by putting
>> + * them on the memblock reserved list if they are not already e820 reserved.
>> + * This includes:
>> + *  - The TXT HEAP
>> + *  - The ACM area
>> + *  - The TXT private register bank
>> + *  - The MDR list sent to the MLE by the ACM (see TXT specification)
>> + *  (Normally the above are properly reserved by firmware but if it was not
>> + *  done, reserve them now)
>> + *  - The AP wake block
>> + *  - TPM log external to the TXT heap
>> + *
>> + * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
>> + * the low PMR must be reservered too.
>> + */
>> +static void __init slaunch_txt_reserve(void __iomem *txt)
>> +{
>> +	struct txt_sinit_memory_descriptor_record *mdr;
>> +	struct txt_sinit_mle_data *sinit_mle_data;
>> +	u64 base, size, heap_base, heap_size;
>> +	u32 mdrnum, mdroffset, mdrslen;
>> +	u32 field_offset, i;
>> +	void *mdrs;
>> +
>> +	base = TXT_PRIV_CONFIG_REGS_BASE;
>> +	size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
>> +	slaunch_txt_reserve_range(base, size);
>> +
>> +	memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
>> +	memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
>> +	slaunch_txt_reserve_range(heap_base, heap_size);
>> +
>> +	memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
>> +	memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
>> +	slaunch_txt_reserve_range(base, size);
>> +
>> +	field_offset = offsetof(struct txt_sinit_mle_data,
>> +				sinit_vtd_dmar_table_size);
>> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +						  field_offset);
>> +
>> +	mdrnum = sinit_mle_data->num_of_sinit_mdrs;
>> +	mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
>> +
>> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
>> +
>> +	if (!mdrnum)
>> +		goto nomdr;
>> +
>> +	mdrslen = mdrnum * sizeof(struct txt_sinit_memory_descriptor_record);
>> +
>> +	mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +					mdroffset + mdrslen - 8);
>> +
>> +	mdr = mdrs + mdroffset - 8;
>> +
>> +	for (i = 0; i < mdrnum; i++, mdr++) {
>> +		/* Spec says some entries can have length 0, ignore them */
>> +		if (mdr->type > 0 && mdr->length > 0)
>> +			slaunch_txt_reserve_range(mdr->address, mdr->length);
>> +	}
>> +
>> +	txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
>> +
>> +nomdr:
>> +	slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
>> +				  ap_wake_info.ap_wake_block_size);
>> +
>> +	/*
>> +	 * Earlier checks ensured that the event log was properly situated
>> +	 * either inside the TXT heap or outside. This is a check to see if the
>> +	 * event log needs to be reserved. If it is in the TXT heap, it is
>> +	 * already reserved.
>> +	 */
>> +	if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
>> +		slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
>> +
>> +	for (i = 0; i < e820_table->nr_entries; i++) {
>> +		base = e820_table->entries[i].addr;
>> +		size = e820_table->entries[i].size;
>> +		if ((base >= vtd_pmr_lo_size) && (base < 0x100000000ULL))
>> +			slaunch_txt_reserve_range(base, size);
>> +		else if ((base < vtd_pmr_lo_size) &&
>> +			 (base + size > vtd_pmr_lo_size))
>> +			slaunch_txt_reserve_range(vtd_pmr_lo_size,
>> +						  base + size - vtd_pmr_lo_size);
>> +	}
>> +}
>> +
>> +/*
>> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
>> + * It is stored in the TXT heap. Fetch it from there and make it available
>> + * to the IOMMU driver.
>> + */
>> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
>> +{
>> +	struct txt_sinit_mle_data *sinit_mle_data;
>> +	u32 field_offset, dmar_size, dmar_offset;
>> +	void *dmar;
>> +
>> +	memset(&txt_dmar, 0, PAGE_SIZE);
>> +
>> +	field_offset = offsetof(struct txt_sinit_mle_data,
>> +				processor_scrtm_status);
>> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +						  field_offset);
>> +
>> +	dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
>> +	dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
>> +
>> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
>> +
>> +	if (!dmar_size || !dmar_offset)
>> +		slaunch_txt_reset(txt,
>> +				  "Error invalid DMAR table values\n",
>> +				  SL_ERROR_HEAP_INVALID_DMAR);
>> +
>> +	if (unlikely(dmar_size > PAGE_SIZE))
>> +		slaunch_txt_reset(txt,
>> +				  "Error DMAR too big to store\n",
>> +				  SL_ERROR_HEAP_DMAR_SIZE);
>> +
>> +
>> +	dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
>> +					dmar_offset + dmar_size - 8);
>> +	if (!dmar)
>> +		slaunch_txt_reset(txt,
>> +				  "Error early_ioremap of DMAR\n",
>> +				  SL_ERROR_HEAP_DMAR_MAP);
>> +
>> +	memcpy(&txt_dmar[0], dmar + dmar_offset - 8, dmar_size);
>> +
>> +	txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
>> +}
>> +
>> +/*
>> + * The location of the safe AP wake code block is stored in the TXT heap.
>> + * Fetch needed values here in the early init code for later use in SMP
>> + * startup.
>> + *
>> + * Also get the TPM event log values are in the SLRT and have to be fetched.
>> + * They will be put on the memblock reserve list later.
>> + */
>> +static void __init slaunch_fetch_values(void __iomem *txt)
>> +{
>> +	struct txt_os_mle_data *os_mle_data;
>> +	struct slr_entry_log_info *log_info;
>> +	struct slr_table *slrt;
>> +	u8 *jmp_offset;
>> +	u32 size;
>> +
>> +	os_mle_data = txt_early_get_heap_table(txt, TXT_OS_MLE_DATA_TABLE,
>> +					       sizeof(*os_mle_data));
>> +
>> +	ap_wake_info.ap_wake_block = os_mle_data->ap_wake_block;
>> +	ap_wake_info.ap_wake_block_size = os_mle_data->ap_wake_block_size;
>> +
>> +	jmp_offset = os_mle_data->mle_scratch + SL_SCRATCH_AP_JMP_OFFSET;
>> +	ap_wake_info.ap_jmp_offset = *((u32 *)jmp_offset);
>> +
>> +	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, sizeof(*slrt));
>> +	if (!slrt)
>> +		slaunch_txt_reset(txt,
>> +			"Error early_memremap of SLRT failed\n",
>> +			SL_ERROR_SLRT_MAP);
>> +
>> +	size = slrt->size;
>> +	early_memunmap(slrt, sizeof(*slrt));
>> +
>> +	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, size);
>> +	if (!slrt)
>> +		slaunch_txt_reset(txt,
>> +			"Error early_memremap of SLRT failed\n",
>> +			SL_ERROR_SLRT_MAP);
>> +
>> +	log_info = (struct slr_entry_log_info *)
>> +		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
>> +
>> +	if (!log_info)
>> +		slaunch_txt_reset(txt,
>> +				  "SLRT missing logging info entry\n",
>> +				  SL_ERROR_SLRT_MISSING_ENTRY);
>> +
>> +	evtlog_addr = log_info->addr;
>> +	evtlog_size = log_info->size;
>> +
>> +	early_memunmap(slrt, size);
>> +
>> +	txt_early_put_heap_table(os_mle_data, sizeof(*os_mle_data));
>> +}
>> +
>> +/*
>> + * Intel TXT specific late stub setup and validation.
>> + */
>> +void __init slaunch_setup_txt(void)
>> +{
>> +	u64 one = TXT_REGVALUE_ONE, val;
>> +	void __iomem *txt;
>> +
>> +	if (!boot_cpu_has(X86_FEATURE_SMX))
>> +		return;
>> +
>> +	/*
>> +	 * If booted through secure launch entry point, the loadflags
>> +	 * option will be set.
>> +	 */
>> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
>> +		return;
>> +
>> +	/*
>> +	 * See if SENTER was done by reading the status register in the
>> +	 * public space. If the public register space cannot be read, TXT may
>> +	 * be disabled.
>> +	 */
>> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
>> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +	if (!txt)
>> +		return;
>> +
>> +	memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
>> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +
>> +	/* SENTER should have been done */
>> +	if (!(val & TXT_SENTER_DONE_STS))
>> +		panic("Error TXT.STS SENTER_DONE not set\n");
>> +
>> +	/* SEXIT should have been cleared */
>> +	if (val & TXT_SEXIT_DONE_STS)
>> +		panic("Error TXT.STS SEXIT_DONE set\n");
>> +
>> +	/* Now we want to use the private register space */
>> +	txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
>> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +	if (!txt) {
>> +		/* This is really bad, no where to go from here */
>> +		panic("Error early_ioremap of TXT priv registers\n");
>> +	}
>> +
>> +	/*
>> +	 * Try to read the Intel VID from the TXT private registers to see if
>> +	 * TXT measured launch happened properly and the private space is
>> +	 * available.
>> +	 */
>> +	memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
>> +	if ((val & 0xffff) != 0x8086) {
>> +		/*
>> +		 * Can't do a proper TXT reset since it appears something is
>> +		 * wrong even though SENTER happened and it should be in SMX
>> +		 * mode.
>> +		 */
>> +		panic("Invalid TXT vendor ID, not in SMX mode\n");
>> +	}
>> +
>> +	/* Set flags so subsequent code knows the status of the launch */
>> +	sl_flags |= (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT);
>> +
>> +	/*
>> +	 * Reading the proper DIDVID from the private register space means we
>> +	 * are in SMX mode and private registers are open for read/write.
>> +	 */
>> +
>> +	/* On Intel, have to handle TPM localities via TXT */
>> +	memcpy_toio(txt + TXT_CR_CMD_SECRETS, &one, sizeof(one));
>> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
>> +	memcpy_toio(txt + TXT_CR_CMD_OPEN_LOCALITY1, &one, sizeof(one));
>> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
>> +
>> +	slaunch_fetch_values(txt);
>> +
>> +	slaunch_verify_pmrs(txt);
>> +
>> +	slaunch_txt_reserve(txt);
>> +
>> +	slaunch_copy_dmar_table(txt);
>> +
>> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +
>> +	pr_info("Intel TXT setup complete\n");
>> +}
>> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
>> index a3414af..5d1ac8d 100644
>> --- a/drivers/iommu/intel/dmar.c
>> +++ b/drivers/iommu/intel/dmar.c
>> @@ -28,6 +28,7 @@
>>   #include <linux/iommu.h>
>>   #include <linux/numa.h>
>>   #include <linux/limits.h>
>> +#include <linux/slaunch.h>
>>   #include <asm/irq_remapping.h>
>>   
>>   #include "iommu.h"
>> @@ -660,6 +661,9 @@ static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar,
>>   	 */
>>   	dmar_tbl = tboot_get_dmar_table(dmar_tbl);
>>   
>> +	/* If Secure Launch is active, it has similar logic */
>> +	dmar_tbl = slaunch_get_dmar_table(dmar_tbl);
>> +
>>   	dmar = (struct acpi_table_dmar *)dmar_tbl;
>>   	if (!dmar)
>>   		return -ENODEV;
>> -- 
>> 1.8.3.1
> 
> Is it possible to test TXT in QEMU? Never done it so that's why I'm
> asking.

I would be if emulation of the GETSEC leaf functions were added to QEMU. 
AFAIK there is no public implementation of this at present.

Thanks
Ross

> 
> BR, Jarkko
> 


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 05/14] x86: Secure Launch main header file
  2023-05-12 11:00     ` Matthew Garrett
@ 2023-05-12 16:10       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-12 16:10 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel, Ross Philipson

On 5/12/23 07:00, Matthew Garrett wrote:
> On Thu, May 04, 2023 at 02:50:14PM +0000, Ross Philipson wrote:
> 
>> +static inline int tpm12_log_event(void *evtlog_base, u32 evtlog_size,
>> +				  u32 event_size, void *event)
>> +{
>> +	struct tpm12_event_log_header *evtlog =
>> +		(struct tpm12_event_log_header *)evtlog_base;
>> +
>> +	if (memcmp(evtlog->signature, TPM12_EVTLOG_SIGNATURE,
>> +		   sizeof(TPM12_EVTLOG_SIGNATURE)))
>> +		return -EINVAL;
>> +
>> +	if (evtlog->container_size > evtlog_size)
>> +		return -EINVAL;
>> +
>> +	if (evtlog->next_event_offset + event_size > evtlog->container_size)
>> +		return -E2BIG;
>> +
>> +	memcpy(evtlog_base + evtlog->next_event_offset, event, event_size);
>> +	evtlog->next_event_offset += event_size;
>> +
>> +	return 0;
>> +}
>> +
>> +static inline int tpm20_log_event(struct txt_heap_event_log_pointer2_1_element *elem,
>> +				  void *evtlog_base, u32 evtlog_size,
>> +				  u32 event_size, void *event)
>> +{
>> +	struct tcg_pcr_event *header =
>> +		(struct tcg_pcr_event *)evtlog_base;
>> +
>> +	/* Has to be at least big enough for the signature */
>> +	if (header->event_size < sizeof(TCG_SPECID_SIG))
>> +		return -EINVAL;
>> +
>> +	if (memcmp((u8 *)header + sizeof(struct tcg_pcr_event),
>> +		   TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
>> +		return -EINVAL;
>> +
>> +	if (elem->allocated_event_container_size > evtlog_size)
>> +		return -EINVAL;
>> +
>> +	if (elem->next_record_offset + event_size >
>> +	    elem->allocated_event_container_size)
>> +		return -E2BIG;
>> +
>> +	memcpy(evtlog_base + elem->next_record_offset, event, event_size);
>> +	elem->next_record_offset += event_size;
>> +
>> +	return 0;
>> +}
>> +
> 
> These seem like they'd potentially be useful outside the context of SL,
> maybe put them in a more generic location? Very much a nice to have, not
> a blocker from my side.

Yea we can look into finding a nice home somewhere in the TPM event log 
code for these.

> 
>> +/*
>> + * External functions avalailable in mainline kernel.
> 
> Nit: "available"

Ack

Thanks

> 


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

* Re: [PATCH v6 05/14] x86: Secure Launch main header file
@ 2023-05-12 16:10       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-12 16:10 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel, Ross Philipson

On 5/12/23 07:00, Matthew Garrett wrote:
> On Thu, May 04, 2023 at 02:50:14PM +0000, Ross Philipson wrote:
> 
>> +static inline int tpm12_log_event(void *evtlog_base, u32 evtlog_size,
>> +				  u32 event_size, void *event)
>> +{
>> +	struct tpm12_event_log_header *evtlog =
>> +		(struct tpm12_event_log_header *)evtlog_base;
>> +
>> +	if (memcmp(evtlog->signature, TPM12_EVTLOG_SIGNATURE,
>> +		   sizeof(TPM12_EVTLOG_SIGNATURE)))
>> +		return -EINVAL;
>> +
>> +	if (evtlog->container_size > evtlog_size)
>> +		return -EINVAL;
>> +
>> +	if (evtlog->next_event_offset + event_size > evtlog->container_size)
>> +		return -E2BIG;
>> +
>> +	memcpy(evtlog_base + evtlog->next_event_offset, event, event_size);
>> +	evtlog->next_event_offset += event_size;
>> +
>> +	return 0;
>> +}
>> +
>> +static inline int tpm20_log_event(struct txt_heap_event_log_pointer2_1_element *elem,
>> +				  void *evtlog_base, u32 evtlog_size,
>> +				  u32 event_size, void *event)
>> +{
>> +	struct tcg_pcr_event *header =
>> +		(struct tcg_pcr_event *)evtlog_base;
>> +
>> +	/* Has to be at least big enough for the signature */
>> +	if (header->event_size < sizeof(TCG_SPECID_SIG))
>> +		return -EINVAL;
>> +
>> +	if (memcmp((u8 *)header + sizeof(struct tcg_pcr_event),
>> +		   TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
>> +		return -EINVAL;
>> +
>> +	if (elem->allocated_event_container_size > evtlog_size)
>> +		return -EINVAL;
>> +
>> +	if (elem->next_record_offset + event_size >
>> +	    elem->allocated_event_container_size)
>> +		return -E2BIG;
>> +
>> +	memcpy(evtlog_base + elem->next_record_offset, event, event_size);
>> +	elem->next_record_offset += event_size;
>> +
>> +	return 0;
>> +}
>> +
> 
> These seem like they'd potentially be useful outside the context of SL,
> maybe put them in a more generic location? Very much a nice to have, not
> a blocker from my side.

Yea we can look into finding a nice home somewhere in the TPM event log 
code for these.

> 
>> +/*
>> + * External functions avalailable in mainline kernel.
> 
> Nit: "available"

Ack

Thanks

> 


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-12 13:24             ` Thomas Gleixner
@ 2023-05-12 16:13               ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 16:13 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Ard Biesheuvel, Eric Biggers, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi, dpsmith, mingo, bp, hpa, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On Fri, May 12, 2023 at 03:24:04PM +0200, Thomas Gleixner wrote:
> On Fri, May 12 2023 at 12:28, Matthew Garrett wrote:
> > Unless we assert that SHA-1 events are unsupported, it seems a bit odd 
> > to force a policy on people who have both banks enabled. People with 
> > mixed fleets are potentially going to be dealing with SHA-1 measurements 
> > for a while yet, and while there's obviously a security benefit in using 
> > SHA-2 instead it'd be irritating to have to maintain two attestation 
> > policies.
> 
> Why?
> 
> If you have a mixed fleet then it's not too much asked to provide two
> data sets. On a TPM2 system you can enforce SHA-2 and only fallback to
> SHA-1 on TPM 1.2 hardware. No?

No, beause having TPM2 hardware doesn't guarantee that your firmware 
enables SHA-2 (which also means this is something that could change with 
firmware updates, which means that refusing to support SHA-1 if the 
SHA-2 banks are enabled could result in an entirely different policy 
being required (and plausibly one that isn't implemented in their 
existing tooling)

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-12 16:13               ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 16:13 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Ard Biesheuvel, Eric Biggers, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi, dpsmith, mingo, bp, hpa, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On Fri, May 12, 2023 at 03:24:04PM +0200, Thomas Gleixner wrote:
> On Fri, May 12 2023 at 12:28, Matthew Garrett wrote:
> > Unless we assert that SHA-1 events are unsupported, it seems a bit odd 
> > to force a policy on people who have both banks enabled. People with 
> > mixed fleets are potentially going to be dealing with SHA-1 measurements 
> > for a while yet, and while there's obviously a security benefit in using 
> > SHA-2 instead it'd be irritating to have to maintain two attestation 
> > policies.
> 
> Why?
> 
> If you have a mixed fleet then it's not too much asked to provide two
> data sets. On a TPM2 system you can enforce SHA-2 and only fallback to
> SHA-1 on TPM 1.2 hardware. No?

No, beause having TPM2 hardware doesn't guarantee that your firmware 
enables SHA-2 (which also means this is something that could change with 
firmware updates, which means that refusing to support SHA-1 if the 
SHA-2 banks are enabled could result in an entirely different policy 
being required (and plausibly one that isn't implemented in their 
existing tooling)

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-12 11:26     ` Matthew Garrett
@ 2023-05-12 16:17       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-12 16:17 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel, Ross Philipson

On 5/12/23 07:26, Matthew Garrett wrote:
> On Thu, May 04, 2023 at 02:50:16PM +0000, Ross Philipson wrote:
> 
>> +static void sl_find_event_log(struct slr_table *slrt)
> 
> If this is called after the EFI stub then we're presumably
> post-ExitBootServices and we're copied the TPM event log into a
> configuration table so it's available to the runtime kernel. That also
> means that we should be adding all further measurements to the Final
> Events Table rather than the initial event log. How's that handled here,
> both in terms of ensuring further events (generated by firmware or by
> us) get added to the right place, and in terms of ensuring the event
> logs the kernel has later on were covered appropriately? Or is the SL
> event log an entirely different thing that can be merged in later
> because it only covers the DRTM PCRs?

This is a good point. At this point it is really something we 
overlooked. We will have to revisit this and figure out the best way to 
find the final event log depending on how things booted.

> 
>> +static void sl_extend_setup_data(struct slr_policy_entry *entry)
>> +{
>> +	struct setup_data *data;
>> +
>> +	/*
>> +	 * Measuring the boot params measured the fixed e820 memory map.
>> +	 * Measure any setup_data entries including e820 extended entries.
>> +	 */
>> +	data = (struct setup_data *)(unsigned long)entry->entity;
>> +	while (data)
>> +		data = sl_handle_setup_data(data, entry);
>> +}
> 
> Is e820 sufficient here? There are cases where we use the EFI memory map
> directly (sorry), but I don't know if any of them are relevant to DRTM
> outcomes.

I am not 100% sure what you are asking but we also measure the EFI 
memory map. This comment is just to note that if the e820 exceeded the 
space in the fixed map in boot parameters, we would pick up any extra 
entries when measuring the setup_data list.

Thanks
Ross

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-05-12 16:17       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-12 16:17 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel, Ross Philipson

On 5/12/23 07:26, Matthew Garrett wrote:
> On Thu, May 04, 2023 at 02:50:16PM +0000, Ross Philipson wrote:
> 
>> +static void sl_find_event_log(struct slr_table *slrt)
> 
> If this is called after the EFI stub then we're presumably
> post-ExitBootServices and we're copied the TPM event log into a
> configuration table so it's available to the runtime kernel. That also
> means that we should be adding all further measurements to the Final
> Events Table rather than the initial event log. How's that handled here,
> both in terms of ensuring further events (generated by firmware or by
> us) get added to the right place, and in terms of ensuring the event
> logs the kernel has later on were covered appropriately? Or is the SL
> event log an entirely different thing that can be merged in later
> because it only covers the DRTM PCRs?

This is a good point. At this point it is really something we 
overlooked. We will have to revisit this and figure out the best way to 
find the final event log depending on how things booted.

> 
>> +static void sl_extend_setup_data(struct slr_policy_entry *entry)
>> +{
>> +	struct setup_data *data;
>> +
>> +	/*
>> +	 * Measuring the boot params measured the fixed e820 memory map.
>> +	 * Measure any setup_data entries including e820 extended entries.
>> +	 */
>> +	data = (struct setup_data *)(unsigned long)entry->entity;
>> +	while (data)
>> +		data = sl_handle_setup_data(data, entry);
>> +}
> 
> Is e820 sufficient here? There are cases where we use the EFI memory map
> directly (sorry), but I don't know if any of them are relevant to DRTM
> outcomes.

I am not 100% sure what you are asking but we also measure the EFI 
memory map. This comment is just to note that if the e820 exceeded the 
space in the fixed map in boot parameters, we would pick up any extra 
entries when measuring the setup_data list.

Thanks
Ross

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 13/14] tpm: Allow locality 2 to be set when initializing the TPM for Secure Launch
  2023-05-12 11:43     ` Matthew Garrett
@ 2023-05-12 16:22       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-12 16:22 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel, Ross Philipson

On 5/12/23 07:43, Matthew Garrett wrote:
> On Thu, May 04, 2023 at 02:50:22PM +0000, Ross Philipson wrote:
>> The Secure Launch MLE environment uses PCRs that are only accessible from
>> the DRTM locality 2. By default the TPM drivers always initialize the
>> locality to 0. When a Secure Launch is in progress, initialize the
>> locality to 2.
> 
> This looks correct in itself, but looking at the CRB driver code I don't
> think locality support is actually implemented. Are there any SL systems
> using CRB?

We have never seen a system that supports CRB other than some firmware 
TPMs that don't work with TXT in the first place. CRB is unexplored 
territory at this point.

Thanks
Ross

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

* Re: [PATCH v6 13/14] tpm: Allow locality 2 to be set when initializing the TPM for Secure Launch
@ 2023-05-12 16:22       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-12 16:22 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel, Ross Philipson

On 5/12/23 07:43, Matthew Garrett wrote:
> On Thu, May 04, 2023 at 02:50:22PM +0000, Ross Philipson wrote:
>> The Secure Launch MLE environment uses PCRs that are only accessible from
>> the DRTM locality 2. By default the TPM drivers always initialize the
>> locality to 0. When a Secure Launch is in progress, initialize the
>> locality to 2.
> 
> This looks correct in itself, but looking at the CRB driver code I don't
> think locality support is actually implemented. Are there any SL systems
> using CRB?

We have never seen a system that supports CRB other than some firmware 
TPMs that don't work with TXT in the first place. CRB is unexplored 
territory at this point.

Thanks
Ross

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-12 16:17       ` Ross Philipson
@ 2023-05-12 16:27         ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 16:27 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, May 12, 2023 at 12:17:50PM -0400, Ross Philipson wrote:

> I am not 100% sure what you are asking but we also measure the EFI memory
> map. This comment is just to note that if the e820 exceeded the space in the
> fixed map in boot parameters, we would pick up any extra entries when
> measuring the setup_data list.

Ack, picked this up in a later patch but didn't come back to follow up. 
Thanks!

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-05-12 16:27         ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 16:27 UTC (permalink / raw)
  To: Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, May 12, 2023 at 12:17:50PM -0400, Ross Philipson wrote:

> I am not 100% sure what you are asking but we also measure the EFI memory
> map. This comment is just to note that if the e820 exceeded the space in the
> fixed map in boot parameters, we would pick up any extra entries when
> measuring the setup_data list.

Ack, picked this up in a later patch but didn't come back to follow up. 
Thanks!

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 09/14] x86: Secure Launch SMP bringup support
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-12 18:02     ` Thomas Gleixner
  -1 siblings, 0 replies; 200+ messages in thread
From: Thomas Gleixner @ 2023-05-12 18:02 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
>  
> +#ifdef CONFIG_SECURE_LAUNCH
> +
> +static atomic_t first_ap_only = {1};

ATOMIC_INIT(1) if at all.

> +
> +/*
> + * Called to fix the long jump address for the waiting APs to vector to
> + * the correct startup location in the Secure Launch stub in the rmpiggy.
> + */
> +static int
> +slaunch_fixup_jump_vector(void)

One line please.

> +{
> +	struct sl_ap_wake_info *ap_wake_info;
> +	u32 *ap_jmp_ptr = NULL;
> +
> +	if (!atomic_dec_and_test(&first_ap_only))
> +		return 0;

Why does this need an atomic? CPU bringup is fully serialized and even
with the upcoming parallel bootup work, there is no concurrency on this
function.

Aside of that. Why isn't this initialized during boot in a __init function?

> +	ap_wake_info = slaunch_get_ap_wake_info();
> +
> +	ap_jmp_ptr = (u32 *)__va(ap_wake_info->ap_wake_block +
> +				 ap_wake_info->ap_jmp_offset);
> +
> +	*ap_jmp_ptr = real_mode_header->sl_trampoline_start32;
> +
> +	pr_debug("TXT AP long jump address updated\n");
> +
> +	return 0;

Why does this need a return code of all return paths return 0?

> +}
> +
> +/*
> + * TXT AP startup is quite different than normal. The APs cannot have #INIT
> + * asserted on them or receive SIPIs. The early Secure Launch code has parked
> + * the APs in a pause loop waiting to receive an NMI. This will wake the APs
> + * and have them jump to the protected mode code in the rmpiggy where the rest
> + * of the SMP boot of the AP will proceed normally.
> + */
> +static int
> +slaunch_wakeup_cpu_from_txt(int cpu, int apicid)
> +{
> +	unsigned long send_status = 0, accept_status = 0;
> +
> +	/* Only done once */

Yes. But not here.

> +	if (slaunch_fixup_jump_vector())
> +		return -1;
> +
> +	/* Send NMI IPI to idling AP and wake it up */
> +	apic_icr_write(APIC_DM_NMI, apicid);
> +
> +	if (init_udelay == 0)
> +		udelay(10);
> +	else
> +		udelay(300);

The wonders of copy & pasta. This condition is pointless because this
code only runs on systems which force init_udelay to 0.

> +	send_status = safe_apic_wait_icr_idle();

Moar copy & pasta. As this is guaranteed to be X2APIC mode, this
function is a nop and returns 0 unconditionally.

> +	if (init_udelay == 0)
> +		udelay(10);
> +	else
> +		udelay(300);
> +
> +	accept_status = (apic_read(APIC_ESR) & 0xEF);

The point of this is? Bit 0-3 are Pentium and P6 only.

Bit 4 Tried to send low prio IPI but not supported
Bit 5 Illegal Vector sent
Bit 6 Illegal Vector received
Bit 7 X2APIC illegal register access

IOW, there is no accept error here. That would be bit 2 which is never set
on anything modern

But aside of that the read is moot anyway because the CPU has the APIC
error vector enabled so if this would happen the APIC error interrupt
would have swallowed and cleared the error condition.

IOW. Everything except the apic_icr_write() here is completely useless.

> +#else
> +
> +#define slaunch_wakeup_cpu_from_txt(cpu, apicid)	0

inline stub please. 

> +
> +#endif  /* !CONFIG_SECURE_LAUNCH */
> +
>  /*
>   * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
>   * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
> @@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>  	cpumask_clear_cpu(cpu, cpu_initialized_mask);
>  	smp_mb();
>  
> +	/* With Intel TXT, the AP startup is totally different */
> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==
> +	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {

Stick this condition into a helper function please

> +		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
> +		goto txt_wake;
> +	}
> +
>  	/*
>  	 * Wake up a CPU in difference cases:
>  	 * - Use a method from the APIC driver if one defined, with wakeup
> @@ -1147,6 +1232,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>  		boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
>  						     cpu0_nmi_registered);
>  
> +txt_wake:

Sorry, but what has this to do with TXT ? And why can't the above just
be yet another if clause in the existing if/else if maze?

Now that brings me to another question. How is this supposed to work
with CPU hotplug post boot?

It will simply not work at all because once a CPU is offlined it is
going to sit in an endless loop and wait for INIT/SIPI/SIPI. So it will
get that NMI and go back to wait.

So you need a TXT specific cpu_play_dead() implementation, which should
preferrably use monitor/mwait where each "offline" CPU sits and waits
until a condition becomes true. Then you don't need a NMI for wakeup at
all. Just writing the condition into that per CPU cache line should be
enough.

Thanks,

        tglx


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 09/14] x86: Secure Launch SMP bringup support
@ 2023-05-12 18:02     ` Thomas Gleixner
  0 siblings, 0 replies; 200+ messages in thread
From: Thomas Gleixner @ 2023-05-12 18:02 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
>  
> +#ifdef CONFIG_SECURE_LAUNCH
> +
> +static atomic_t first_ap_only = {1};

ATOMIC_INIT(1) if at all.

> +
> +/*
> + * Called to fix the long jump address for the waiting APs to vector to
> + * the correct startup location in the Secure Launch stub in the rmpiggy.
> + */
> +static int
> +slaunch_fixup_jump_vector(void)

One line please.

> +{
> +	struct sl_ap_wake_info *ap_wake_info;
> +	u32 *ap_jmp_ptr = NULL;
> +
> +	if (!atomic_dec_and_test(&first_ap_only))
> +		return 0;

Why does this need an atomic? CPU bringup is fully serialized and even
with the upcoming parallel bootup work, there is no concurrency on this
function.

Aside of that. Why isn't this initialized during boot in a __init function?

> +	ap_wake_info = slaunch_get_ap_wake_info();
> +
> +	ap_jmp_ptr = (u32 *)__va(ap_wake_info->ap_wake_block +
> +				 ap_wake_info->ap_jmp_offset);
> +
> +	*ap_jmp_ptr = real_mode_header->sl_trampoline_start32;
> +
> +	pr_debug("TXT AP long jump address updated\n");
> +
> +	return 0;

Why does this need a return code of all return paths return 0?

> +}
> +
> +/*
> + * TXT AP startup is quite different than normal. The APs cannot have #INIT
> + * asserted on them or receive SIPIs. The early Secure Launch code has parked
> + * the APs in a pause loop waiting to receive an NMI. This will wake the APs
> + * and have them jump to the protected mode code in the rmpiggy where the rest
> + * of the SMP boot of the AP will proceed normally.
> + */
> +static int
> +slaunch_wakeup_cpu_from_txt(int cpu, int apicid)
> +{
> +	unsigned long send_status = 0, accept_status = 0;
> +
> +	/* Only done once */

Yes. But not here.

> +	if (slaunch_fixup_jump_vector())
> +		return -1;
> +
> +	/* Send NMI IPI to idling AP and wake it up */
> +	apic_icr_write(APIC_DM_NMI, apicid);
> +
> +	if (init_udelay == 0)
> +		udelay(10);
> +	else
> +		udelay(300);

The wonders of copy & pasta. This condition is pointless because this
code only runs on systems which force init_udelay to 0.

> +	send_status = safe_apic_wait_icr_idle();

Moar copy & pasta. As this is guaranteed to be X2APIC mode, this
function is a nop and returns 0 unconditionally.

> +	if (init_udelay == 0)
> +		udelay(10);
> +	else
> +		udelay(300);
> +
> +	accept_status = (apic_read(APIC_ESR) & 0xEF);

The point of this is? Bit 0-3 are Pentium and P6 only.

Bit 4 Tried to send low prio IPI but not supported
Bit 5 Illegal Vector sent
Bit 6 Illegal Vector received
Bit 7 X2APIC illegal register access

IOW, there is no accept error here. That would be bit 2 which is never set
on anything modern

But aside of that the read is moot anyway because the CPU has the APIC
error vector enabled so if this would happen the APIC error interrupt
would have swallowed and cleared the error condition.

IOW. Everything except the apic_icr_write() here is completely useless.

> +#else
> +
> +#define slaunch_wakeup_cpu_from_txt(cpu, apicid)	0

inline stub please. 

> +
> +#endif  /* !CONFIG_SECURE_LAUNCH */
> +
>  /*
>   * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
>   * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
> @@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>  	cpumask_clear_cpu(cpu, cpu_initialized_mask);
>  	smp_mb();
>  
> +	/* With Intel TXT, the AP startup is totally different */
> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==
> +	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {

Stick this condition into a helper function please

> +		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
> +		goto txt_wake;
> +	}
> +
>  	/*
>  	 * Wake up a CPU in difference cases:
>  	 * - Use a method from the APIC driver if one defined, with wakeup
> @@ -1147,6 +1232,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>  		boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
>  						     cpu0_nmi_registered);
>  
> +txt_wake:

Sorry, but what has this to do with TXT ? And why can't the above just
be yet another if clause in the existing if/else if maze?

Now that brings me to another question. How is this supposed to work
with CPU hotplug post boot?

It will simply not work at all because once a CPU is offlined it is
going to sit in an endless loop and wait for INIT/SIPI/SIPI. So it will
get that NMI and go back to wait.

So you need a TXT specific cpu_play_dead() implementation, which should
preferrably use monitor/mwait where each "offline" CPU sits and waits
until a condition becomes true. Then you don't need a NMI for wakeup at
all. Just writing the condition into that per CPU cache line should be
enough.

Thanks,

        tglx


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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-04 14:50   ` Ross Philipson
@ 2023-05-12 18:04     ` Thomas Gleixner
  -1 siblings, 0 replies; 200+ messages in thread
From: Thomas Gleixner @ 2023-05-12 18:04 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel


On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
> +
> +/* CPUID: leaf 1, ECX, SMX feature bit */
> +#define X86_FEATURE_BIT_SMX	(1 << 6)
> +
> +/* Can't include apiddef.h in asm */

Why not? All it needs is a #ifndef __ASSEMBLY__ guard around the C parts.

> +#define XAPIC_ENABLE	(1 << 11)
> +#define X2APIC_ENABLE	(1 << 10)
> +
> +/* Can't include traps.h in asm */

NMI_VECTOR is defined in irq_vectors.h which just has a include
<linux/threads.h> for no real good reason.

> +#define X86_TRAP_NMI	2

<SNIP>

> +/*
> + * See the comment in head_64.S for detailed informatoin on what this macro
> + * is used for.
> + */
> +#define rva(X) ((X) - sl_stub_entry)

I'm having a hard time to find that comment in head_64.S. At least it's
not in this patch.

> +.Lsl_ap_cs:
> +	/* Load the relocated AP IDT */
[ 11 more citation lines. Click/Enter to show. ]
> +	lidt	(sl_ap_idt_desc - sl_txt_ap_wake_begin)(%ecx)
> +
> +	/* Fixup MTRRs and misc enable MSR on APs too */
> +	call	sl_txt_load_regs
> +
> +	/* Enable SMI with GETSEC[SMCTRL] */
> +	GETSEC $(SMX_X86_GETSEC_SMCTRL)
> +
> +	/* IRET-to-self can be used to enable NMIs which SENTER disabled */
> +	leal	rva(.Lnmi_enabled_ap)(%ebx), %eax
> +	pushfl
> +	pushl	$(__SL32_CS)
> +	pushl	%eax
> +	iret

So from here on any NMI which hits the AP before it can reach the wait
loop will corrupt EDX...

> +/* This is the beginning of the relocated AP wake code block */
> +	.global sl_txt_ap_wake_begin
[ 10 more citation lines. Click/Enter to show. ]
> +sl_txt_ap_wake_begin:
> +
> +	/*
> +	 * Wait for NMI IPI in the relocated AP wake block which was provided
> +	 * and protected in the memory map by the prelaunch code. Leave all
> +	 * other interrupts masked since we do not expect anything but an NMI.
> +	 */
> +	xorl	%edx, %edx
> +
> +1:
> +	hlt
> +	testl	%edx, %edx
> +	jz	1b

This really makes me nervous. A stray NMI and the AP starts going.

Can't this NMI just bring the AP out of HLT w/o changing any state and
the AP evaluates a memory location which indicates whether it should
start up or not.

> +	/*
> +	 * This is the long absolute jump to the 32b Secure Launch protected
> +	 * mode stub code in the rmpiggy. The jump address will be fixed in

Providing an actual name for the stub might spare to rummage through
code to figure out where this is supposed to jump to.

> +	 * the SMP boot code when the first AP is brought up. This whole area
> +	 * is provided and protected in the memory map by the prelaunch code.
[ 2 more citation lines. Click/Enter to show. ]
> +	 */
> +	.byte	0xea
> +sl_ap_jmp_offset:
> +	.long	0x00000000
> +	.word	__SL32_CS

Thanks,

	tglx

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-05-12 18:04     ` Thomas Gleixner
  0 siblings, 0 replies; 200+ messages in thread
From: Thomas Gleixner @ 2023-05-12 18:04 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: ross.philipson, dpsmith, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel


On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
> +
> +/* CPUID: leaf 1, ECX, SMX feature bit */
> +#define X86_FEATURE_BIT_SMX	(1 << 6)
> +
> +/* Can't include apiddef.h in asm */

Why not? All it needs is a #ifndef __ASSEMBLY__ guard around the C parts.

> +#define XAPIC_ENABLE	(1 << 11)
> +#define X2APIC_ENABLE	(1 << 10)
> +
> +/* Can't include traps.h in asm */

NMI_VECTOR is defined in irq_vectors.h which just has a include
<linux/threads.h> for no real good reason.

> +#define X86_TRAP_NMI	2

<SNIP>

> +/*
> + * See the comment in head_64.S for detailed informatoin on what this macro
> + * is used for.
> + */
> +#define rva(X) ((X) - sl_stub_entry)

I'm having a hard time to find that comment in head_64.S. At least it's
not in this patch.

> +.Lsl_ap_cs:
> +	/* Load the relocated AP IDT */
[ 11 more citation lines. Click/Enter to show. ]
> +	lidt	(sl_ap_idt_desc - sl_txt_ap_wake_begin)(%ecx)
> +
> +	/* Fixup MTRRs and misc enable MSR on APs too */
> +	call	sl_txt_load_regs
> +
> +	/* Enable SMI with GETSEC[SMCTRL] */
> +	GETSEC $(SMX_X86_GETSEC_SMCTRL)
> +
> +	/* IRET-to-self can be used to enable NMIs which SENTER disabled */
> +	leal	rva(.Lnmi_enabled_ap)(%ebx), %eax
> +	pushfl
> +	pushl	$(__SL32_CS)
> +	pushl	%eax
> +	iret

So from here on any NMI which hits the AP before it can reach the wait
loop will corrupt EDX...

> +/* This is the beginning of the relocated AP wake code block */
> +	.global sl_txt_ap_wake_begin
[ 10 more citation lines. Click/Enter to show. ]
> +sl_txt_ap_wake_begin:
> +
> +	/*
> +	 * Wait for NMI IPI in the relocated AP wake block which was provided
> +	 * and protected in the memory map by the prelaunch code. Leave all
> +	 * other interrupts masked since we do not expect anything but an NMI.
> +	 */
> +	xorl	%edx, %edx
> +
> +1:
> +	hlt
> +	testl	%edx, %edx
> +	jz	1b

This really makes me nervous. A stray NMI and the AP starts going.

Can't this NMI just bring the AP out of HLT w/o changing any state and
the AP evaluates a memory location which indicates whether it should
start up or not.

> +	/*
> +	 * This is the long absolute jump to the 32b Secure Launch protected
> +	 * mode stub code in the rmpiggy. The jump address will be fixed in

Providing an actual name for the stub might spare to rummage through
code to figure out where this is supposed to jump to.

> +	 * the SMP boot code when the first AP is brought up. This whole area
> +	 * is provided and protected in the memory map by the prelaunch code.
[ 2 more citation lines. Click/Enter to show. ]
> +	 */
> +	.byte	0xea
> +sl_ap_jmp_offset:
> +	.long	0x00000000
> +	.word	__SL32_CS

Thanks,

	tglx

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-12 16:13               ` Matthew Garrett
@ 2023-05-12 18:17                 ` Thomas Gleixner
  -1 siblings, 0 replies; 200+ messages in thread
From: Thomas Gleixner @ 2023-05-12 18:17 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ard Biesheuvel, Eric Biggers, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi, dpsmith, mingo, bp, hpa, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On Fri, May 12 2023 at 17:13, Matthew Garrett wrote:
> On Fri, May 12, 2023 at 03:24:04PM +0200, Thomas Gleixner wrote:
>> On Fri, May 12 2023 at 12:28, Matthew Garrett wrote:
>> > Unless we assert that SHA-1 events are unsupported, it seems a bit odd 
>> > to force a policy on people who have both banks enabled. People with 
>> > mixed fleets are potentially going to be dealing with SHA-1 measurements 
>> > for a while yet, and while there's obviously a security benefit in using 
>> > SHA-2 instead it'd be irritating to have to maintain two attestation 
>> > policies.
>> 
>> Why?
>> 
>> If you have a mixed fleet then it's not too much asked to provide two
>> data sets. On a TPM2 system you can enforce SHA-2 and only fallback to
>> SHA-1 on TPM 1.2 hardware. No?
>
> No, beause having TPM2 hardware doesn't guarantee that your firmware 
> enables SHA-2 (which also means this is something that could change with 
> firmware updates, which means that refusing to support SHA-1 if the 
> SHA-2 banks are enabled could result in an entirely different policy 
> being required (and plausibly one that isn't implemented in their 
> existing tooling)

It's not rocket science to have both variants supported in tooling,
really.

What a mess.


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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-12 18:17                 ` Thomas Gleixner
  0 siblings, 0 replies; 200+ messages in thread
From: Thomas Gleixner @ 2023-05-12 18:17 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ard Biesheuvel, Eric Biggers, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi, dpsmith, mingo, bp, hpa, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On Fri, May 12 2023 at 17:13, Matthew Garrett wrote:
> On Fri, May 12, 2023 at 03:24:04PM +0200, Thomas Gleixner wrote:
>> On Fri, May 12 2023 at 12:28, Matthew Garrett wrote:
>> > Unless we assert that SHA-1 events are unsupported, it seems a bit odd 
>> > to force a policy on people who have both banks enabled. People with 
>> > mixed fleets are potentially going to be dealing with SHA-1 measurements 
>> > for a while yet, and while there's obviously a security benefit in using 
>> > SHA-2 instead it'd be irritating to have to maintain two attestation 
>> > policies.
>> 
>> Why?
>> 
>> If you have a mixed fleet then it's not too much asked to provide two
>> data sets. On a TPM2 system you can enforce SHA-2 and only fallback to
>> SHA-1 on TPM 1.2 hardware. No?
>
> No, beause having TPM2 hardware doesn't guarantee that your firmware 
> enables SHA-2 (which also means this is something that could change with 
> firmware updates, which means that refusing to support SHA-1 if the 
> SHA-2 banks are enabled could result in an entirely different policy 
> being required (and plausibly one that isn't implemented in their 
> existing tooling)

It's not rocket science to have both variants supported in tooling,
really.

What a mess.


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-12 18:17                 ` Thomas Gleixner
@ 2023-05-12 19:12                   ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 19:12 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Ard Biesheuvel, Eric Biggers, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi, dpsmith, mingo, bp, hpa, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On Fri, May 12, 2023 at 08:17:21PM +0200, Thomas Gleixner wrote:
> On Fri, May 12 2023 at 17:13, Matthew Garrett wrote:
> > On Fri, May 12, 2023 at 03:24:04PM +0200, Thomas Gleixner wrote:
> >> On Fri, May 12 2023 at 12:28, Matthew Garrett wrote:
> >> > Unless we assert that SHA-1 events are unsupported, it seems a bit odd 
> >> > to force a policy on people who have both banks enabled. People with 
> >> > mixed fleets are potentially going to be dealing with SHA-1 measurements 
> >> > for a while yet, and while there's obviously a security benefit in using 
> >> > SHA-2 instead it'd be irritating to have to maintain two attestation 
> >> > policies.
> >> 
> >> Why?
> >> 
> >> If you have a mixed fleet then it's not too much asked to provide two
> >> data sets. On a TPM2 system you can enforce SHA-2 and only fallback to
> >> SHA-1 on TPM 1.2 hardware. No?
> >
> > No, beause having TPM2 hardware doesn't guarantee that your firmware 
> > enables SHA-2 (which also means this is something that could change with 
> > firmware updates, which means that refusing to support SHA-1 if the 
> > SHA-2 banks are enabled could result in an entirely different policy 
> > being required (and plausibly one that isn't implemented in their 
> > existing tooling)
> 
> It's not rocket science to have both variants supported in tooling,
> really.

People who are currently using tboot are only getting SHA-1, so there's 
no obvious reason for them to have added support yet. *My* tooling all 
supports SHA-2 so I'm completely fine here, but either we refuse to 
support a bunch of hardware or we have to support SHA-1 anyway, and if 
we have to support it the only reason not to implement it even in the 
"SHA-2 is supported" case is because we have opinions about how other 
people implement their security.

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-12 19:12                   ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-12 19:12 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Ard Biesheuvel, Eric Biggers, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi, dpsmith, mingo, bp, hpa, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On Fri, May 12, 2023 at 08:17:21PM +0200, Thomas Gleixner wrote:
> On Fri, May 12 2023 at 17:13, Matthew Garrett wrote:
> > On Fri, May 12, 2023 at 03:24:04PM +0200, Thomas Gleixner wrote:
> >> On Fri, May 12 2023 at 12:28, Matthew Garrett wrote:
> >> > Unless we assert that SHA-1 events are unsupported, it seems a bit odd 
> >> > to force a policy on people who have both banks enabled. People with 
> >> > mixed fleets are potentially going to be dealing with SHA-1 measurements 
> >> > for a while yet, and while there's obviously a security benefit in using 
> >> > SHA-2 instead it'd be irritating to have to maintain two attestation 
> >> > policies.
> >> 
> >> Why?
> >> 
> >> If you have a mixed fleet then it's not too much asked to provide two
> >> data sets. On a TPM2 system you can enforce SHA-2 and only fallback to
> >> SHA-1 on TPM 1.2 hardware. No?
> >
> > No, beause having TPM2 hardware doesn't guarantee that your firmware 
> > enables SHA-2 (which also means this is something that could change with 
> > firmware updates, which means that refusing to support SHA-1 if the 
> > SHA-2 banks are enabled could result in an entirely different policy 
> > being required (and plausibly one that isn't implemented in their 
> > existing tooling)
> 
> It's not rocket science to have both variants supported in tooling,
> really.

People who are currently using tboot are only getting SHA-1, so there's 
no obvious reason for them to have added support yet. *My* tooling all 
supports SHA-2 so I'm completely fine here, but either we refuse to 
support a bunch of hardware or we have to support SHA-1 anyway, and if 
we have to support it the only reason not to implement it even in the 
"SHA-2 is supported" case is because we have opinions about how other 
people implement their security.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-12 19:12                   ` Matthew Garrett
@ 2023-05-12 19:42                     ` Andrew Cooper
  -1 siblings, 0 replies; 200+ messages in thread
From: Andrew Cooper @ 2023-05-12 19:42 UTC (permalink / raw)
  To: Matthew Garrett, Thomas Gleixner
  Cc: Ard Biesheuvel, Eric Biggers, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi, dpsmith, mingo, bp, hpa, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel, richard

On 12/05/2023 8:12 pm, Matthew Garrett wrote:
> On Fri, May 12, 2023 at 08:17:21PM +0200, Thomas Gleixner wrote:
>> On Fri, May 12 2023 at 17:13, Matthew Garrett wrote:
>>> On Fri, May 12, 2023 at 03:24:04PM +0200, Thomas Gleixner wrote:
>>>> On Fri, May 12 2023 at 12:28, Matthew Garrett wrote:
>>>>> Unless we assert that SHA-1 events are unsupported, it seems a bit odd 
>>>>> to force a policy on people who have both banks enabled. People with 
>>>>> mixed fleets are potentially going to be dealing with SHA-1 measurements 
>>>>> for a while yet, and while there's obviously a security benefit in using 
>>>>> SHA-2 instead it'd be irritating to have to maintain two attestation 
>>>>> policies.
>>>> Why?
>>>>
>>>> If you have a mixed fleet then it's not too much asked to provide two
>>>> data sets. On a TPM2 system you can enforce SHA-2 and only fallback to
>>>> SHA-1 on TPM 1.2 hardware. No?
>>> No, beause having TPM2 hardware doesn't guarantee that your firmware 
>>> enables SHA-2 (which also means this is something that could change with 
>>> firmware updates, which means that refusing to support SHA-1 if the 
>>> SHA-2 banks are enabled could result in an entirely different policy 
>>> being required (and plausibly one that isn't implemented in their 
>>> existing tooling)
>> It's not rocket science to have both variants supported in tooling,
>> really.
> People who are currently using tboot are only getting SHA-1, so there's 
> no obvious reason for them to have added support yet. *My* tooling all 
> supports SHA-2 so I'm completely fine here, but either we refuse to 
> support a bunch of hardware or we have to support SHA-1 anyway, and if 
> we have to support it the only reason not to implement it even in the 
> "SHA-2 is supported" case is because we have opinions about how other 
> people implement their security.

The way to deal with this is to merge DRTM support (when it's ready of
course) so people have an option which isn't tboot.

Then warn on finding a TPM2 without SHA-2, and make it a failure for
https://fwupd.github.io/libfwupdplugin/hsi.html#tpm-20-present etc, and
eventually the vendors will decide that the easiest way to avoid getting
a cross in their customers UIs is to implement SHA-2 support properly.

~Andrew

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-12 19:42                     ` Andrew Cooper
  0 siblings, 0 replies; 200+ messages in thread
From: Andrew Cooper @ 2023-05-12 19:42 UTC (permalink / raw)
  To: Matthew Garrett, Thomas Gleixner
  Cc: Ard Biesheuvel, Eric Biggers, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi, dpsmith, mingo, bp, hpa, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel, richard

On 12/05/2023 8:12 pm, Matthew Garrett wrote:
> On Fri, May 12, 2023 at 08:17:21PM +0200, Thomas Gleixner wrote:
>> On Fri, May 12 2023 at 17:13, Matthew Garrett wrote:
>>> On Fri, May 12, 2023 at 03:24:04PM +0200, Thomas Gleixner wrote:
>>>> On Fri, May 12 2023 at 12:28, Matthew Garrett wrote:
>>>>> Unless we assert that SHA-1 events are unsupported, it seems a bit odd 
>>>>> to force a policy on people who have both banks enabled. People with 
>>>>> mixed fleets are potentially going to be dealing with SHA-1 measurements 
>>>>> for a while yet, and while there's obviously a security benefit in using 
>>>>> SHA-2 instead it'd be irritating to have to maintain two attestation 
>>>>> policies.
>>>> Why?
>>>>
>>>> If you have a mixed fleet then it's not too much asked to provide two
>>>> data sets. On a TPM2 system you can enforce SHA-2 and only fallback to
>>>> SHA-1 on TPM 1.2 hardware. No?
>>> No, beause having TPM2 hardware doesn't guarantee that your firmware 
>>> enables SHA-2 (which also means this is something that could change with 
>>> firmware updates, which means that refusing to support SHA-1 if the 
>>> SHA-2 banks are enabled could result in an entirely different policy 
>>> being required (and plausibly one that isn't implemented in their 
>>> existing tooling)
>> It's not rocket science to have both variants supported in tooling,
>> really.
> People who are currently using tboot are only getting SHA-1, so there's 
> no obvious reason for them to have added support yet. *My* tooling all 
> supports SHA-2 so I'm completely fine here, but either we refuse to 
> support a bunch of hardware or we have to support SHA-1 anyway, and if 
> we have to support it the only reason not to implement it even in the 
> "SHA-2 is supported" case is because we have opinions about how other 
> people implement their security.

The way to deal with this is to merge DRTM support (when it's ready of
course) so people have an option which isn't tboot.

Then warn on finding a TPM2 without SHA-2, and make it a failure for
https://fwupd.github.io/libfwupdplugin/hsi.html#tpm-20-present etc, and
eventually the vendors will decide that the easiest way to avoid getting
a cross in their customers UIs is to implement SHA-2 support properly.

~Andrew

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-12 12:24               ` Andrew Cooper
@ 2023-05-14 18:18                 ` Eric Biggers
  -1 siblings, 0 replies; 200+ messages in thread
From: Eric Biggers @ 2023-05-14 18:18 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Ard Biesheuvel, Matthew Garrett, Ross Philipson, linux-kernel,
	x86, linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi, dpsmith, tglx, mingo, bp, hpa, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On Fri, May 12, 2023 at 01:24:22PM +0100, Andrew Cooper wrote:
> On 12/05/2023 12:58 pm, Ard Biesheuvel wrote:
> > On Fri, 12 May 2023 at 13:28, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> >> On Fri, May 12, 2023 at 01:18:45PM +0200, Ard Biesheuvel wrote:
> >>> On Fri, 12 May 2023 at 13:04, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> >>>> On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:
> >>>>
> >>>>> SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> >>>>> now?
> >>>> TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also
> >>>> at the whim of the firmware in terms of whether the SHA-2 banks are
> >>>> enabled. But even if the SHA-2 banks are enabled, if you suddenly stop
> >>>> extending the SHA-1 banks, a malicious actor can later turn up and
> >>>> extend whatever they want into them and present a SHA-1-only
> >>>> attestation. Ideally whatever is handling that attestation should know
> >>>> whether or not to expect an attestation with SHA-2, but the easiest way
> >>>> to maintain security is to always extend all banks.
> >>>>
> >>> Wouldn't it make more sense to measure some terminating event into the
> >>> SHA-1 banks instead?
> >> Unless we assert that SHA-1 events are unsupported, it seems a bit odd
> >> to force a policy on people who have both banks enabled. People with
> >> mixed fleets are potentially going to be dealing with SHA-1 measurements
> >> for a while yet, and while there's obviously a security benefit in using
> >> SHA-2 instead it'd be irritating to have to maintain two attestation
> >> policies.
> > I understand why that matters from an operational perspective.
> >
> > However, we are dealing with brand new code being proposed for Linux
> > mainline, and so this is our only chance to push back on this, as
> > otherwise, we will have to maintain it for a very long time.
> >
> > IOW, D-RTM does not exist today in Linux, and it is up to us to define
> > what it will look like. From that perspective, it is downright
> > preposterous to even consider supporting SHA-1, given that SHA-1 by
> > itself gives none of the guarantees that D-RTM aims to provide. If
> > reducing your TCB is important enough to warrant switching to this
> > implementation of D-RTM, surely you can upgrade your attestation
> > policies as well.
> 
> You're suggesting that because Linux has been slow to take D-RTM over
> the past decade, you're going to intentionally break people with older
> hardware just because you don't feel like using an older algorithm?
> 
> That's about the worst possible reason to not take support.
> 
> There really are people in the world with older TPM 1.2 systems where
> this D-RTM using SHA1 only is an improvement over using the incumbent tboot.
> 
> ~Andrew

This patchset is proposing a new kernel feature.  So by definition, there are no
existing users of it that can be broken.

The fact is, SHA-1 is cryptographically broken.  It isn't actually about how
"old" the algorithm is, or what anyone's "feelings" are.

Maybe a renaming from Secure Launch to simply Launch is in order?

- Eric

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-14 18:18                 ` Eric Biggers
  0 siblings, 0 replies; 200+ messages in thread
From: Eric Biggers @ 2023-05-14 18:18 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Ard Biesheuvel, Matthew Garrett, Ross Philipson, linux-kernel,
	x86, linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi, dpsmith, tglx, mingo, bp, hpa, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On Fri, May 12, 2023 at 01:24:22PM +0100, Andrew Cooper wrote:
> On 12/05/2023 12:58 pm, Ard Biesheuvel wrote:
> > On Fri, 12 May 2023 at 13:28, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> >> On Fri, May 12, 2023 at 01:18:45PM +0200, Ard Biesheuvel wrote:
> >>> On Fri, 12 May 2023 at 13:04, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> >>>> On Tue, May 09, 2023 at 06:21:44PM -0700, Eric Biggers wrote:
> >>>>
> >>>>> SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> >>>>> now?
> >>>> TXT is supported on some TPM 1.2 systems as well. TPM 2 systems are also
> >>>> at the whim of the firmware in terms of whether the SHA-2 banks are
> >>>> enabled. But even if the SHA-2 banks are enabled, if you suddenly stop
> >>>> extending the SHA-1 banks, a malicious actor can later turn up and
> >>>> extend whatever they want into them and present a SHA-1-only
> >>>> attestation. Ideally whatever is handling that attestation should know
> >>>> whether or not to expect an attestation with SHA-2, but the easiest way
> >>>> to maintain security is to always extend all banks.
> >>>>
> >>> Wouldn't it make more sense to measure some terminating event into the
> >>> SHA-1 banks instead?
> >> Unless we assert that SHA-1 events are unsupported, it seems a bit odd
> >> to force a policy on people who have both banks enabled. People with
> >> mixed fleets are potentially going to be dealing with SHA-1 measurements
> >> for a while yet, and while there's obviously a security benefit in using
> >> SHA-2 instead it'd be irritating to have to maintain two attestation
> >> policies.
> > I understand why that matters from an operational perspective.
> >
> > However, we are dealing with brand new code being proposed for Linux
> > mainline, and so this is our only chance to push back on this, as
> > otherwise, we will have to maintain it for a very long time.
> >
> > IOW, D-RTM does not exist today in Linux, and it is up to us to define
> > what it will look like. From that perspective, it is downright
> > preposterous to even consider supporting SHA-1, given that SHA-1 by
> > itself gives none of the guarantees that D-RTM aims to provide. If
> > reducing your TCB is important enough to warrant switching to this
> > implementation of D-RTM, surely you can upgrade your attestation
> > policies as well.
> 
> You're suggesting that because Linux has been slow to take D-RTM over
> the past decade, you're going to intentionally break people with older
> hardware just because you don't feel like using an older algorithm?
> 
> That's about the worst possible reason to not take support.
> 
> There really are people in the world with older TPM 1.2 systems where
> this D-RTM using SHA1 only is an improvement over using the incumbent tboot.
> 
> ~Andrew

This patchset is proposing a new kernel feature.  So by definition, there are no
existing users of it that can be broken.

The fact is, SHA-1 is cryptographically broken.  It isn't actually about how
"old" the algorithm is, or what anyone's "feelings" are.

Maybe a renaming from Secure Launch to simply Launch is in order?

- Eric

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-14 18:18                 ` Eric Biggers
@ 2023-05-14 19:11                   ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-14 19:11 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Andrew Cooper, Ard Biesheuvel, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi, dpsmith, tglx, mingo, bp, hpa, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On Sun, May 14, 2023 at 11:18:17AM -0700, Eric Biggers wrote:
> On Fri, May 12, 2023 at 01:24:22PM +0100, Andrew Cooper wrote:
> > You're suggesting that because Linux has been slow to take D-RTM over
> > the past decade, you're going to intentionally break people with older
> > hardware just because you don't feel like using an older algorithm?
> > 
> > That's about the worst possible reason to not take support.
> > 
> > There really are people in the world with older TPM 1.2 systems where
> > this D-RTM using SHA1 only is an improvement over using the incumbent tboot.
> > 
> > ~Andrew
> 
> This patchset is proposing a new kernel feature.  So by definition, there are no
> existing users of it that can be broken.

The patchset reimplements a more extensible version of an existing 
feature which people already consume, and presumably people will be 
encouraged to transition to it. There is plenty of hardware that 
supports this feature that only implements SHA-1. If you want to propose 
that the kernel not implement any functionality that uses deprecated 
hash algorithms then that seems like a larger conversation rather than 
one that should focus on a single pachset.

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-14 19:11                   ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-14 19:11 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Andrew Cooper, Ard Biesheuvel, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi, dpsmith, tglx, mingo, bp, hpa, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On Sun, May 14, 2023 at 11:18:17AM -0700, Eric Biggers wrote:
> On Fri, May 12, 2023 at 01:24:22PM +0100, Andrew Cooper wrote:
> > You're suggesting that because Linux has been slow to take D-RTM over
> > the past decade, you're going to intentionally break people with older
> > hardware just because you don't feel like using an older algorithm?
> > 
> > That's about the worst possible reason to not take support.
> > 
> > There really are people in the world with older TPM 1.2 systems where
> > this D-RTM using SHA1 only is an improvement over using the incumbent tboot.
> > 
> > ~Andrew
> 
> This patchset is proposing a new kernel feature.  So by definition, there are no
> existing users of it that can be broken.

The patchset reimplements a more extensible version of an existing 
feature which people already consume, and presumably people will be 
encouraged to transition to it. There is plenty of hardware that 
supports this feature that only implements SHA-1. If you want to propose 
that the kernel not implement any functionality that uses deprecated 
hash algorithms then that seems like a larger conversation rather than 
one that should focus on a single pachset.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 11/14] reboot: Secure Launch SEXIT support on reboot paths
  2023-05-12 11:40     ` Matthew Garrett
@ 2023-05-15 18:16       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-15 18:16 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/12/23 07:40, Matthew Garrett wrote:
> On Thu, May 04, 2023 at 02:50:20PM +0000, Ross Philipson wrote:
>> If the MLE kernel is being powered off, rebooted or halted,
>> then SEXIT must be called. Note that the SEXIT GETSEC leaf
>> can only be called after a machine_shutdown() has been done on
>> these paths. The machine_shutdown() is not called on a few paths
>> like when poweroff action does not have a poweroff callback (into
>> ACPI code) or when an emergency reset is done. In these cases,
>> just the TXT registers are finalized but SEXIT is skipped.
> 
> What are the consequences of SEXIT not being called, and why is it ok to
> skip it in these circumstances?

Well the system is resetting so there are no real consequences. The 
problem on those two paths is that the APs have not been halted with a 
machine_shutdown() and that is a precondition to issuing GETSEC[SEXIT]. 
Only the BSP should be active and SEXIT must be done on it.

Thanks
Ross

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 11/14] reboot: Secure Launch SEXIT support on reboot paths
@ 2023-05-15 18:16       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-15 18:16 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/12/23 07:40, Matthew Garrett wrote:
> On Thu, May 04, 2023 at 02:50:20PM +0000, Ross Philipson wrote:
>> If the MLE kernel is being powered off, rebooted or halted,
>> then SEXIT must be called. Note that the SEXIT GETSEC leaf
>> can only be called after a machine_shutdown() has been done on
>> these paths. The machine_shutdown() is not called on a few paths
>> like when poweroff action does not have a poweroff callback (into
>> ACPI code) or when an emergency reset is done. In these cases,
>> just the TXT registers are finalized but SEXIT is skipped.
> 
> What are the consequences of SEXIT not being called, and why is it ok to
> skip it in these circumstances?

Well the system is resetting so there are no real consequences. The 
problem on those two paths is that the APs have not been halted with a 
machine_shutdown() and that is a precondition to issuing GETSEC[SEXIT]. 
Only the BSP should be active and SEXIT must be done on it.

Thanks
Ross

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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
  2023-05-12 15:44     ` Thomas Gleixner
@ 2023-05-15 20:06       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-15 20:06 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, mingo, bp, hpa, ardb, mjg59, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel, Ross Philipson

On 5/12/23 11:44, Thomas Gleixner wrote:
> On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
>> The routine slaunch_setup is called out of the x86 specific setup_arch
> 
> Can you please make functions visible in changelogs by appending (),
> i.e. setup_arch() ?

Yes I will.

> 
> See https://urldefense.com/v3/__https://www.kernel.org/doc/html/latest/process/maintainer-tip.html__;!!ACWV5N9M2RV99hQ!IpJMDBpAvJRDAh0tZI_nMv0zZqwQDnxFjBEKRitYq4JU-iV-NnXg28lGtTwb1ynVA4XEy5n9aSdIekxkztyZ$
> for further hints.
> 
>> +static u32 sl_flags;
>> +static struct sl_ap_wake_info ap_wake_info;
>> +static u64 evtlog_addr;
>> +static u32 evtlog_size;
>> +static u64 vtd_pmr_lo_size;
> 
> Is any of this modifyable after boot? If not then this wants to be
> annotated with __ro_after_init.

I believe you are correct and these are never modified after boot so I 
will do this.

> 
>> +/* This should be plenty of room */
>> +static u8 txt_dmar[PAGE_SIZE] __aligned(16);
>> +
>> +u32 slaunch_get_flags(void)
>> +{
>> +	return sl_flags;
>> +}
>> +EXPORT_SYMBOL(slaunch_get_flags);
> 
> What needs this export? If there is a reason then please EXPORT_SYMBOL_GPL()

I think that may be incorrect. I will look into it.

> 
>> +struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
>> +{
>> +	return &ap_wake_info;
>> +}
> 
> If you return a pointer, then there is not much of point for encapsulating.

I am sorry, I am not 100% sure what you mean.

> 
>> +struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
> 
> Some explanation on public visible functions would be really useful.

I can add that.

> 
>> +{
>> +	/* The DMAR is only stashed and provided via TXT on Intel systems */
> 
> -ENOPARSE.

I take it you mean you don't understand the comment. I will try to make 
it clearer.

> 
>> +	if (memcmp(txt_dmar, "DMAR", 4))
>> +		return dmar;
>> +
>> +	return (struct acpi_table_header *)(&txt_dmar[0]);
> 
> s/&txt_dmar[0]/txt_dmar/ No?

Just an old habit. I can change it.

> 
>> +}
> 
>> +void __noreturn slaunch_txt_reset(void __iomem *txt,
>> +				  const char *msg, u64 error)
> 
> Please avoid these line breaks. We lifted the 80 character limit quite
> some time ago.

Ack

> 
>> +
>> +	/* Iterate over heap tables looking for table of "type" */
>> +	for (i = 0; i < type; i++) {
>> +		base += offset;
>> +		heap = early_memremap(base, sizeof(u64));
>> +		if (!heap)
>> +			slaunch_txt_reset(txt,
>> +				"Error early_memremap of heap for heap walk\n",
>> +				SL_ERROR_HEAP_MAP);
> 
> This is horrible to read.
> 
> 		if (!heap) {
> 			slaunch_txt_reset(txt, "Error early_memremap of heap for heap walk\n",
>                          		  SL_ERROR_HEAP_MAP);
>                  }
> 
> See documentation about bracket rules.

Will do.

> 
>> +
>> +/*
>> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
>> + * It is stored in the TXT heap. Fetch it from there and make it available
>> + * to the IOMMU driver.
>> + */
>> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
>> +{
>> +	struct txt_sinit_mle_data *sinit_mle_data;
>> +	u32 field_offset, dmar_size, dmar_offset;
>> +	void *dmar;
>> +
>> +	memset(&txt_dmar, 0, PAGE_SIZE);
> 
> txt_dmar is statically allocated so it's already zero, no?

Yes. This may be left over from an older iteration of the patches. I 
will ditch it.

> 
>> +/*
>> + * Intel TXT specific late stub setup and validation.
>> + */
>> +void __init slaunch_setup_txt(void)
>> +{
>> +	u64 one = TXT_REGVALUE_ONE, val;
>> +	void __iomem *txt;
>> +
>> +	if (!boot_cpu_has(X86_FEATURE_SMX))
>> +		return;
>> +
>> +	/*
>> +	 * If booted through secure launch entry point, the loadflags
>> +	 * option will be set.
>> +	 */
>> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
>> +		return;
>> +
>> +	/*
>> +	 * See if SENTER was done by reading the status register in the
>> +	 * public space. If the public register space cannot be read, TXT may
>> +	 * be disabled.
>> +	 */
>> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
>> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +	if (!txt)
>> +		return;
> 
> Wait. You have established above that SMX is available and the boot has
> set the SLAUNCH flag.
> 
> So if that ioremap() fails then there is an issue with the fixmaps.
> 
> How is returning here sensible? The system will just die later on in the
> worst case with some undecodable issue.

Good point. I don't think I can do a TXT reset at this point but I could 
panic.

Thanks for the review,
Ross

> 
> Thanks,
> 
>          tglx


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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
@ 2023-05-15 20:06       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-15 20:06 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, mingo, bp, hpa, ardb, mjg59, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel, Ross Philipson

On 5/12/23 11:44, Thomas Gleixner wrote:
> On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
>> The routine slaunch_setup is called out of the x86 specific setup_arch
> 
> Can you please make functions visible in changelogs by appending (),
> i.e. setup_arch() ?

Yes I will.

> 
> See https://urldefense.com/v3/__https://www.kernel.org/doc/html/latest/process/maintainer-tip.html__;!!ACWV5N9M2RV99hQ!IpJMDBpAvJRDAh0tZI_nMv0zZqwQDnxFjBEKRitYq4JU-iV-NnXg28lGtTwb1ynVA4XEy5n9aSdIekxkztyZ$
> for further hints.
> 
>> +static u32 sl_flags;
>> +static struct sl_ap_wake_info ap_wake_info;
>> +static u64 evtlog_addr;
>> +static u32 evtlog_size;
>> +static u64 vtd_pmr_lo_size;
> 
> Is any of this modifyable after boot? If not then this wants to be
> annotated with __ro_after_init.

I believe you are correct and these are never modified after boot so I 
will do this.

> 
>> +/* This should be plenty of room */
>> +static u8 txt_dmar[PAGE_SIZE] __aligned(16);
>> +
>> +u32 slaunch_get_flags(void)
>> +{
>> +	return sl_flags;
>> +}
>> +EXPORT_SYMBOL(slaunch_get_flags);
> 
> What needs this export? If there is a reason then please EXPORT_SYMBOL_GPL()

I think that may be incorrect. I will look into it.

> 
>> +struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
>> +{
>> +	return &ap_wake_info;
>> +}
> 
> If you return a pointer, then there is not much of point for encapsulating.

I am sorry, I am not 100% sure what you mean.

> 
>> +struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
> 
> Some explanation on public visible functions would be really useful.

I can add that.

> 
>> +{
>> +	/* The DMAR is only stashed and provided via TXT on Intel systems */
> 
> -ENOPARSE.

I take it you mean you don't understand the comment. I will try to make 
it clearer.

> 
>> +	if (memcmp(txt_dmar, "DMAR", 4))
>> +		return dmar;
>> +
>> +	return (struct acpi_table_header *)(&txt_dmar[0]);
> 
> s/&txt_dmar[0]/txt_dmar/ No?

Just an old habit. I can change it.

> 
>> +}
> 
>> +void __noreturn slaunch_txt_reset(void __iomem *txt,
>> +				  const char *msg, u64 error)
> 
> Please avoid these line breaks. We lifted the 80 character limit quite
> some time ago.

Ack

> 
>> +
>> +	/* Iterate over heap tables looking for table of "type" */
>> +	for (i = 0; i < type; i++) {
>> +		base += offset;
>> +		heap = early_memremap(base, sizeof(u64));
>> +		if (!heap)
>> +			slaunch_txt_reset(txt,
>> +				"Error early_memremap of heap for heap walk\n",
>> +				SL_ERROR_HEAP_MAP);
> 
> This is horrible to read.
> 
> 		if (!heap) {
> 			slaunch_txt_reset(txt, "Error early_memremap of heap for heap walk\n",
>                          		  SL_ERROR_HEAP_MAP);
>                  }
> 
> See documentation about bracket rules.

Will do.

> 
>> +
>> +/*
>> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
>> + * It is stored in the TXT heap. Fetch it from there and make it available
>> + * to the IOMMU driver.
>> + */
>> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
>> +{
>> +	struct txt_sinit_mle_data *sinit_mle_data;
>> +	u32 field_offset, dmar_size, dmar_offset;
>> +	void *dmar;
>> +
>> +	memset(&txt_dmar, 0, PAGE_SIZE);
> 
> txt_dmar is statically allocated so it's already zero, no?

Yes. This may be left over from an older iteration of the patches. I 
will ditch it.

> 
>> +/*
>> + * Intel TXT specific late stub setup and validation.
>> + */
>> +void __init slaunch_setup_txt(void)
>> +{
>> +	u64 one = TXT_REGVALUE_ONE, val;
>> +	void __iomem *txt;
>> +
>> +	if (!boot_cpu_has(X86_FEATURE_SMX))
>> +		return;
>> +
>> +	/*
>> +	 * If booted through secure launch entry point, the loadflags
>> +	 * option will be set.
>> +	 */
>> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
>> +		return;
>> +
>> +	/*
>> +	 * See if SENTER was done by reading the status register in the
>> +	 * public space. If the public register space cannot be read, TXT may
>> +	 * be disabled.
>> +	 */
>> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
>> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
>> +	if (!txt)
>> +		return;
> 
> Wait. You have established above that SMX is available and the boot has
> set the SLAUNCH flag.
> 
> So if that ioremap() fails then there is an issue with the fixmaps.
> 
> How is returning here sensible? The system will just die later on in the
> worst case with some undecodable issue.

Good point. I don't think I can do a TXT reset at this point but I could 
panic.

Thanks for the review,
Ross

> 
> Thanks,
> 
>          tglx


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-12 18:04     ` Thomas Gleixner
@ 2023-05-15 20:13       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-15 20:13 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, mingo, bp, hpa, ardb, mjg59, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel, Ross Philipson

On 5/12/23 14:04, Thomas Gleixner wrote:
> 
> On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
>> +
>> +/* CPUID: leaf 1, ECX, SMX feature bit */
>> +#define X86_FEATURE_BIT_SMX	(1 << 6)
>> +
>> +/* Can't include apiddef.h in asm */
> 
> Why not? All it needs is a #ifndef __ASSEMBLY__ guard around the C parts.

I guess I was reluctant to fiddle with another header file but I can do 
this.

> 
>> +#define XAPIC_ENABLE	(1 << 11)
>> +#define X2APIC_ENABLE	(1 << 10)
>> +
>> +/* Can't include traps.h in asm */
> 
> NMI_VECTOR is defined in irq_vectors.h which just has a include
> <linux/threads.h> for no real good reason.

Ack

> 
>> +#define X86_TRAP_NMI	2
> 
> <SNIP>
> 
>> +/*
>> + * See the comment in head_64.S for detailed informatoin on what this macro
>> + * is used for.
>> + */
>> +#define rva(X) ((X) - sl_stub_entry)
> 
> I'm having a hard time to find that comment in head_64.S. At least it's
> not in this patch.

The is a macro very much like this one and large comment in head_64.S. I 
am just referencing that. If you would rather see that comment 
duplicated here, I can.

> 
>> +.Lsl_ap_cs:
>> +	/* Load the relocated AP IDT */
> [ 11 more citation lines. Click/Enter to show. ]
>> +	lidt	(sl_ap_idt_desc - sl_txt_ap_wake_begin)(%ecx)
>> +
>> +	/* Fixup MTRRs and misc enable MSR on APs too */
>> +	call	sl_txt_load_regs
>> +
>> +	/* Enable SMI with GETSEC[SMCTRL] */
>> +	GETSEC $(SMX_X86_GETSEC_SMCTRL)
>> +
>> +	/* IRET-to-self can be used to enable NMIs which SENTER disabled */
>> +	leal	rva(.Lnmi_enabled_ap)(%ebx), %eax
>> +	pushfl
>> +	pushl	$(__SL32_CS)
>> +	pushl	%eax
>> +	iret
> 
> So from here on any NMI which hits the AP before it can reach the wait
> loop will corrupt EDX...
> 
>> +/* This is the beginning of the relocated AP wake code block */
>> +	.global sl_txt_ap_wake_begin
> [ 10 more citation lines. Click/Enter to show. ]
>> +sl_txt_ap_wake_begin:
>> +
>> +	/*
>> +	 * Wait for NMI IPI in the relocated AP wake block which was provided
>> +	 * and protected in the memory map by the prelaunch code. Leave all
>> +	 * other interrupts masked since we do not expect anything but an NMI.
>> +	 */
>> +	xorl	%edx, %edx
>> +
>> +1:
>> +	hlt
>> +	testl	%edx, %edx
>> +	jz	1b
> 
> This really makes me nervous. A stray NMI and the AP starts going.
> 
> Can't this NMI just bring the AP out of HLT w/o changing any state and
> the AP evaluates a memory location which indicates whether it should
> start up or not.

Given you comments on patch 09, perhaps all this NMI business becomes 
obsolete.

> 
>> +	/*
>> +	 * This is the long absolute jump to the 32b Secure Launch protected
>> +	 * mode stub code in the rmpiggy. The jump address will be fixed in
> 
> Providing an actual name for the stub might spare to rummage through
> code to figure out where this is supposed to jump to.

That can be done.

> 
>> +	 * the SMP boot code when the first AP is brought up. This whole area
>> +	 * is provided and protected in the memory map by the prelaunch code.
> [ 2 more citation lines. Click/Enter to show. ]
>> +	 */
>> +	.byte	0xea
>> +sl_ap_jmp_offset:
>> +	.long	0x00000000
>> +	.word	__SL32_CS
> 
> Thanks,
> 
> 	tglx

Thanks
Ross

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-05-15 20:13       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-15 20:13 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, mingo, bp, hpa, ardb, mjg59, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel, Ross Philipson

On 5/12/23 14:04, Thomas Gleixner wrote:
> 
> On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
>> +
>> +/* CPUID: leaf 1, ECX, SMX feature bit */
>> +#define X86_FEATURE_BIT_SMX	(1 << 6)
>> +
>> +/* Can't include apiddef.h in asm */
> 
> Why not? All it needs is a #ifndef __ASSEMBLY__ guard around the C parts.

I guess I was reluctant to fiddle with another header file but I can do 
this.

> 
>> +#define XAPIC_ENABLE	(1 << 11)
>> +#define X2APIC_ENABLE	(1 << 10)
>> +
>> +/* Can't include traps.h in asm */
> 
> NMI_VECTOR is defined in irq_vectors.h which just has a include
> <linux/threads.h> for no real good reason.

Ack

> 
>> +#define X86_TRAP_NMI	2
> 
> <SNIP>
> 
>> +/*
>> + * See the comment in head_64.S for detailed informatoin on what this macro
>> + * is used for.
>> + */
>> +#define rva(X) ((X) - sl_stub_entry)
> 
> I'm having a hard time to find that comment in head_64.S. At least it's
> not in this patch.

The is a macro very much like this one and large comment in head_64.S. I 
am just referencing that. If you would rather see that comment 
duplicated here, I can.

> 
>> +.Lsl_ap_cs:
>> +	/* Load the relocated AP IDT */
> [ 11 more citation lines. Click/Enter to show. ]
>> +	lidt	(sl_ap_idt_desc - sl_txt_ap_wake_begin)(%ecx)
>> +
>> +	/* Fixup MTRRs and misc enable MSR on APs too */
>> +	call	sl_txt_load_regs
>> +
>> +	/* Enable SMI with GETSEC[SMCTRL] */
>> +	GETSEC $(SMX_X86_GETSEC_SMCTRL)
>> +
>> +	/* IRET-to-self can be used to enable NMIs which SENTER disabled */
>> +	leal	rva(.Lnmi_enabled_ap)(%ebx), %eax
>> +	pushfl
>> +	pushl	$(__SL32_CS)
>> +	pushl	%eax
>> +	iret
> 
> So from here on any NMI which hits the AP before it can reach the wait
> loop will corrupt EDX...
> 
>> +/* This is the beginning of the relocated AP wake code block */
>> +	.global sl_txt_ap_wake_begin
> [ 10 more citation lines. Click/Enter to show. ]
>> +sl_txt_ap_wake_begin:
>> +
>> +	/*
>> +	 * Wait for NMI IPI in the relocated AP wake block which was provided
>> +	 * and protected in the memory map by the prelaunch code. Leave all
>> +	 * other interrupts masked since we do not expect anything but an NMI.
>> +	 */
>> +	xorl	%edx, %edx
>> +
>> +1:
>> +	hlt
>> +	testl	%edx, %edx
>> +	jz	1b
> 
> This really makes me nervous. A stray NMI and the AP starts going.
> 
> Can't this NMI just bring the AP out of HLT w/o changing any state and
> the AP evaluates a memory location which indicates whether it should
> start up or not.

Given you comments on patch 09, perhaps all this NMI business becomes 
obsolete.

> 
>> +	/*
>> +	 * This is the long absolute jump to the 32b Secure Launch protected
>> +	 * mode stub code in the rmpiggy. The jump address will be fixed in
> 
> Providing an actual name for the stub might spare to rummage through
> code to figure out where this is supposed to jump to.

That can be done.

> 
>> +	 * the SMP boot code when the first AP is brought up. This whole area
>> +	 * is provided and protected in the memory map by the prelaunch code.
> [ 2 more citation lines. Click/Enter to show. ]
>> +	 */
>> +	.byte	0xea
>> +sl_ap_jmp_offset:
>> +	.long	0x00000000
>> +	.word	__SL32_CS
> 
> Thanks,
> 
> 	tglx

Thanks
Ross

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

* Re: [PATCH v6 09/14] x86: Secure Launch SMP bringup support
  2023-05-12 18:02     ` Thomas Gleixner
@ 2023-05-15 20:19       ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-15 20:19 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, mingo, bp, hpa, ardb, mjg59, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel, Ross Philipson

On 5/12/23 14:02, Thomas Gleixner wrote:
> On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
>>   
>> +#ifdef CONFIG_SECURE_LAUNCH
>> +
>> +static atomic_t first_ap_only = {1};
> 
> ATOMIC_INIT(1) if at all.
> 
>> +
>> +/*
>> + * Called to fix the long jump address for the waiting APs to vector to
>> + * the correct startup location in the Secure Launch stub in the rmpiggy.
>> + */
>> +static int
>> +slaunch_fixup_jump_vector(void)
> 
> One line please.
> 
>> +{
>> +	struct sl_ap_wake_info *ap_wake_info;
>> +	u32 *ap_jmp_ptr = NULL;
>> +
>> +	if (!atomic_dec_and_test(&first_ap_only))
>> +		return 0;
> 
> Why does this need an atomic? CPU bringup is fully serialized and even
> with the upcoming parallel bootup work, there is no concurrency on this
> function.
> 
> Aside of that. Why isn't this initialized during boot in a __init function?
> 
>> +	ap_wake_info = slaunch_get_ap_wake_info();
>> +
>> +	ap_jmp_ptr = (u32 *)__va(ap_wake_info->ap_wake_block +
>> +				 ap_wake_info->ap_jmp_offset);
>> +
>> +	*ap_jmp_ptr = real_mode_header->sl_trampoline_start32;
>> +
>> +	pr_debug("TXT AP long jump address updated\n");
>> +
>> +	return 0;
> 
> Why does this need a return code of all return paths return 0?
> 
>> +}
>> +
>> +/*
>> + * TXT AP startup is quite different than normal. The APs cannot have #INIT
>> + * asserted on them or receive SIPIs. The early Secure Launch code has parked
>> + * the APs in a pause loop waiting to receive an NMI. This will wake the APs
>> + * and have them jump to the protected mode code in the rmpiggy where the rest
>> + * of the SMP boot of the AP will proceed normally.
>> + */
>> +static int
>> +slaunch_wakeup_cpu_from_txt(int cpu, int apicid)
>> +{
>> +	unsigned long send_status = 0, accept_status = 0;
>> +
>> +	/* Only done once */
> 
> Yes. But not here.
> 
>> +	if (slaunch_fixup_jump_vector())
>> +		return -1;
>> +
>> +	/* Send NMI IPI to idling AP and wake it up */
>> +	apic_icr_write(APIC_DM_NMI, apicid);
>> +
>> +	if (init_udelay == 0)
>> +		udelay(10);
>> +	else
>> +		udelay(300);
> 
> The wonders of copy & pasta. This condition is pointless because this
> code only runs on systems which force init_udelay to 0.
> 
>> +	send_status = safe_apic_wait_icr_idle();
> 
> Moar copy & pasta. As this is guaranteed to be X2APIC mode, this
> function is a nop and returns 0 unconditionally.
> 
>> +	if (init_udelay == 0)
>> +		udelay(10);
>> +	else
>> +		udelay(300);
>> +
>> +	accept_status = (apic_read(APIC_ESR) & 0xEF);
> 
> The point of this is? Bit 0-3 are Pentium and P6 only.
> 
> Bit 4 Tried to send low prio IPI but not supported
> Bit 5 Illegal Vector sent
> Bit 6 Illegal Vector received
> Bit 7 X2APIC illegal register access
> 
> IOW, there is no accept error here. That would be bit 2 which is never set
> on anything modern
> 
> But aside of that the read is moot anyway because the CPU has the APIC
> error vector enabled so if this would happen the APIC error interrupt
> would have swallowed and cleared the error condition.
> 
> IOW. Everything except the apic_icr_write() here is completely useless.
> 
>> +#else
>> +
>> +#define slaunch_wakeup_cpu_from_txt(cpu, apicid)	0
> 
> inline stub please.
> 
>> +
>> +#endif  /* !CONFIG_SECURE_LAUNCH */
>> +
>>   /*
>>    * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
>>    * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
>> @@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>>   	cpumask_clear_cpu(cpu, cpu_initialized_mask);
>>   	smp_mb();
>>   
>> +	/* With Intel TXT, the AP startup is totally different */
>> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==
>> +	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {
> 
> Stick this condition into a helper function please
> 
>> +		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
>> +		goto txt_wake;
>> +	}
>> +
>>   	/*
>>   	 * Wake up a CPU in difference cases:
>>   	 * - Use a method from the APIC driver if one defined, with wakeup
>> @@ -1147,6 +1232,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>>   		boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
>>   						     cpu0_nmi_registered);
>>   
>> +txt_wake:
> 
> Sorry, but what has this to do with TXT ? And why can't the above just
> be yet another if clause in the existing if/else if maze?
> 
> Now that brings me to another question. How is this supposed to work
> with CPU hotplug post boot?
> 
> It will simply not work at all because once a CPU is offlined it is
> going to sit in an endless loop and wait for INIT/SIPI/SIPI. So it will
> get that NMI and go back to wait.
> 
> So you need a TXT specific cpu_play_dead() implementation, which should
> preferrably use monitor/mwait where each "offline" CPU sits and waits
> until a condition becomes true. Then you don't need a NMI for wakeup at
> all. Just writing the condition into that per CPU cache line should be
> enough.
> 
> Thanks,
> 
>          tglx
> 
There is a lot here to think about. It sounds like you are suggesting we 
design all of this differently and we can definitely do that. We need 
time to go over this and your parallel startup series before we can 
really get down to how best to approach this.

I am going on vacation and will be back the first week of June. I will 
get back to you then once I have had time to go over all of this and 
your other patches.

Thank you for all your responses.

Ross

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 09/14] x86: Secure Launch SMP bringup support
@ 2023-05-15 20:19       ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-05-15 20:19 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, mingo, bp, hpa, ardb, mjg59, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel, Ross Philipson

On 5/12/23 14:02, Thomas Gleixner wrote:
> On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
>>   
>> +#ifdef CONFIG_SECURE_LAUNCH
>> +
>> +static atomic_t first_ap_only = {1};
> 
> ATOMIC_INIT(1) if at all.
> 
>> +
>> +/*
>> + * Called to fix the long jump address for the waiting APs to vector to
>> + * the correct startup location in the Secure Launch stub in the rmpiggy.
>> + */
>> +static int
>> +slaunch_fixup_jump_vector(void)
> 
> One line please.
> 
>> +{
>> +	struct sl_ap_wake_info *ap_wake_info;
>> +	u32 *ap_jmp_ptr = NULL;
>> +
>> +	if (!atomic_dec_and_test(&first_ap_only))
>> +		return 0;
> 
> Why does this need an atomic? CPU bringup is fully serialized and even
> with the upcoming parallel bootup work, there is no concurrency on this
> function.
> 
> Aside of that. Why isn't this initialized during boot in a __init function?
> 
>> +	ap_wake_info = slaunch_get_ap_wake_info();
>> +
>> +	ap_jmp_ptr = (u32 *)__va(ap_wake_info->ap_wake_block +
>> +				 ap_wake_info->ap_jmp_offset);
>> +
>> +	*ap_jmp_ptr = real_mode_header->sl_trampoline_start32;
>> +
>> +	pr_debug("TXT AP long jump address updated\n");
>> +
>> +	return 0;
> 
> Why does this need a return code of all return paths return 0?
> 
>> +}
>> +
>> +/*
>> + * TXT AP startup is quite different than normal. The APs cannot have #INIT
>> + * asserted on them or receive SIPIs. The early Secure Launch code has parked
>> + * the APs in a pause loop waiting to receive an NMI. This will wake the APs
>> + * and have them jump to the protected mode code in the rmpiggy where the rest
>> + * of the SMP boot of the AP will proceed normally.
>> + */
>> +static int
>> +slaunch_wakeup_cpu_from_txt(int cpu, int apicid)
>> +{
>> +	unsigned long send_status = 0, accept_status = 0;
>> +
>> +	/* Only done once */
> 
> Yes. But not here.
> 
>> +	if (slaunch_fixup_jump_vector())
>> +		return -1;
>> +
>> +	/* Send NMI IPI to idling AP and wake it up */
>> +	apic_icr_write(APIC_DM_NMI, apicid);
>> +
>> +	if (init_udelay == 0)
>> +		udelay(10);
>> +	else
>> +		udelay(300);
> 
> The wonders of copy & pasta. This condition is pointless because this
> code only runs on systems which force init_udelay to 0.
> 
>> +	send_status = safe_apic_wait_icr_idle();
> 
> Moar copy & pasta. As this is guaranteed to be X2APIC mode, this
> function is a nop and returns 0 unconditionally.
> 
>> +	if (init_udelay == 0)
>> +		udelay(10);
>> +	else
>> +		udelay(300);
>> +
>> +	accept_status = (apic_read(APIC_ESR) & 0xEF);
> 
> The point of this is? Bit 0-3 are Pentium and P6 only.
> 
> Bit 4 Tried to send low prio IPI but not supported
> Bit 5 Illegal Vector sent
> Bit 6 Illegal Vector received
> Bit 7 X2APIC illegal register access
> 
> IOW, there is no accept error here. That would be bit 2 which is never set
> on anything modern
> 
> But aside of that the read is moot anyway because the CPU has the APIC
> error vector enabled so if this would happen the APIC error interrupt
> would have swallowed and cleared the error condition.
> 
> IOW. Everything except the apic_icr_write() here is completely useless.
> 
>> +#else
>> +
>> +#define slaunch_wakeup_cpu_from_txt(cpu, apicid)	0
> 
> inline stub please.
> 
>> +
>> +#endif  /* !CONFIG_SECURE_LAUNCH */
>> +
>>   /*
>>    * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
>>    * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
>> @@ -1132,6 +1210,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>>   	cpumask_clear_cpu(cpu, cpu_initialized_mask);
>>   	smp_mb();
>>   
>> +	/* With Intel TXT, the AP startup is totally different */
>> +	if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) ==
>> +	   (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) {
> 
> Stick this condition into a helper function please
> 
>> +		boot_error = slaunch_wakeup_cpu_from_txt(cpu, apicid);
>> +		goto txt_wake;
>> +	}
>> +
>>   	/*
>>   	 * Wake up a CPU in difference cases:
>>   	 * - Use a method from the APIC driver if one defined, with wakeup
>> @@ -1147,6 +1232,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
>>   		boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
>>   						     cpu0_nmi_registered);
>>   
>> +txt_wake:
> 
> Sorry, but what has this to do with TXT ? And why can't the above just
> be yet another if clause in the existing if/else if maze?
> 
> Now that brings me to another question. How is this supposed to work
> with CPU hotplug post boot?
> 
> It will simply not work at all because once a CPU is offlined it is
> going to sit in an endless loop and wait for INIT/SIPI/SIPI. So it will
> get that NMI and go back to wait.
> 
> So you need a TXT specific cpu_play_dead() implementation, which should
> preferrably use monitor/mwait where each "offline" CPU sits and waits
> until a condition becomes true. Then you don't need a NMI for wakeup at
> all. Just writing the condition into that per CPU cache line should be
> enough.
> 
> Thanks,
> 
>          tglx
> 
There is a lot here to think about. It sounds like you are suggesting we 
design all of this differently and we can definitely do that. We need 
time to go over this and your parallel startup series before we can 
really get down to how best to approach this.

I am going on vacation and will be back the first week of June. I will 
get back to you then once I have had time to go over all of this and 
your other patches.

Thank you for all your responses.

Ross

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-05-10 23:04     ` Jarkko Sakkinen
@ 2023-05-15 20:58       ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-15 20:58 UTC (permalink / raw)
  To: Jarkko Sakkinen, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi
  Cc: tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On 5/10/23 19:04, Jarkko Sakkinen wrote:
> On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
>> Introduce the Secure Launch Resource Table which forms the formal
>> interface between the pre and post launch code.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   include/linux/slr_table.h | 270 ++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 270 insertions(+)
>>   create mode 100644 include/linux/slr_table.h
>>
>> diff --git a/include/linux/slr_table.h b/include/linux/slr_table.h
>> new file mode 100644
>> index 0000000..d4b76e5
>> --- /dev/null
>> +++ b/include/linux/slr_table.h
>> @@ -0,0 +1,270 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Secure Launch Resource Table
>> + *
>> + * Copyright (c) 2023, Oracle and/or its affiliates.
>> + */
>> +
>> +#ifndef _LINUX_SLR_TABLE_H
>> +#define _LINUX_SLR_TABLE_H
>> +
>> +/* Put this in efi.h if it becomes a standard */
>> +#define SLR_TABLE_GUID				EFI_GUID(0x877a9b2a, 0x0385, 0x45d1, 0xa0, 0x34, 0x9d, 0xac, 0x9c, 0x9e, 0x56, 0x5f)
>> +
>> +/* SLR table header values */
>> +#define SLR_TABLE_MAGIC		0x4452544d
>> +#define SLR_TABLE_REVISION	1
>> +
>> +/* Current revisions for the policy and UEFI config */
>> +#define SLR_POLICY_REVISION		1
>> +#define SLR_UEFI_CONFIG_REVISION	1
>> +
>> +/* SLR defined architectures */
>> +#define SLR_INTEL_TXT		1
>> +#define SLR_AMD_SKINIT		2
>> +
>> +/* SLR defined bootloaders */
>> +#define SLR_BOOTLOADER_INVALID	0
>> +#define SLR_BOOTLOADER_GRUB	1
>> +
>> +/* Log formats */
>> +#define SLR_DRTM_TPM12_LOG	1
>> +#define SLR_DRTM_TPM20_LOG	2
>> +
>> +/* DRTM Policy Entry Flags */
>> +#define SLR_POLICY_FLAG_MEASURED	0x1
>> +#define SLR_POLICY_IMPLICIT_SIZE	0x2
>> +
>> +/* Array Lengths */
>> +#define TPM_EVENT_INFO_LENGTH		32
>> +#define TXT_VARIABLE_MTRRS_LENGTH	32
>> +
>> +/* Tags */
>> +#define SLR_ENTRY_INVALID	0x0000
>> +#define SLR_ENTRY_DL_INFO	0x0001
>> +#define SLR_ENTRY_LOG_INFO	0x0002
>> +#define SLR_ENTRY_ENTRY_POLICY	0x0003
>> +#define SLR_ENTRY_INTEL_INFO	0x0004
>> +#define SLR_ENTRY_AMD_INFO	0x0005
>> +#define SLR_ENTRY_ARM_INFO	0x0006
>> +#define SLR_ENTRY_UEFI_INFO	0x0007
>> +#define SLR_ENTRY_UEFI_CONFIG	0x0008
>> +#define SLR_ENTRY_END		0xffff
> 
> "Enums are preferred when defining several related constants."
> 
> See:
> 
> https://www.kernel.org/doc/html/latest/process/coding-style.html#macros-enums-and-rtl

These values are only used for a u16 field in a packed structure. 
Correct me if I am mistaken, but if an enum is used this will result in 
type/casting handling to/from the u16 which would negate some of the 
main benefits of using an enum.

v/r,
dps


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-05-15 20:58       ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-15 20:58 UTC (permalink / raw)
  To: Jarkko Sakkinen, Ross Philipson, linux-kernel, x86,
	linux-integrity, linux-doc, linux-crypto, iommu, kexec,
	linux-efi
  Cc: tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On 5/10/23 19:04, Jarkko Sakkinen wrote:
> On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
>> Introduce the Secure Launch Resource Table which forms the formal
>> interface between the pre and post launch code.
>>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
>> ---
>>   include/linux/slr_table.h | 270 ++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 270 insertions(+)
>>   create mode 100644 include/linux/slr_table.h
>>
>> diff --git a/include/linux/slr_table.h b/include/linux/slr_table.h
>> new file mode 100644
>> index 0000000..d4b76e5
>> --- /dev/null
>> +++ b/include/linux/slr_table.h
>> @@ -0,0 +1,270 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Secure Launch Resource Table
>> + *
>> + * Copyright (c) 2023, Oracle and/or its affiliates.
>> + */
>> +
>> +#ifndef _LINUX_SLR_TABLE_H
>> +#define _LINUX_SLR_TABLE_H
>> +
>> +/* Put this in efi.h if it becomes a standard */
>> +#define SLR_TABLE_GUID				EFI_GUID(0x877a9b2a, 0x0385, 0x45d1, 0xa0, 0x34, 0x9d, 0xac, 0x9c, 0x9e, 0x56, 0x5f)
>> +
>> +/* SLR table header values */
>> +#define SLR_TABLE_MAGIC		0x4452544d
>> +#define SLR_TABLE_REVISION	1
>> +
>> +/* Current revisions for the policy and UEFI config */
>> +#define SLR_POLICY_REVISION		1
>> +#define SLR_UEFI_CONFIG_REVISION	1
>> +
>> +/* SLR defined architectures */
>> +#define SLR_INTEL_TXT		1
>> +#define SLR_AMD_SKINIT		2
>> +
>> +/* SLR defined bootloaders */
>> +#define SLR_BOOTLOADER_INVALID	0
>> +#define SLR_BOOTLOADER_GRUB	1
>> +
>> +/* Log formats */
>> +#define SLR_DRTM_TPM12_LOG	1
>> +#define SLR_DRTM_TPM20_LOG	2
>> +
>> +/* DRTM Policy Entry Flags */
>> +#define SLR_POLICY_FLAG_MEASURED	0x1
>> +#define SLR_POLICY_IMPLICIT_SIZE	0x2
>> +
>> +/* Array Lengths */
>> +#define TPM_EVENT_INFO_LENGTH		32
>> +#define TXT_VARIABLE_MTRRS_LENGTH	32
>> +
>> +/* Tags */
>> +#define SLR_ENTRY_INVALID	0x0000
>> +#define SLR_ENTRY_DL_INFO	0x0001
>> +#define SLR_ENTRY_LOG_INFO	0x0002
>> +#define SLR_ENTRY_ENTRY_POLICY	0x0003
>> +#define SLR_ENTRY_INTEL_INFO	0x0004
>> +#define SLR_ENTRY_AMD_INFO	0x0005
>> +#define SLR_ENTRY_ARM_INFO	0x0006
>> +#define SLR_ENTRY_UEFI_INFO	0x0007
>> +#define SLR_ENTRY_UEFI_CONFIG	0x0008
>> +#define SLR_ENTRY_END		0xffff
> 
> "Enums are preferred when defining several related constants."
> 
> See:
> 
> https://www.kernel.org/doc/html/latest/process/coding-style.html#macros-enums-and-rtl

These values are only used for a u16 field in a packed structure. 
Correct me if I am mistaken, but if an enum is used this will result in 
type/casting handling to/from the u16 which would negate some of the 
main benefits of using an enum.

v/r,
dps


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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-05-12 10:55     ` Matthew Garrett
@ 2023-05-15 21:15       ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-15 21:15 UTC (permalink / raw)
  To: Matthew Garrett, Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/12/23 06:55, Matthew Garrett wrote:
> On Thu, May 04, 2023 at 02:50:13PM +0000, Ross Philipson wrote:
> 
>> +#define SLR_TABLE_MAGIC		0x4452544d
> 
>  From convention I'd expect this to be 0x534c5254, but not really an
> issue.

Apologies, but which convention?

>> +/* SLR defined bootloaders */
>> +#define SLR_BOOTLOADER_INVALID	0
>> +#define SLR_BOOTLOADER_GRUB	1
> 
> Oof. Having the kernel know about bootloaders has not worked out super
> well for us in the past. If someone writes a new bootloader, are they
> unable to Secure Launch any existing kernels? The pragmatic thing for
> them to do would be to just pretend they're grub, which kind of defeats
> the point of having this definition...

Actually, this is not for making the kernel know about bootloaders. This 
is dealing with the challenge created when the preamble was split for 
efi-stub, and similar use cases, where what sets up the preamble, ie. 
the bootloader, is separate from what invokes the dynamic launch, ie. 
the DLE handler. The reality is that even in the simplest implementation 
of the DLE handler, a remnant of GRUB for call back from efi-stub, there 
is information that is needed to cross the gap.

>> +} __packed;
> 
> Random nit - why are they all packed? Are there circumstances where two
> pieces of code with different assumptions about alignment will be
> looking at a single instance of a table? It doesn't seem likely we're
> going to be doing DRTM in a 32-bit firmware environment while launching
> a 64-bit kernel?

We wrote the TrenchBoot Secure Launch general spec [1] with as much 
forethought as possible for the target environments. Specifically, the 
desire is to have a common approach for x86 (Intel and AMD), Arm, and 
perhaps down the road the POWER arch. In particular, I do not believe 
there is anything in the Arm DRTM beta spec that prohibits a mixed 32/64 
bit environment. In the end it is better to for the spec to be safe for 
those environments then having to make changes to the spec later down 
the road.

[1] https://trenchboot.org/specifications/Secure_Launch/

v/r,
dps

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-05-15 21:15       ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-15 21:15 UTC (permalink / raw)
  To: Matthew Garrett, Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/12/23 06:55, Matthew Garrett wrote:
> On Thu, May 04, 2023 at 02:50:13PM +0000, Ross Philipson wrote:
> 
>> +#define SLR_TABLE_MAGIC		0x4452544d
> 
>  From convention I'd expect this to be 0x534c5254, but not really an
> issue.

Apologies, but which convention?

>> +/* SLR defined bootloaders */
>> +#define SLR_BOOTLOADER_INVALID	0
>> +#define SLR_BOOTLOADER_GRUB	1
> 
> Oof. Having the kernel know about bootloaders has not worked out super
> well for us in the past. If someone writes a new bootloader, are they
> unable to Secure Launch any existing kernels? The pragmatic thing for
> them to do would be to just pretend they're grub, which kind of defeats
> the point of having this definition...

Actually, this is not for making the kernel know about bootloaders. This 
is dealing with the challenge created when the preamble was split for 
efi-stub, and similar use cases, where what sets up the preamble, ie. 
the bootloader, is separate from what invokes the dynamic launch, ie. 
the DLE handler. The reality is that even in the simplest implementation 
of the DLE handler, a remnant of GRUB for call back from efi-stub, there 
is information that is needed to cross the gap.

>> +} __packed;
> 
> Random nit - why are they all packed? Are there circumstances where two
> pieces of code with different assumptions about alignment will be
> looking at a single instance of a table? It doesn't seem likely we're
> going to be doing DRTM in a 32-bit firmware environment while launching
> a 64-bit kernel?

We wrote the TrenchBoot Secure Launch general spec [1] with as much 
forethought as possible for the target environments. Specifically, the 
desire is to have a common approach for x86 (Intel and AMD), Arm, and 
perhaps down the road the POWER arch. In particular, I do not believe 
there is anything in the Arm DRTM beta spec that prohibits a mixed 32/64 
bit environment. In the end it is better to for the spec to be safe for 
those environments then having to make changes to the spec later down 
the road.

[1] https://trenchboot.org/specifications/Secure_Launch/

v/r,
dps

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-05-15 21:15       ` Daniel P. Smith
@ 2023-05-15 21:22         ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-15 21:22 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Mon, May 15, 2023 at 05:15:15PM -0400, Daniel P. Smith wrote:
> On 5/12/23 06:55, Matthew Garrett wrote:
> > On Thu, May 04, 2023 at 02:50:13PM +0000, Ross Philipson wrote:
> > 
> > > +#define SLR_TABLE_MAGIC		0x4452544d
> > 
> >  From convention I'd expect this to be 0x534c5254, but not really an
> > issue.
> 
> Apologies, but which convention?

Tables in ACPI and UEFI tend to have magic that corresponds to their 
name, so a table called SLRT would tend to have magic that matches the 
ASCII values for that. In this case the SLRT has DRTM as its magic, 
which is a touch unexpected.

> > Oof. Having the kernel know about bootloaders has not worked out super
> > well for us in the past. If someone writes a new bootloader, are they
> > unable to Secure Launch any existing kernels? The pragmatic thing for
> > them to do would be to just pretend they're grub, which kind of defeats
> > the point of having this definition...
> 
> Actually, this is not for making the kernel know about bootloaders. This is
> dealing with the challenge created when the preamble was split for efi-stub,
> and similar use cases, where what sets up the preamble, ie. the bootloader,
> is separate from what invokes the dynamic launch, ie. the DLE handler. The
> reality is that even in the simplest implementation of the DLE handler, a
> remnant of GRUB for call back from efi-stub, there is information that is
> needed to cross the gap.

What if I don't use grub, but use something that behaves equivalently? 
Which value should be used here?

> We wrote the TrenchBoot Secure Launch general spec [1] with as much
> forethought as possible for the target environments. Specifically, the
> desire is to have a common approach for x86 (Intel and AMD), Arm, and
> perhaps down the road the POWER arch. In particular, I do not believe there
> is anything in the Arm DRTM beta spec that prohibits a mixed 32/64 bit
> environment. In the end it is better to for the spec to be safe for those
> environments then having to make changes to the spec later down the road.

Ok.

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-05-15 21:22         ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-15 21:22 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Mon, May 15, 2023 at 05:15:15PM -0400, Daniel P. Smith wrote:
> On 5/12/23 06:55, Matthew Garrett wrote:
> > On Thu, May 04, 2023 at 02:50:13PM +0000, Ross Philipson wrote:
> > 
> > > +#define SLR_TABLE_MAGIC		0x4452544d
> > 
> >  From convention I'd expect this to be 0x534c5254, but not really an
> > issue.
> 
> Apologies, but which convention?

Tables in ACPI and UEFI tend to have magic that corresponds to their 
name, so a table called SLRT would tend to have magic that matches the 
ASCII values for that. In this case the SLRT has DRTM as its magic, 
which is a touch unexpected.

> > Oof. Having the kernel know about bootloaders has not worked out super
> > well for us in the past. If someone writes a new bootloader, are they
> > unable to Secure Launch any existing kernels? The pragmatic thing for
> > them to do would be to just pretend they're grub, which kind of defeats
> > the point of having this definition...
> 
> Actually, this is not for making the kernel know about bootloaders. This is
> dealing with the challenge created when the preamble was split for efi-stub,
> and similar use cases, where what sets up the preamble, ie. the bootloader,
> is separate from what invokes the dynamic launch, ie. the DLE handler. The
> reality is that even in the simplest implementation of the DLE handler, a
> remnant of GRUB for call back from efi-stub, there is information that is
> needed to cross the gap.

What if I don't use grub, but use something that behaves equivalently? 
Which value should be used here?

> We wrote the TrenchBoot Secure Launch general spec [1] with as much
> forethought as possible for the target environments. Specifically, the
> desire is to have a common approach for x86 (Intel and AMD), Arm, and
> perhaps down the road the POWER arch. In particular, I do not believe there
> is anything in the Arm DRTM beta spec that prohibits a mixed 32/64 bit
> environment. In the end it is better to for the spec to be safe for those
> environments then having to make changes to the spec later down the road.

Ok.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-10  1:21     ` Eric Biggers
@ 2023-05-15 21:23       ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-15 21:23 UTC (permalink / raw)
  To: Eric Biggers, Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/9/23 21:21, Eric Biggers wrote:
> On Thu, May 04, 2023 at 02:50:15PM +0000, Ross Philipson wrote:
>> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>>
>> The SHA algorithms are necessary to measure configuration information into
>> the TPM as early as possible before using the values. This implementation
>> uses the established approach of #including the SHA libraries directly in
>> the code since the compressed kernel is not uncompressed at this point.
>>
>> The SHA code here has its origins in the code from the main kernel:
>>
>> commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")
>>
>> That code could not be pulled directly into the setup portion of the
>> compressed kernel because of other dependencies it pulls in. The result
>> is this is a modified copy of that code that still leverages the core
>> SHA algorithms.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> 
> SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> now?

I think others have commented as to why SHA-1 is provided.

> And if you absolutely MUST use SHA-1 despite it being insecure, please at least
> don't obfuscate it by calling it simply "SHA".

Apologies that it appears that way to you. Typically when referring to 
the family or a subset of the SHA algorithms, SHA-0, SHA-1, SHA-2, and 
SHA-3, it is generally accepted to refer to them as the "SHA 
algorithms". And this is contrasted to the SM algorithms which the TCG 
spec provides for which we have no intentions to support ourselves, 
though others are welcome to contribute.

Again, apologies for misunderstanding and thank you for taking the time 
to review the series.

v/r,
dps


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-15 21:23       ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-15 21:23 UTC (permalink / raw)
  To: Eric Biggers, Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/9/23 21:21, Eric Biggers wrote:
> On Thu, May 04, 2023 at 02:50:15PM +0000, Ross Philipson wrote:
>> From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
>>
>> The SHA algorithms are necessary to measure configuration information into
>> the TPM as early as possible before using the values. This implementation
>> uses the established approach of #including the SHA libraries directly in
>> the code since the compressed kernel is not uncompressed at this point.
>>
>> The SHA code here has its origins in the code from the main kernel:
>>
>> commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")
>>
>> That code could not be pulled directly into the setup portion of the
>> compressed kernel because of other dependencies it pulls in. The result
>> is this is a modified copy of that code that still leverages the core
>> SHA algorithms.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
>> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> 
> SHA-1 is insecure.  Why are you still using SHA-1?  Don't TPMs support SHA-2
> now?

I think others have commented as to why SHA-1 is provided.

> And if you absolutely MUST use SHA-1 despite it being insecure, please at least
> don't obfuscate it by calling it simply "SHA".

Apologies that it appears that way to you. Typically when referring to 
the family or a subset of the SHA algorithms, SHA-0, SHA-1, SHA-2, and 
SHA-3, it is generally accepted to refer to them as the "SHA 
algorithms". And this is contrasted to the SM algorithms which the TCG 
spec provides for which we have no intentions to support ourselves, 
though others are welcome to contribute.

Again, apologies for misunderstanding and thank you for taking the time 
to review the series.

v/r,
dps


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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-05-15 21:22         ` Matthew Garrett
@ 2023-05-16  0:41           ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-16  0:41 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/15/23 17:22, Matthew Garrett wrote:
> On Mon, May 15, 2023 at 05:15:15PM -0400, Daniel P. Smith wrote:
>> On 5/12/23 06:55, Matthew Garrett wrote:
>>> On Thu, May 04, 2023 at 02:50:13PM +0000, Ross Philipson wrote:
>>>
>>>> +#define SLR_TABLE_MAGIC		0x4452544d
>>>
>>>   From convention I'd expect this to be 0x534c5254, but not really an
>>> issue.
>>
>> Apologies, but which convention?
> 
> Tables in ACPI and UEFI tend to have magic that corresponds to their
> name, so a table called SLRT would tend to have magic that matches the
> ASCII values for that. In this case the SLRT has DRTM as its magic,
> which is a touch unexpected.

While the SLRT is meant for UEFI and non-UEFI environments, DRTM is 
definitely a hold over when we started this and you are correct, 
probably not the best choice. In fact, I agree that SLRT is a far better 
magic. We will update the spec and fix it in the series.

>>> Oof. Having the kernel know about bootloaders has not worked out super
>>> well for us in the past. If someone writes a new bootloader, are they
>>> unable to Secure Launch any existing kernels? The pragmatic thing for
>>> them to do would be to just pretend they're grub, which kind of defeats
>>> the point of having this definition...
>>
>> Actually, this is not for making the kernel know about bootloaders. This is
>> dealing with the challenge created when the preamble was split for efi-stub,
>> and similar use cases, where what sets up the preamble, ie. the bootloader,
>> is separate from what invokes the dynamic launch, ie. the DLE handler. The
>> reality is that even in the simplest implementation of the DLE handler, a
>> remnant of GRUB for call back from efi-stub, there is information that is
>> needed to cross the gap.
> 
> What if I don't use grub, but use something that behaves equivalently?
> Which value should be used here?

Generally we would request that the bootloader submit a request to 
register for a value to be reserved in the spec. That aside, the intent 
here is to allow for the possibility for the DLE handler to be 
independent from the bootloader, but this does not have to be this way. 
If a non-open entity decides to produce their own implementation, they 
can freely use a unallocated value at their own risk that it could be 
allocated to another bootloader in the future. Though in this scenario 
it likely would not matter as the non-open DLE handler would only be 
present when the non-open bootloader was present.

>> We wrote the TrenchBoot Secure Launch general spec [1] with as much
>> forethought as possible for the target environments. Specifically, the
>> desire is to have a common approach for x86 (Intel and AMD), Arm, and
>> perhaps down the road the POWER arch. In particular, I do not believe there
>> is anything in the Arm DRTM beta spec that prohibits a mixed 32/64 bit
>> environment. In the end it is better to for the spec to be safe for those
>> environments then having to make changes to the spec later down the road.
> 
> Ok.

Thank you for the review!

v/r,
dps

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-05-16  0:41           ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-16  0:41 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/15/23 17:22, Matthew Garrett wrote:
> On Mon, May 15, 2023 at 05:15:15PM -0400, Daniel P. Smith wrote:
>> On 5/12/23 06:55, Matthew Garrett wrote:
>>> On Thu, May 04, 2023 at 02:50:13PM +0000, Ross Philipson wrote:
>>>
>>>> +#define SLR_TABLE_MAGIC		0x4452544d
>>>
>>>   From convention I'd expect this to be 0x534c5254, but not really an
>>> issue.
>>
>> Apologies, but which convention?
> 
> Tables in ACPI and UEFI tend to have magic that corresponds to their
> name, so a table called SLRT would tend to have magic that matches the
> ASCII values for that. In this case the SLRT has DRTM as its magic,
> which is a touch unexpected.

While the SLRT is meant for UEFI and non-UEFI environments, DRTM is 
definitely a hold over when we started this and you are correct, 
probably not the best choice. In fact, I agree that SLRT is a far better 
magic. We will update the spec and fix it in the series.

>>> Oof. Having the kernel know about bootloaders has not worked out super
>>> well for us in the past. If someone writes a new bootloader, are they
>>> unable to Secure Launch any existing kernels? The pragmatic thing for
>>> them to do would be to just pretend they're grub, which kind of defeats
>>> the point of having this definition...
>>
>> Actually, this is not for making the kernel know about bootloaders. This is
>> dealing with the challenge created when the preamble was split for efi-stub,
>> and similar use cases, where what sets up the preamble, ie. the bootloader,
>> is separate from what invokes the dynamic launch, ie. the DLE handler. The
>> reality is that even in the simplest implementation of the DLE handler, a
>> remnant of GRUB for call back from efi-stub, there is information that is
>> needed to cross the gap.
> 
> What if I don't use grub, but use something that behaves equivalently?
> Which value should be used here?

Generally we would request that the bootloader submit a request to 
register for a value to be reserved in the spec. That aside, the intent 
here is to allow for the possibility for the DLE handler to be 
independent from the bootloader, but this does not have to be this way. 
If a non-open entity decides to produce their own implementation, they 
can freely use a unallocated value at their own risk that it could be 
allocated to another bootloader in the future. Though in this scenario 
it likely would not matter as the non-open DLE handler would only be 
present when the non-open bootloader was present.

>> We wrote the TrenchBoot Secure Launch general spec [1] with as much
>> forethought as possible for the target environments. Specifically, the
>> desire is to have a common approach for x86 (Intel and AMD), Arm, and
>> perhaps down the road the POWER arch. In particular, I do not believe there
>> is anything in the Arm DRTM beta spec that prohibits a mixed 32/64 bit
>> environment. In the end it is better to for the spec to be safe for those
>> environments then having to make changes to the spec later down the road.
> 
> Ok.

Thank you for the review!

v/r,
dps

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
  2023-05-11  3:33     ` Herbert Xu
@ 2023-05-16  0:50       ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-16  0:50 UTC (permalink / raw)
  To: Herbert Xu, Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/10/23 23:33, Herbert Xu wrote:
> Ross Philipson <ross.philipson@oracle.com> wrote:
>>
>> +static void __sha_transform(u32 *digest, const char *data)
>> +{
>> +       u32 ws[SHA1_WORKSPACE_WORDS];
>> +
>> +       sha1_transform(digest, data, ws);
>> +
>> +       memzero_explicit(ws, sizeof(ws));
>> +}
>> +
>> +void early_sha1_init(struct sha1_state *sctx)
>> +{
>> +       sha1_init(sctx->state);
>> +       sctx->count = 0;
>> +}
>> +
>> +void early_sha1_update(struct sha1_state *sctx,
>> +                      const u8 *data,
>> +                      unsigned int len)
>> +{
>> +       unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
>> +
>> +       sctx->count += len;
>> +
>> +       if (likely((partial + len) >= SHA1_BLOCK_SIZE)) {
>> +               int blocks;
>> +
>> +               if (partial) {
>> +                       int p = SHA1_BLOCK_SIZE - partial;
>> +
>> +                       memcpy(sctx->buffer + partial, data, p);
>> +                       data += p;
>> +                       len -= p;
>> +
>> +                       __sha_transform(sctx->state, sctx->buffer);
>> +               }
>> +
>> +               blocks = len / SHA1_BLOCK_SIZE;
>> +               len %= SHA1_BLOCK_SIZE;
>> +
>> +               if (blocks) {
>> +                       while (blocks--) {
>> +                               __sha_transform(sctx->state, data);
>> +                               data += SHA1_BLOCK_SIZE;
>> +                       }
>> +               }
>> +               partial = 0;
>> +       }
>> +
>> +       if (len)
>> +               memcpy(sctx->buffer + partial, data, len);
>> +}
>> +
>> +void early_sha1_final(struct sha1_state *sctx, u8 *out)
>> +{
>> +       const int bit_offset = SHA1_BLOCK_SIZE - sizeof(__be64);
>> +       unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
>> +       __be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
>> +       __be32 *digest = (__be32 *)out;
>> +       int i;
>> +
>> +       sctx->buffer[partial++] = 0x80;
>> +       if (partial > bit_offset) {
>> +               memset(sctx->buffer + partial, 0x0, SHA1_BLOCK_SIZE - partial);
>> +               partial = 0;
>> +
>> +               __sha_transform(sctx->state, sctx->buffer);
>> +       }
>> +
>> +       memset(sctx->buffer + partial, 0x0, bit_offset - partial);
>> +       *bits = cpu_to_be64(sctx->count << 3);
>> +       __sha_transform(sctx->state, sctx->buffer);
>> +
>> +       for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
>> +               put_unaligned_be32(sctx->state[i], digest++);
>> +
>> +       *sctx = (struct sha1_state){};
>> +}
> 
> If we're going to add SHA1 then this should go into lib/crypto
> just like SHA2.

As mentioned before, this patch mimicked an early version for SHA2. We 
were remiss in not keeping it aligned with how the SHA2 evolved. I will 
take a closer look, but these wrappers may be able to go away and be 
reduced to just an include as SHA2 does these days.

v/r,
dps

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements
@ 2023-05-16  0:50       ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-16  0:50 UTC (permalink / raw)
  To: Herbert Xu, Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb, mjg59,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/10/23 23:33, Herbert Xu wrote:
> Ross Philipson <ross.philipson@oracle.com> wrote:
>>
>> +static void __sha_transform(u32 *digest, const char *data)
>> +{
>> +       u32 ws[SHA1_WORKSPACE_WORDS];
>> +
>> +       sha1_transform(digest, data, ws);
>> +
>> +       memzero_explicit(ws, sizeof(ws));
>> +}
>> +
>> +void early_sha1_init(struct sha1_state *sctx)
>> +{
>> +       sha1_init(sctx->state);
>> +       sctx->count = 0;
>> +}
>> +
>> +void early_sha1_update(struct sha1_state *sctx,
>> +                      const u8 *data,
>> +                      unsigned int len)
>> +{
>> +       unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
>> +
>> +       sctx->count += len;
>> +
>> +       if (likely((partial + len) >= SHA1_BLOCK_SIZE)) {
>> +               int blocks;
>> +
>> +               if (partial) {
>> +                       int p = SHA1_BLOCK_SIZE - partial;
>> +
>> +                       memcpy(sctx->buffer + partial, data, p);
>> +                       data += p;
>> +                       len -= p;
>> +
>> +                       __sha_transform(sctx->state, sctx->buffer);
>> +               }
>> +
>> +               blocks = len / SHA1_BLOCK_SIZE;
>> +               len %= SHA1_BLOCK_SIZE;
>> +
>> +               if (blocks) {
>> +                       while (blocks--) {
>> +                               __sha_transform(sctx->state, data);
>> +                               data += SHA1_BLOCK_SIZE;
>> +                       }
>> +               }
>> +               partial = 0;
>> +       }
>> +
>> +       if (len)
>> +               memcpy(sctx->buffer + partial, data, len);
>> +}
>> +
>> +void early_sha1_final(struct sha1_state *sctx, u8 *out)
>> +{
>> +       const int bit_offset = SHA1_BLOCK_SIZE - sizeof(__be64);
>> +       unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
>> +       __be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
>> +       __be32 *digest = (__be32 *)out;
>> +       int i;
>> +
>> +       sctx->buffer[partial++] = 0x80;
>> +       if (partial > bit_offset) {
>> +               memset(sctx->buffer + partial, 0x0, SHA1_BLOCK_SIZE - partial);
>> +               partial = 0;
>> +
>> +               __sha_transform(sctx->state, sctx->buffer);
>> +       }
>> +
>> +       memset(sctx->buffer + partial, 0x0, bit_offset - partial);
>> +       *bits = cpu_to_be64(sctx->count << 3);
>> +       __sha_transform(sctx->state, sctx->buffer);
>> +
>> +       for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
>> +               put_unaligned_be32(sctx->state[i], digest++);
>> +
>> +       *sctx = (struct sha1_state){};
>> +}
> 
> If we're going to add SHA1 then this should go into lib/crypto
> just like SHA2.

As mentioned before, this patch mimicked an early version for SHA2. We 
were remiss in not keeping it aligned with how the SHA2 evolved. I will 
take a closer look, but these wrappers may be able to go away and be 
reduced to just an include as SHA2 does these days.

v/r,
dps

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-12 16:17       ` Ross Philipson
@ 2023-05-16  1:11         ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-16  1:11 UTC (permalink / raw)
  To: Ross Philipson, Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/12/23 12:17, Ross Philipson wrote:
> On 5/12/23 07:26, Matthew Garrett wrote:
>> On Thu, May 04, 2023 at 02:50:16PM +0000, Ross Philipson wrote:
>>
>>> +static void sl_find_event_log(struct slr_table *slrt)
>>
>> If this is called after the EFI stub then we're presumably
>> post-ExitBootServices and we're copied the TPM event log into a
>> configuration table so it's available to the runtime kernel. That also
>> means that we should be adding all further measurements to the Final
>> Events Table rather than the initial event log. How's that handled here,
>> both in terms of ensuring further events (generated by firmware or by
>> us) get added to the right place, and in terms of ensuring the event
>> logs the kernel has later on were covered appropriately? Or is the SL
>> event log an entirely different thing that can be merged in later
>> because it only covers the DRTM PCRs?
> 
> This is a good point. At this point it is really something we 
> overlooked. We will have to revisit this and figure out the best way to 
> find the final event log depending on how things booted.

I believe Ross misunderstood what you were asking for here. There are 
two reasons this is not possible or desired. The first reason is that on 
Intel, the DRTM log is not initialized by TrenchBoot code in the 
preamble. It is only responsible for allocating a buffer and recording 
the location in the TXT structures. When the SINIT ACM is executed, it 
will initialize the log and record the measurement that CPU sent 
directly to the TPM and then the measurements the ACM makes of the 
environment. If you pointed at the SRTM log, then the ACM would write 
over existing log, which I don't think you want. Now if you pointed at 
the tail end of the SRTM log, you would still end up with a second, 
separate log that just happens to be memory adjacent. The second reason 
is more from a trusted computing perspective, these are two different 
trust chains starting from two different Roots of Trust reflecting two 
different temporal states of the system, i.e. freshness. Typically this 
is were most will point out the need to have a measure of the resident 
firmware, i.e. SMM. To address that, should Intel to publish the spec 
for interacting with PPAM[1], TrenchBoot will be able to finally close 
the SMM gap, giving runtime validation of SMM.

[1] 
https://www.intel.com/content/dam/www/central-libraries/us/en/documents/drtm-based-computing-whitepaper.pdf

v/r,
dps

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-05-16  1:11         ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-16  1:11 UTC (permalink / raw)
  To: Ross Philipson, Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/12/23 12:17, Ross Philipson wrote:
> On 5/12/23 07:26, Matthew Garrett wrote:
>> On Thu, May 04, 2023 at 02:50:16PM +0000, Ross Philipson wrote:
>>
>>> +static void sl_find_event_log(struct slr_table *slrt)
>>
>> If this is called after the EFI stub then we're presumably
>> post-ExitBootServices and we're copied the TPM event log into a
>> configuration table so it's available to the runtime kernel. That also
>> means that we should be adding all further measurements to the Final
>> Events Table rather than the initial event log. How's that handled here,
>> both in terms of ensuring further events (generated by firmware or by
>> us) get added to the right place, and in terms of ensuring the event
>> logs the kernel has later on were covered appropriately? Or is the SL
>> event log an entirely different thing that can be merged in later
>> because it only covers the DRTM PCRs?
> 
> This is a good point. At this point it is really something we 
> overlooked. We will have to revisit this and figure out the best way to 
> find the final event log depending on how things booted.

I believe Ross misunderstood what you were asking for here. There are 
two reasons this is not possible or desired. The first reason is that on 
Intel, the DRTM log is not initialized by TrenchBoot code in the 
preamble. It is only responsible for allocating a buffer and recording 
the location in the TXT structures. When the SINIT ACM is executed, it 
will initialize the log and record the measurement that CPU sent 
directly to the TPM and then the measurements the ACM makes of the 
environment. If you pointed at the SRTM log, then the ACM would write 
over existing log, which I don't think you want. Now if you pointed at 
the tail end of the SRTM log, you would still end up with a second, 
separate log that just happens to be memory adjacent. The second reason 
is more from a trusted computing perspective, these are two different 
trust chains starting from two different Roots of Trust reflecting two 
different temporal states of the system, i.e. freshness. Typically this 
is were most will point out the need to have a measure of the resident 
firmware, i.e. SMM. To address that, should Intel to publish the spec 
for interacting with PPAM[1], TrenchBoot will be able to finally close 
the SMM gap, giving runtime validation of SMM.

[1] 
https://www.intel.com/content/dam/www/central-libraries/us/en/documents/drtm-based-computing-whitepaper.pdf

v/r,
dps

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 11/14] reboot: Secure Launch SEXIT support on reboot paths
  2023-05-15 18:16       ` Ross Philipson
@ 2023-05-16  1:23         ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-16  1:23 UTC (permalink / raw)
  To: Ross Philipson, Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/15/23 14:16, Ross Philipson wrote:
> On 5/12/23 07:40, Matthew Garrett wrote:
>> On Thu, May 04, 2023 at 02:50:20PM +0000, Ross Philipson wrote:
>>> If the MLE kernel is being powered off, rebooted or halted,
>>> then SEXIT must be called. Note that the SEXIT GETSEC leaf
>>> can only be called after a machine_shutdown() has been done on
>>> these paths. The machine_shutdown() is not called on a few paths
>>> like when poweroff action does not have a poweroff callback (into
>>> ACPI code) or when an emergency reset is done. In these cases,
>>> just the TXT registers are finalized but SEXIT is skipped.
>>
>> What are the consequences of SEXIT not being called, and why is it ok to
>> skip it in these circumstances?
> 
> Well the system is resetting so there are no real consequences. The 
> problem on those two paths is that the APs have not been halted with a 
> machine_shutdown() and that is a precondition to issuing GETSEC[SEXIT]. 
> Only the BSP should be active and SEXIT must be done on it.

To expand on this just a bit further. On all paths we were able to 
identify, the SECRETS bit is cleared, memconfig is unlocked, and the 
private registers are all closed. This makes the system as safe as 
possible to go through a power event and be able to come back up on the 
other side. The clean way is to always go through an SEXIT before a 
power event, but as Ross highlighted this can only be done after the APs 
have been halted.

v/r,
dps

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

* Re: [PATCH v6 11/14] reboot: Secure Launch SEXIT support on reboot paths
@ 2023-05-16  1:23         ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-16  1:23 UTC (permalink / raw)
  To: Ross Philipson, Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/15/23 14:16, Ross Philipson wrote:
> On 5/12/23 07:40, Matthew Garrett wrote:
>> On Thu, May 04, 2023 at 02:50:20PM +0000, Ross Philipson wrote:
>>> If the MLE kernel is being powered off, rebooted or halted,
>>> then SEXIT must be called. Note that the SEXIT GETSEC leaf
>>> can only be called after a machine_shutdown() has been done on
>>> these paths. The machine_shutdown() is not called on a few paths
>>> like when poweroff action does not have a poweroff callback (into
>>> ACPI code) or when an emergency reset is done. In these cases,
>>> just the TXT registers are finalized but SEXIT is skipped.
>>
>> What are the consequences of SEXIT not being called, and why is it ok to
>> skip it in these circumstances?
> 
> Well the system is resetting so there are no real consequences. The 
> problem on those two paths is that the APs have not been halted with a 
> machine_shutdown() and that is a precondition to issuing GETSEC[SEXIT]. 
> Only the BSP should be active and SEXIT must be done on it.

To expand on this just a bit further. On all paths we were able to 
identify, the SECRETS bit is cleared, memconfig is unlocked, and the 
private registers are all closed. This makes the system as safe as 
possible to go through a power event and be able to come back up on the 
other side. The clean way is to always go through an SEXIT before a 
power event, but as Ross highlighted this can only be done after the APs 
have been halted.

v/r,
dps

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 13/14] tpm: Allow locality 2 to be set when initializing the TPM for Secure Launch
  2023-05-12 16:22       ` Ross Philipson
@ 2023-05-16  1:37         ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-16  1:37 UTC (permalink / raw)
  To: Ross Philipson, Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/12/23 12:22, Ross Philipson wrote:
> On 5/12/23 07:43, Matthew Garrett wrote:
>> On Thu, May 04, 2023 at 02:50:22PM +0000, Ross Philipson wrote:
>>> The Secure Launch MLE environment uses PCRs that are only accessible 
>>> from
>>> the DRTM locality 2. By default the TPM drivers always initialize the
>>> locality to 0. When a Secure Launch is in progress, initialize the
>>> locality to 2.
>>
>> This looks correct in itself, but looking at the CRB driver code I don't
>> think locality support is actually implemented. Are there any SL systems
>> using CRB?
> 
> We have never seen a system that supports CRB other than some firmware 
> TPMs that don't work with TXT in the first place. CRB is unexplored 
> territory at this point.

So there is often confusion over the CRB interface. If you ask an ARM 
person, they will describe a door-bell, general purpose memory interface 
that has no support for locality. That interface is described in the 
TCG's Mobile TPM interface. Though there is work in progress to address 
this. Now if you speak with an x86 person, they will describe a 
state-based command-response mechanism using MMIO registers which has 
locality support. That interface is described in the TCG PC Client 
specification.

As to whether there are devices with CRB and TXT. I have seen talk on 
the tboot mailing list that there exist an Intel client devices that has 
an Intel-PTT fTPM using the PC Client CRB interface and Intel-TXT. I 
myself have never seen one, so I could not point you at a SKU/Part No. 
for such a device. If someone has such a device and willing to help, 
drop me a line and I would be glad to work with them to get this tested.

v/r,
dps

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

* Re: [PATCH v6 13/14] tpm: Allow locality 2 to be set when initializing the TPM for Secure Launch
@ 2023-05-16  1:37         ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-05-16  1:37 UTC (permalink / raw)
  To: Ross Philipson, Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/12/23 12:22, Ross Philipson wrote:
> On 5/12/23 07:43, Matthew Garrett wrote:
>> On Thu, May 04, 2023 at 02:50:22PM +0000, Ross Philipson wrote:
>>> The Secure Launch MLE environment uses PCRs that are only accessible 
>>> from
>>> the DRTM locality 2. By default the TPM drivers always initialize the
>>> locality to 0. When a Secure Launch is in progress, initialize the
>>> locality to 2.
>>
>> This looks correct in itself, but looking at the CRB driver code I don't
>> think locality support is actually implemented. Are there any SL systems
>> using CRB?
> 
> We have never seen a system that supports CRB other than some firmware 
> TPMs that don't work with TXT in the first place. CRB is unexplored 
> territory at this point.

So there is often confusion over the CRB interface. If you ask an ARM 
person, they will describe a door-bell, general purpose memory interface 
that has no support for locality. That interface is described in the 
TCG's Mobile TPM interface. Though there is work in progress to address 
this. Now if you speak with an x86 person, they will describe a 
state-based command-response mechanism using MMIO registers which has 
locality support. That interface is described in the TCG PC Client 
specification.

As to whether there are devices with CRB and TXT. I have seen talk on 
the tboot mailing list that there exist an Intel client devices that has 
an Intel-PTT fTPM using the PC Client CRB interface and Intel-TXT. I 
myself have never seen one, so I could not point you at a SKU/Part No. 
for such a device. If someone has such a device and willing to help, 
drop me a line and I would be glad to work with them to get this tested.

v/r,
dps

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-05-16  0:41           ` Daniel P. Smith
@ 2023-05-16  1:43             ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-16  1:43 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Mon, May 15, 2023 at 08:41:00PM -0400, Daniel P. Smith wrote:
> On 5/15/23 17:22, Matthew Garrett wrote:
> > What if I don't use grub, but use something that behaves equivalently?
> > Which value should be used here?
> 
> Generally we would request that the bootloader submit a request to register
> for a value to be reserved in the spec. That aside, the intent here is to
> allow for the possibility for the DLE handler to be independent from the
> bootloader, but this does not have to be this way. If a non-open entity
> decides to produce their own implementation, they can freely use a
> unallocated value at their own risk that it could be allocated to another
> bootloader in the future. Though in this scenario it likely would not matter
> as the non-open DLE handler would only be present when the non-open
> bootloader was present.

Is the expectation that the DLE will always be shipped with the 
bootloader? I think I'm not entirely clear on what's consuming this and 
why.


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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-05-16  1:43             ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-16  1:43 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Mon, May 15, 2023 at 08:41:00PM -0400, Daniel P. Smith wrote:
> On 5/15/23 17:22, Matthew Garrett wrote:
> > What if I don't use grub, but use something that behaves equivalently?
> > Which value should be used here?
> 
> Generally we would request that the bootloader submit a request to register
> for a value to be reserved in the spec. That aside, the intent here is to
> allow for the possibility for the DLE handler to be independent from the
> bootloader, but this does not have to be this way. If a non-open entity
> decides to produce their own implementation, they can freely use a
> unallocated value at their own risk that it could be allocated to another
> bootloader in the future. Though in this scenario it likely would not matter
> as the non-open DLE handler would only be present when the non-open
> bootloader was present.

Is the expectation that the DLE will always be shipped with the 
bootloader? I think I'm not entirely clear on what's consuming this and 
why.


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-16  1:11         ` Daniel P. Smith
@ 2023-05-16  1:45           ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-16  1:45 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Mon, May 15, 2023 at 09:11:15PM -0400, Daniel P. Smith wrote:
> On 5/12/23 12:17, Ross Philipson wrote:
> > This is a good point. At this point it is really something we
> > overlooked. We will have to revisit this and figure out the best way to
> > find the final event log depending on how things booted.
> 
> I believe Ross misunderstood what you were asking for here. There are two
> reasons this is not possible or desired. The first reason is that on Intel,
> the DRTM log is not initialized by TrenchBoot code in the preamble. It is
> only responsible for allocating a buffer and recording the location in the
> TXT structures. When the SINIT ACM is executed, it will initialize the log
> and record the measurement that CPU sent directly to the TPM and then the
> measurements the ACM makes of the environment. If you pointed at the SRTM
> log, then the ACM would write over existing log, which I don't think you
> want. Now if you pointed at the tail end of the SRTM log, you would still
> end up with a second, separate log that just happens to be memory adjacent.

Ok. I think it would be clearer if either the function names or some 
comments expressly indicated that this refers to the DRTM event log and 
that that's a separate entity from the SRTM one, "event log" on its own 
is likely to cause people to think of the existing log rather than 
associate it with something else.

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-05-16  1:45           ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-05-16  1:45 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Mon, May 15, 2023 at 09:11:15PM -0400, Daniel P. Smith wrote:
> On 5/12/23 12:17, Ross Philipson wrote:
> > This is a good point. At this point it is really something we
> > overlooked. We will have to revisit this and figure out the best way to
> > find the final event log depending on how things booted.
> 
> I believe Ross misunderstood what you were asking for here. There are two
> reasons this is not possible or desired. The first reason is that on Intel,
> the DRTM log is not initialized by TrenchBoot code in the preamble. It is
> only responsible for allocating a buffer and recording the location in the
> TXT structures. When the SINIT ACM is executed, it will initialize the log
> and record the measurement that CPU sent directly to the TPM and then the
> measurements the ACM makes of the environment. If you pointed at the SRTM
> log, then the ACM would write over existing log, which I don't think you
> want. Now if you pointed at the tail end of the SRTM log, you would still
> end up with a second, separate log that just happens to be memory adjacent.

Ok. I think it would be clearer if either the function names or some 
comments expressly indicated that this refers to the DRTM event log and 
that that's a separate entity from the SRTM one, "event log" on its own 
is likely to cause people to think of the existing log rather than 
associate it with something else.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
  2023-05-12 15:58       ` Ross Philipson
@ 2023-05-24  2:55         ` Jarkko Sakkinen
  -1 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-24  2:55 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On Fri May 12, 2023 at 6:58 PM EEST, Ross Philipson wrote:
> On 5/10/23 19:02, Jarkko Sakkinen wrote:
> > On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
> >> The routine slaunch_setup is called out of the x86 specific setup_arch
> >> routine during early kernel boot. After determining what platform is
> >> present, various operations specific to that platform occur. This
> >> includes finalizing setting for the platform late launch and verifying
> >> that memory protections are in place.
> >>
> >> For TXT, this code also reserves the original compressed kernel setup
> >> area where the APs were left looping so that this memory cannot be used.
> >>
> >> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> >> ---
> >>   arch/x86/kernel/Makefile   |   1 +
> >>   arch/x86/kernel/setup.c    |   3 +
> >>   arch/x86/kernel/slaunch.c  | 497 +++++++++++++++++++++++++++++++++++++++++++++
> >>   drivers/iommu/intel/dmar.c |   4 +
> >>   4 files changed, 505 insertions(+)
> >>   create mode 100644 arch/x86/kernel/slaunch.c
> >>
> >> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> >> index dd61752..3d2a33e 100644
> >> --- a/arch/x86/kernel/Makefile
> >> +++ b/arch/x86/kernel/Makefile
> >> @@ -72,6 +72,7 @@ obj-$(CONFIG_X86_32)		+= tls.o
> >>   obj-$(CONFIG_IA32_EMULATION)	+= tls.o
> >>   obj-y				+= step.o
> >>   obj-$(CONFIG_INTEL_TXT)		+= tboot.o
> >> +obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
> >>   obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
> >>   obj-y				+= stacktrace.o
> >>   obj-y				+= cpu/
> >> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> >> index 16babff..592c09e 100644
> >> --- a/arch/x86/kernel/setup.c
> >> +++ b/arch/x86/kernel/setup.c
> >> @@ -21,6 +21,7 @@
> >>   #include <linux/root_dev.h>
> >>   #include <linux/hugetlb.h>
> >>   #include <linux/tboot.h>
> >> +#include <linux/slaunch.h>
> > 
> > Only because of pure curiosity: what made you choose this location in
> > the middle for the new include? :-)
>
> Only because Secure Launch is like TBOOT. No other real reason.
>
> > 
> >>   #include <linux/usb/xhci-dbgp.h>
> >>   #include <linux/static_call.h>
> >>   #include <linux/swiotlb.h>
> >> @@ -1063,6 +1064,8 @@ void __init setup_arch(char **cmdline_p)
> >>   	early_gart_iommu_check();
> >>   #endif
> >>   
> >> +	slaunch_setup_txt();
> >> +
> >>   	/*
> >>   	 * partially used pages are not usable - thus
> >>   	 * we are rounding upwards:
> >> diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
> >> new file mode 100644
> >> index 0000000..7dba088
> >> --- /dev/null
> >> +++ b/arch/x86/kernel/slaunch.c
> >> @@ -0,0 +1,497 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * Secure Launch late validation/setup and finalization support.
> >> + *
> >> + * Copyright (c) 2022, Oracle and/or its affiliates.
> >> + */
> >> +
> >> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> >> +
> >> +#include <linux/linkage.h>
> >> +#include <linux/mm.h>
> >> +#include <linux/io.h>
> >> +#include <linux/uaccess.h>
> >> +#include <linux/security.h>
> >> +#include <linux/memblock.h>
> >> +#include <asm/segment.h>
> >> +#include <asm/sections.h>
> >> +#include <asm/tlbflush.h>
> >> +#include <asm/e820/api.h>
> >> +#include <asm/setup.h>
> >> +#include <linux/slr_table.h>
> >> +#include <linux/slaunch.h>
> >> +
> >> +static u32 sl_flags;
> >> +static struct sl_ap_wake_info ap_wake_info;
> >> +static u64 evtlog_addr;
> >> +static u32 evtlog_size;
> >> +static u64 vtd_pmr_lo_size;
> >> +
> >> +/* This should be plenty of room */
> >> +static u8 txt_dmar[PAGE_SIZE] __aligned(16);
> >> +
> >> +u32 slaunch_get_flags(void)
> >> +{
> >> +	return sl_flags;
> >> +}
> >> +EXPORT_SYMBOL(slaunch_get_flags);
> >> +
> >> +struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
> >> +{
> >> +	return &ap_wake_info;
> >> +}
> >> +
> >> +struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
> >> +{
> >> +	/* The DMAR is only stashed and provided via TXT on Intel systems */
> >> +	if (memcmp(txt_dmar, "DMAR", 4))
> >> +		return dmar;
> >> +
> >> +	return (struct acpi_table_header *)(&txt_dmar[0]);
> >> +}
> >> +
> >> +void __noreturn slaunch_txt_reset(void __iomem *txt,
> >> +				  const char *msg, u64 error)
> >> +{
> >> +	u64 one = 1, val;
> >> +
> >> +	pr_err("%s", msg);
> >> +
> >> +	/*
> >> +	 * This performs a TXT reset with a sticky error code. The reads of
> >> +	 * TXT_CR_E2STS act as barriers.
> >> +	 */
> >> +	memcpy_toio(txt + TXT_CR_ERRORCODE, &error, sizeof(error));
> >> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> >> +	memcpy_toio(txt + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
> >> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> >> +	memcpy_toio(txt + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
> >> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> >> +	memcpy_toio(txt + TXT_CR_CMD_RESET, &one, sizeof(one));
> >> +
> >> +	for ( ; ; )
> >> +		asm volatile ("hlt");
> >> +
> >> +	unreachable();
> >> +}
> >> +
> >> +/*
> >> + * The TXT heap is too big to map all at once with early_ioremap
> >> + * so it is done a table at a time.
> >> + */
> >> +static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
> >> +					     u32 bytes)
> >> +{
> >> +	u64 base, size, offset = 0;
> >> +	void *heap;
> >> +	int i;
> >> +
> >> +	if (type > TXT_SINIT_TABLE_MAX)
> >> +		slaunch_txt_reset(txt,
> >> +			"Error invalid table type for early heap walk\n",
> >> +			SL_ERROR_HEAP_WALK);
> > 
> > Align with 'txt'.
>
> Ack
>
> > 
> >> +
> >> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
> >> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
> >> +
> >> +	/* Iterate over heap tables looking for table of "type" */
> >> +	for (i = 0; i < type; i++) {
> >> +		base += offset;
> >> +		heap = early_memremap(base, sizeof(u64));
> >> +		if (!heap)
> >> +			slaunch_txt_reset(txt,
> >> +				"Error early_memremap of heap for heap walk\n",
> >> +				SL_ERROR_HEAP_MAP);
> >> +
> >> +		offset = *((u64 *)heap);
> >> +
> >> +		/*
> >> +		 * After the first iteration, any offset of zero is invalid and
> >> +		 * implies the TXT heap is corrupted.
> >> +		 */
> >> +		if (!offset)
> >> +			slaunch_txt_reset(txt,
> >> +				"Error invalid 0 offset in heap walk\n",
> >> +				SL_ERROR_HEAP_ZERO_OFFSET);
> >> +
> >> +		early_memunmap(heap, sizeof(u64));
> >> +	}
> >> +
> >> +	/* Skip the size field at the head of each table */
> >> +	base += sizeof(u64);
> >> +	heap = early_memremap(base, bytes);
> >> +	if (!heap)
> >> +		slaunch_txt_reset(txt,
> >> +				  "Error early_memremap of heap section\n",
> >> +				  SL_ERROR_HEAP_MAP);
> >> +
> >> +	return heap;
> >> +}
> >> +
> >> +static void __init txt_early_put_heap_table(void *addr, unsigned long size)
> >> +{
> >> +	early_memunmap(addr, size);
> >> +}
> >> +
> >> +/*
> >> + * TXT uses a special set of VTd registers to protect all of memory from DMA
> >> + * until the IOMMU can be programmed to protect memory. There is the low
> >> + * memory PMR that can protect all memory up to 4G. The high memory PRM can
> >> + * be setup to protect all memory beyond 4Gb. Validate that these values cover
> >> + * what is expected.
> >> + */
> >> +static void __init slaunch_verify_pmrs(void __iomem *txt)
> >> +{
> >> +	struct txt_os_sinit_data *os_sinit_data;
> >> +	u32 field_offset, err = 0;
> >> +	const char *errmsg = "";
> >> +	unsigned long last_pfn;
> >> +
> >> +	field_offset = offsetof(struct txt_os_sinit_data, lcp_po_base);
> >> +	os_sinit_data = txt_early_get_heap_table(txt, TXT_OS_SINIT_DATA_TABLE,
> >> +						 field_offset);
> >> +
> >> +	/* Save a copy */
> >> +	vtd_pmr_lo_size = os_sinit_data->vtd_pmr_lo_size;
> >> +
> >> +	last_pfn = e820__end_of_ram_pfn();
> >> +
> >> +	/*
> >> +	 * First make sure the hi PMR covers all memory above 4G. In the
> >> +	 * unlikely case where there is < 4G on the system, the hi PMR will
> >> +	 * not be set.
> >> +	 */
> >> +	if (os_sinit_data->vtd_pmr_hi_base != 0x0ULL) {
> >> +		if (os_sinit_data->vtd_pmr_hi_base != 0x100000000ULL) {
> >> +			err = SL_ERROR_HI_PMR_BASE;
> >> +			errmsg =  "Error hi PMR base\n";
> >> +			goto out;
> >> +		}
> >> +
> >> +		if (PFN_PHYS(last_pfn) > os_sinit_data->vtd_pmr_hi_base +
> >> +		    os_sinit_data->vtd_pmr_hi_size) {
> >> +			err = SL_ERROR_HI_PMR_SIZE;
> >> +			errmsg = "Error hi PMR size\n";
> >> +			goto out;
> >> +		}
> >> +	}
> >> +
> >> +	/*
> >> +	 * Lo PMR base should always be 0. This was already checked in
> >> +	 * early stub.
> >> +	 */
> >> +
> >> +	/*
> >> +	 * Check that if the kernel was loaded below 4G, that it is protected
> >> +	 * by the lo PMR. Note this is the decompressed kernel. The ACM would
> >> +	 * have ensured the compressed kernel (the MLE image) was protected.
> >> +	 */
> >> +	if ((__pa_symbol(_end) < 0x100000000ULL) &&
> >> +	    (__pa_symbol(_end) > os_sinit_data->vtd_pmr_lo_size)) {
> >> +		err = SL_ERROR_LO_PMR_MLE;
> >> +		errmsg = "Error lo PMR does not cover MLE kernel\n";
> >> +	}
> >> +
> >> +	/*
> >> +	 * Other regions of interest like boot param, AP wake block, cmdline
> >> +	 * already checked for PMR coverage in the early stub code.
> >> +	 */
> >> +
> >> +out:
> >> +	txt_early_put_heap_table(os_sinit_data, field_offset);
> >> +
> >> +	if (err)
> >> +		slaunch_txt_reset(txt, errmsg, err);
> >> +}
> >> +
> >> +static void __init slaunch_txt_reserve_range(u64 base, u64 size)
> >> +{
> >> +	int type;
> >> +
> >> +	type = e820__get_entry_type(base, base + size - 1);
> >> +	if (type == E820_TYPE_RAM) {
> >> +		pr_info("memblock reserve base: %llx size: %llx\n", base, size);
> >> +		memblock_reserve(base, size);
> >> +	}
> >> +}
> >> +
> >> +/*
> >> + * For Intel, certain regions of memory must be marked as reserved by putting
> >> + * them on the memblock reserved list if they are not already e820 reserved.
> >> + * This includes:
> >> + *  - The TXT HEAP
> >> + *  - The ACM area
> >> + *  - The TXT private register bank
> >> + *  - The MDR list sent to the MLE by the ACM (see TXT specification)
> >> + *  (Normally the above are properly reserved by firmware but if it was not
> >> + *  done, reserve them now)
> >> + *  - The AP wake block
> >> + *  - TPM log external to the TXT heap
> >> + *
> >> + * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
> >> + * the low PMR must be reservered too.
> >> + */
> >> +static void __init slaunch_txt_reserve(void __iomem *txt)
> >> +{
> >> +	struct txt_sinit_memory_descriptor_record *mdr;
> >> +	struct txt_sinit_mle_data *sinit_mle_data;
> >> +	u64 base, size, heap_base, heap_size;
> >> +	u32 mdrnum, mdroffset, mdrslen;
> >> +	u32 field_offset, i;
> >> +	void *mdrs;
> >> +
> >> +	base = TXT_PRIV_CONFIG_REGS_BASE;
> >> +	size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
> >> +	slaunch_txt_reserve_range(base, size);
> >> +
> >> +	memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
> >> +	memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
> >> +	slaunch_txt_reserve_range(heap_base, heap_size);
> >> +
> >> +	memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
> >> +	memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
> >> +	slaunch_txt_reserve_range(base, size);
> >> +
> >> +	field_offset = offsetof(struct txt_sinit_mle_data,
> >> +				sinit_vtd_dmar_table_size);
> >> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> >> +						  field_offset);
> >> +
> >> +	mdrnum = sinit_mle_data->num_of_sinit_mdrs;
> >> +	mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
> >> +
> >> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
> >> +
> >> +	if (!mdrnum)
> >> +		goto nomdr;
> >> +
> >> +	mdrslen = mdrnum * sizeof(struct txt_sinit_memory_descriptor_record);
> >> +
> >> +	mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> >> +					mdroffset + mdrslen - 8);
> >> +
> >> +	mdr = mdrs + mdroffset - 8;
> >> +
> >> +	for (i = 0; i < mdrnum; i++, mdr++) {
> >> +		/* Spec says some entries can have length 0, ignore them */
> >> +		if (mdr->type > 0 && mdr->length > 0)
> >> +			slaunch_txt_reserve_range(mdr->address, mdr->length);
> >> +	}
> >> +
> >> +	txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
> >> +
> >> +nomdr:
> >> +	slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
> >> +				  ap_wake_info.ap_wake_block_size);
> >> +
> >> +	/*
> >> +	 * Earlier checks ensured that the event log was properly situated
> >> +	 * either inside the TXT heap or outside. This is a check to see if the
> >> +	 * event log needs to be reserved. If it is in the TXT heap, it is
> >> +	 * already reserved.
> >> +	 */
> >> +	if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
> >> +		slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
> >> +
> >> +	for (i = 0; i < e820_table->nr_entries; i++) {
> >> +		base = e820_table->entries[i].addr;
> >> +		size = e820_table->entries[i].size;
> >> +		if ((base >= vtd_pmr_lo_size) && (base < 0x100000000ULL))
> >> +			slaunch_txt_reserve_range(base, size);
> >> +		else if ((base < vtd_pmr_lo_size) &&
> >> +			 (base + size > vtd_pmr_lo_size))
> >> +			slaunch_txt_reserve_range(vtd_pmr_lo_size,
> >> +						  base + size - vtd_pmr_lo_size);
> >> +	}
> >> +}
> >> +
> >> +/*
> >> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
> >> + * It is stored in the TXT heap. Fetch it from there and make it available
> >> + * to the IOMMU driver.
> >> + */
> >> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
> >> +{
> >> +	struct txt_sinit_mle_data *sinit_mle_data;
> >> +	u32 field_offset, dmar_size, dmar_offset;
> >> +	void *dmar;
> >> +
> >> +	memset(&txt_dmar, 0, PAGE_SIZE);
> >> +
> >> +	field_offset = offsetof(struct txt_sinit_mle_data,
> >> +				processor_scrtm_status);
> >> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> >> +						  field_offset);
> >> +
> >> +	dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
> >> +	dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
> >> +
> >> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
> >> +
> >> +	if (!dmar_size || !dmar_offset)
> >> +		slaunch_txt_reset(txt,
> >> +				  "Error invalid DMAR table values\n",
> >> +				  SL_ERROR_HEAP_INVALID_DMAR);
> >> +
> >> +	if (unlikely(dmar_size > PAGE_SIZE))
> >> +		slaunch_txt_reset(txt,
> >> +				  "Error DMAR too big to store\n",
> >> +				  SL_ERROR_HEAP_DMAR_SIZE);
> >> +
> >> +
> >> +	dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> >> +					dmar_offset + dmar_size - 8);
> >> +	if (!dmar)
> >> +		slaunch_txt_reset(txt,
> >> +				  "Error early_ioremap of DMAR\n",
> >> +				  SL_ERROR_HEAP_DMAR_MAP);
> >> +
> >> +	memcpy(&txt_dmar[0], dmar + dmar_offset - 8, dmar_size);
> >> +
> >> +	txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
> >> +}
> >> +
> >> +/*
> >> + * The location of the safe AP wake code block is stored in the TXT heap.
> >> + * Fetch needed values here in the early init code for later use in SMP
> >> + * startup.
> >> + *
> >> + * Also get the TPM event log values are in the SLRT and have to be fetched.
> >> + * They will be put on the memblock reserve list later.
> >> + */
> >> +static void __init slaunch_fetch_values(void __iomem *txt)
> >> +{
> >> +	struct txt_os_mle_data *os_mle_data;
> >> +	struct slr_entry_log_info *log_info;
> >> +	struct slr_table *slrt;
> >> +	u8 *jmp_offset;
> >> +	u32 size;
> >> +
> >> +	os_mle_data = txt_early_get_heap_table(txt, TXT_OS_MLE_DATA_TABLE,
> >> +					       sizeof(*os_mle_data));
> >> +
> >> +	ap_wake_info.ap_wake_block = os_mle_data->ap_wake_block;
> >> +	ap_wake_info.ap_wake_block_size = os_mle_data->ap_wake_block_size;
> >> +
> >> +	jmp_offset = os_mle_data->mle_scratch + SL_SCRATCH_AP_JMP_OFFSET;
> >> +	ap_wake_info.ap_jmp_offset = *((u32 *)jmp_offset);
> >> +
> >> +	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, sizeof(*slrt));
> >> +	if (!slrt)
> >> +		slaunch_txt_reset(txt,
> >> +			"Error early_memremap of SLRT failed\n",
> >> +			SL_ERROR_SLRT_MAP);
> >> +
> >> +	size = slrt->size;
> >> +	early_memunmap(slrt, sizeof(*slrt));
> >> +
> >> +	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, size);
> >> +	if (!slrt)
> >> +		slaunch_txt_reset(txt,
> >> +			"Error early_memremap of SLRT failed\n",
> >> +			SL_ERROR_SLRT_MAP);
> >> +
> >> +	log_info = (struct slr_entry_log_info *)
> >> +		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
> >> +
> >> +	if (!log_info)
> >> +		slaunch_txt_reset(txt,
> >> +				  "SLRT missing logging info entry\n",
> >> +				  SL_ERROR_SLRT_MISSING_ENTRY);
> >> +
> >> +	evtlog_addr = log_info->addr;
> >> +	evtlog_size = log_info->size;
> >> +
> >> +	early_memunmap(slrt, size);
> >> +
> >> +	txt_early_put_heap_table(os_mle_data, sizeof(*os_mle_data));
> >> +}
> >> +
> >> +/*
> >> + * Intel TXT specific late stub setup and validation.
> >> + */
> >> +void __init slaunch_setup_txt(void)
> >> +{
> >> +	u64 one = TXT_REGVALUE_ONE, val;
> >> +	void __iomem *txt;
> >> +
> >> +	if (!boot_cpu_has(X86_FEATURE_SMX))
> >> +		return;
> >> +
> >> +	/*
> >> +	 * If booted through secure launch entry point, the loadflags
> >> +	 * option will be set.
> >> +	 */
> >> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
> >> +		return;
> >> +
> >> +	/*
> >> +	 * See if SENTER was done by reading the status register in the
> >> +	 * public space. If the public register space cannot be read, TXT may
> >> +	 * be disabled.
> >> +	 */
> >> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
> >> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> >> +	if (!txt)
> >> +		return;
> >> +
> >> +	memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
> >> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> >> +
> >> +	/* SENTER should have been done */
> >> +	if (!(val & TXT_SENTER_DONE_STS))
> >> +		panic("Error TXT.STS SENTER_DONE not set\n");
> >> +
> >> +	/* SEXIT should have been cleared */
> >> +	if (val & TXT_SEXIT_DONE_STS)
> >> +		panic("Error TXT.STS SEXIT_DONE set\n");
> >> +
> >> +	/* Now we want to use the private register space */
> >> +	txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
> >> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> >> +	if (!txt) {
> >> +		/* This is really bad, no where to go from here */
> >> +		panic("Error early_ioremap of TXT priv registers\n");
> >> +	}
> >> +
> >> +	/*
> >> +	 * Try to read the Intel VID from the TXT private registers to see if
> >> +	 * TXT measured launch happened properly and the private space is
> >> +	 * available.
> >> +	 */
> >> +	memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
> >> +	if ((val & 0xffff) != 0x8086) {
> >> +		/*
> >> +		 * Can't do a proper TXT reset since it appears something is
> >> +		 * wrong even though SENTER happened and it should be in SMX
> >> +		 * mode.
> >> +		 */
> >> +		panic("Invalid TXT vendor ID, not in SMX mode\n");
> >> +	}
> >> +
> >> +	/* Set flags so subsequent code knows the status of the launch */
> >> +	sl_flags |= (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT);
> >> +
> >> +	/*
> >> +	 * Reading the proper DIDVID from the private register space means we
> >> +	 * are in SMX mode and private registers are open for read/write.
> >> +	 */
> >> +
> >> +	/* On Intel, have to handle TPM localities via TXT */
> >> +	memcpy_toio(txt + TXT_CR_CMD_SECRETS, &one, sizeof(one));
> >> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> >> +	memcpy_toio(txt + TXT_CR_CMD_OPEN_LOCALITY1, &one, sizeof(one));
> >> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> >> +
> >> +	slaunch_fetch_values(txt);
> >> +
> >> +	slaunch_verify_pmrs(txt);
> >> +
> >> +	slaunch_txt_reserve(txt);
> >> +
> >> +	slaunch_copy_dmar_table(txt);
> >> +
> >> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> >> +
> >> +	pr_info("Intel TXT setup complete\n");
> >> +}
> >> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
> >> index a3414af..5d1ac8d 100644
> >> --- a/drivers/iommu/intel/dmar.c
> >> +++ b/drivers/iommu/intel/dmar.c
> >> @@ -28,6 +28,7 @@
> >>   #include <linux/iommu.h>
> >>   #include <linux/numa.h>
> >>   #include <linux/limits.h>
> >> +#include <linux/slaunch.h>
> >>   #include <asm/irq_remapping.h>
> >>   
> >>   #include "iommu.h"
> >> @@ -660,6 +661,9 @@ static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar,
> >>   	 */
> >>   	dmar_tbl = tboot_get_dmar_table(dmar_tbl);
> >>   
> >> +	/* If Secure Launch is active, it has similar logic */
> >> +	dmar_tbl = slaunch_get_dmar_table(dmar_tbl);
> >> +
> >>   	dmar = (struct acpi_table_dmar *)dmar_tbl;
> >>   	if (!dmar)
> >>   		return -ENODEV;
> >> -- 
> >> 1.8.3.1
> > 
> > Is it possible to test TXT in QEMU? Never done it so that's why I'm
> > asking.
>
> I would be if emulation of the GETSEC leaf functions were added to QEMU. 
> AFAIK there is no public implementation of this at present.

That's a shame. I have one NUC7 which I use sometimes to test SGX
patches but I don't think it scales to TXT (have to check).

BR, Jarkko

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

* Re: [PATCH v6 08/14] x86: Secure Launch kernel late boot stub
@ 2023-05-24  2:55         ` Jarkko Sakkinen
  0 siblings, 0 replies; 200+ messages in thread
From: Jarkko Sakkinen @ 2023-05-24  2:55 UTC (permalink / raw)
  To: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, tglx, mingo, bp, hpa, ardb, mjg59, James.Bottomley,
	luto, nivedita, kanth.ghatraju, trenchboot-devel

On Fri May 12, 2023 at 6:58 PM EEST, Ross Philipson wrote:
> On 5/10/23 19:02, Jarkko Sakkinen wrote:
> > On Thu May 4, 2023 at 5:50 PM EEST, Ross Philipson wrote:
> >> The routine slaunch_setup is called out of the x86 specific setup_arch
> >> routine during early kernel boot. After determining what platform is
> >> present, various operations specific to that platform occur. This
> >> includes finalizing setting for the platform late launch and verifying
> >> that memory protections are in place.
> >>
> >> For TXT, this code also reserves the original compressed kernel setup
> >> area where the APs were left looping so that this memory cannot be used.
> >>
> >> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
> >> ---
> >>   arch/x86/kernel/Makefile   |   1 +
> >>   arch/x86/kernel/setup.c    |   3 +
> >>   arch/x86/kernel/slaunch.c  | 497 +++++++++++++++++++++++++++++++++++++++++++++
> >>   drivers/iommu/intel/dmar.c |   4 +
> >>   4 files changed, 505 insertions(+)
> >>   create mode 100644 arch/x86/kernel/slaunch.c
> >>
> >> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> >> index dd61752..3d2a33e 100644
> >> --- a/arch/x86/kernel/Makefile
> >> +++ b/arch/x86/kernel/Makefile
> >> @@ -72,6 +72,7 @@ obj-$(CONFIG_X86_32)		+= tls.o
> >>   obj-$(CONFIG_IA32_EMULATION)	+= tls.o
> >>   obj-y				+= step.o
> >>   obj-$(CONFIG_INTEL_TXT)		+= tboot.o
> >> +obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
> >>   obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
> >>   obj-y				+= stacktrace.o
> >>   obj-y				+= cpu/
> >> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> >> index 16babff..592c09e 100644
> >> --- a/arch/x86/kernel/setup.c
> >> +++ b/arch/x86/kernel/setup.c
> >> @@ -21,6 +21,7 @@
> >>   #include <linux/root_dev.h>
> >>   #include <linux/hugetlb.h>
> >>   #include <linux/tboot.h>
> >> +#include <linux/slaunch.h>
> > 
> > Only because of pure curiosity: what made you choose this location in
> > the middle for the new include? :-)
>
> Only because Secure Launch is like TBOOT. No other real reason.
>
> > 
> >>   #include <linux/usb/xhci-dbgp.h>
> >>   #include <linux/static_call.h>
> >>   #include <linux/swiotlb.h>
> >> @@ -1063,6 +1064,8 @@ void __init setup_arch(char **cmdline_p)
> >>   	early_gart_iommu_check();
> >>   #endif
> >>   
> >> +	slaunch_setup_txt();
> >> +
> >>   	/*
> >>   	 * partially used pages are not usable - thus
> >>   	 * we are rounding upwards:
> >> diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
> >> new file mode 100644
> >> index 0000000..7dba088
> >> --- /dev/null
> >> +++ b/arch/x86/kernel/slaunch.c
> >> @@ -0,0 +1,497 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * Secure Launch late validation/setup and finalization support.
> >> + *
> >> + * Copyright (c) 2022, Oracle and/or its affiliates.
> >> + */
> >> +
> >> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> >> +
> >> +#include <linux/linkage.h>
> >> +#include <linux/mm.h>
> >> +#include <linux/io.h>
> >> +#include <linux/uaccess.h>
> >> +#include <linux/security.h>
> >> +#include <linux/memblock.h>
> >> +#include <asm/segment.h>
> >> +#include <asm/sections.h>
> >> +#include <asm/tlbflush.h>
> >> +#include <asm/e820/api.h>
> >> +#include <asm/setup.h>
> >> +#include <linux/slr_table.h>
> >> +#include <linux/slaunch.h>
> >> +
> >> +static u32 sl_flags;
> >> +static struct sl_ap_wake_info ap_wake_info;
> >> +static u64 evtlog_addr;
> >> +static u32 evtlog_size;
> >> +static u64 vtd_pmr_lo_size;
> >> +
> >> +/* This should be plenty of room */
> >> +static u8 txt_dmar[PAGE_SIZE] __aligned(16);
> >> +
> >> +u32 slaunch_get_flags(void)
> >> +{
> >> +	return sl_flags;
> >> +}
> >> +EXPORT_SYMBOL(slaunch_get_flags);
> >> +
> >> +struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
> >> +{
> >> +	return &ap_wake_info;
> >> +}
> >> +
> >> +struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
> >> +{
> >> +	/* The DMAR is only stashed and provided via TXT on Intel systems */
> >> +	if (memcmp(txt_dmar, "DMAR", 4))
> >> +		return dmar;
> >> +
> >> +	return (struct acpi_table_header *)(&txt_dmar[0]);
> >> +}
> >> +
> >> +void __noreturn slaunch_txt_reset(void __iomem *txt,
> >> +				  const char *msg, u64 error)
> >> +{
> >> +	u64 one = 1, val;
> >> +
> >> +	pr_err("%s", msg);
> >> +
> >> +	/*
> >> +	 * This performs a TXT reset with a sticky error code. The reads of
> >> +	 * TXT_CR_E2STS act as barriers.
> >> +	 */
> >> +	memcpy_toio(txt + TXT_CR_ERRORCODE, &error, sizeof(error));
> >> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> >> +	memcpy_toio(txt + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
> >> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> >> +	memcpy_toio(txt + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
> >> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> >> +	memcpy_toio(txt + TXT_CR_CMD_RESET, &one, sizeof(one));
> >> +
> >> +	for ( ; ; )
> >> +		asm volatile ("hlt");
> >> +
> >> +	unreachable();
> >> +}
> >> +
> >> +/*
> >> + * The TXT heap is too big to map all at once with early_ioremap
> >> + * so it is done a table at a time.
> >> + */
> >> +static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
> >> +					     u32 bytes)
> >> +{
> >> +	u64 base, size, offset = 0;
> >> +	void *heap;
> >> +	int i;
> >> +
> >> +	if (type > TXT_SINIT_TABLE_MAX)
> >> +		slaunch_txt_reset(txt,
> >> +			"Error invalid table type for early heap walk\n",
> >> +			SL_ERROR_HEAP_WALK);
> > 
> > Align with 'txt'.
>
> Ack
>
> > 
> >> +
> >> +	memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
> >> +	memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
> >> +
> >> +	/* Iterate over heap tables looking for table of "type" */
> >> +	for (i = 0; i < type; i++) {
> >> +		base += offset;
> >> +		heap = early_memremap(base, sizeof(u64));
> >> +		if (!heap)
> >> +			slaunch_txt_reset(txt,
> >> +				"Error early_memremap of heap for heap walk\n",
> >> +				SL_ERROR_HEAP_MAP);
> >> +
> >> +		offset = *((u64 *)heap);
> >> +
> >> +		/*
> >> +		 * After the first iteration, any offset of zero is invalid and
> >> +		 * implies the TXT heap is corrupted.
> >> +		 */
> >> +		if (!offset)
> >> +			slaunch_txt_reset(txt,
> >> +				"Error invalid 0 offset in heap walk\n",
> >> +				SL_ERROR_HEAP_ZERO_OFFSET);
> >> +
> >> +		early_memunmap(heap, sizeof(u64));
> >> +	}
> >> +
> >> +	/* Skip the size field at the head of each table */
> >> +	base += sizeof(u64);
> >> +	heap = early_memremap(base, bytes);
> >> +	if (!heap)
> >> +		slaunch_txt_reset(txt,
> >> +				  "Error early_memremap of heap section\n",
> >> +				  SL_ERROR_HEAP_MAP);
> >> +
> >> +	return heap;
> >> +}
> >> +
> >> +static void __init txt_early_put_heap_table(void *addr, unsigned long size)
> >> +{
> >> +	early_memunmap(addr, size);
> >> +}
> >> +
> >> +/*
> >> + * TXT uses a special set of VTd registers to protect all of memory from DMA
> >> + * until the IOMMU can be programmed to protect memory. There is the low
> >> + * memory PMR that can protect all memory up to 4G. The high memory PRM can
> >> + * be setup to protect all memory beyond 4Gb. Validate that these values cover
> >> + * what is expected.
> >> + */
> >> +static void __init slaunch_verify_pmrs(void __iomem *txt)
> >> +{
> >> +	struct txt_os_sinit_data *os_sinit_data;
> >> +	u32 field_offset, err = 0;
> >> +	const char *errmsg = "";
> >> +	unsigned long last_pfn;
> >> +
> >> +	field_offset = offsetof(struct txt_os_sinit_data, lcp_po_base);
> >> +	os_sinit_data = txt_early_get_heap_table(txt, TXT_OS_SINIT_DATA_TABLE,
> >> +						 field_offset);
> >> +
> >> +	/* Save a copy */
> >> +	vtd_pmr_lo_size = os_sinit_data->vtd_pmr_lo_size;
> >> +
> >> +	last_pfn = e820__end_of_ram_pfn();
> >> +
> >> +	/*
> >> +	 * First make sure the hi PMR covers all memory above 4G. In the
> >> +	 * unlikely case where there is < 4G on the system, the hi PMR will
> >> +	 * not be set.
> >> +	 */
> >> +	if (os_sinit_data->vtd_pmr_hi_base != 0x0ULL) {
> >> +		if (os_sinit_data->vtd_pmr_hi_base != 0x100000000ULL) {
> >> +			err = SL_ERROR_HI_PMR_BASE;
> >> +			errmsg =  "Error hi PMR base\n";
> >> +			goto out;
> >> +		}
> >> +
> >> +		if (PFN_PHYS(last_pfn) > os_sinit_data->vtd_pmr_hi_base +
> >> +		    os_sinit_data->vtd_pmr_hi_size) {
> >> +			err = SL_ERROR_HI_PMR_SIZE;
> >> +			errmsg = "Error hi PMR size\n";
> >> +			goto out;
> >> +		}
> >> +	}
> >> +
> >> +	/*
> >> +	 * Lo PMR base should always be 0. This was already checked in
> >> +	 * early stub.
> >> +	 */
> >> +
> >> +	/*
> >> +	 * Check that if the kernel was loaded below 4G, that it is protected
> >> +	 * by the lo PMR. Note this is the decompressed kernel. The ACM would
> >> +	 * have ensured the compressed kernel (the MLE image) was protected.
> >> +	 */
> >> +	if ((__pa_symbol(_end) < 0x100000000ULL) &&
> >> +	    (__pa_symbol(_end) > os_sinit_data->vtd_pmr_lo_size)) {
> >> +		err = SL_ERROR_LO_PMR_MLE;
> >> +		errmsg = "Error lo PMR does not cover MLE kernel\n";
> >> +	}
> >> +
> >> +	/*
> >> +	 * Other regions of interest like boot param, AP wake block, cmdline
> >> +	 * already checked for PMR coverage in the early stub code.
> >> +	 */
> >> +
> >> +out:
> >> +	txt_early_put_heap_table(os_sinit_data, field_offset);
> >> +
> >> +	if (err)
> >> +		slaunch_txt_reset(txt, errmsg, err);
> >> +}
> >> +
> >> +static void __init slaunch_txt_reserve_range(u64 base, u64 size)
> >> +{
> >> +	int type;
> >> +
> >> +	type = e820__get_entry_type(base, base + size - 1);
> >> +	if (type == E820_TYPE_RAM) {
> >> +		pr_info("memblock reserve base: %llx size: %llx\n", base, size);
> >> +		memblock_reserve(base, size);
> >> +	}
> >> +}
> >> +
> >> +/*
> >> + * For Intel, certain regions of memory must be marked as reserved by putting
> >> + * them on the memblock reserved list if they are not already e820 reserved.
> >> + * This includes:
> >> + *  - The TXT HEAP
> >> + *  - The ACM area
> >> + *  - The TXT private register bank
> >> + *  - The MDR list sent to the MLE by the ACM (see TXT specification)
> >> + *  (Normally the above are properly reserved by firmware but if it was not
> >> + *  done, reserve them now)
> >> + *  - The AP wake block
> >> + *  - TPM log external to the TXT heap
> >> + *
> >> + * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
> >> + * the low PMR must be reservered too.
> >> + */
> >> +static void __init slaunch_txt_reserve(void __iomem *txt)
> >> +{
> >> +	struct txt_sinit_memory_descriptor_record *mdr;
> >> +	struct txt_sinit_mle_data *sinit_mle_data;
> >> +	u64 base, size, heap_base, heap_size;
> >> +	u32 mdrnum, mdroffset, mdrslen;
> >> +	u32 field_offset, i;
> >> +	void *mdrs;
> >> +
> >> +	base = TXT_PRIV_CONFIG_REGS_BASE;
> >> +	size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
> >> +	slaunch_txt_reserve_range(base, size);
> >> +
> >> +	memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
> >> +	memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
> >> +	slaunch_txt_reserve_range(heap_base, heap_size);
> >> +
> >> +	memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
> >> +	memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
> >> +	slaunch_txt_reserve_range(base, size);
> >> +
> >> +	field_offset = offsetof(struct txt_sinit_mle_data,
> >> +				sinit_vtd_dmar_table_size);
> >> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> >> +						  field_offset);
> >> +
> >> +	mdrnum = sinit_mle_data->num_of_sinit_mdrs;
> >> +	mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
> >> +
> >> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
> >> +
> >> +	if (!mdrnum)
> >> +		goto nomdr;
> >> +
> >> +	mdrslen = mdrnum * sizeof(struct txt_sinit_memory_descriptor_record);
> >> +
> >> +	mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> >> +					mdroffset + mdrslen - 8);
> >> +
> >> +	mdr = mdrs + mdroffset - 8;
> >> +
> >> +	for (i = 0; i < mdrnum; i++, mdr++) {
> >> +		/* Spec says some entries can have length 0, ignore them */
> >> +		if (mdr->type > 0 && mdr->length > 0)
> >> +			slaunch_txt_reserve_range(mdr->address, mdr->length);
> >> +	}
> >> +
> >> +	txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
> >> +
> >> +nomdr:
> >> +	slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
> >> +				  ap_wake_info.ap_wake_block_size);
> >> +
> >> +	/*
> >> +	 * Earlier checks ensured that the event log was properly situated
> >> +	 * either inside the TXT heap or outside. This is a check to see if the
> >> +	 * event log needs to be reserved. If it is in the TXT heap, it is
> >> +	 * already reserved.
> >> +	 */
> >> +	if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
> >> +		slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
> >> +
> >> +	for (i = 0; i < e820_table->nr_entries; i++) {
> >> +		base = e820_table->entries[i].addr;
> >> +		size = e820_table->entries[i].size;
> >> +		if ((base >= vtd_pmr_lo_size) && (base < 0x100000000ULL))
> >> +			slaunch_txt_reserve_range(base, size);
> >> +		else if ((base < vtd_pmr_lo_size) &&
> >> +			 (base + size > vtd_pmr_lo_size))
> >> +			slaunch_txt_reserve_range(vtd_pmr_lo_size,
> >> +						  base + size - vtd_pmr_lo_size);
> >> +	}
> >> +}
> >> +
> >> +/*
> >> + * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
> >> + * It is stored in the TXT heap. Fetch it from there and make it available
> >> + * to the IOMMU driver.
> >> + */
> >> +static void __init slaunch_copy_dmar_table(void __iomem *txt)
> >> +{
> >> +	struct txt_sinit_mle_data *sinit_mle_data;
> >> +	u32 field_offset, dmar_size, dmar_offset;
> >> +	void *dmar;
> >> +
> >> +	memset(&txt_dmar, 0, PAGE_SIZE);
> >> +
> >> +	field_offset = offsetof(struct txt_sinit_mle_data,
> >> +				processor_scrtm_status);
> >> +	sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> >> +						  field_offset);
> >> +
> >> +	dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
> >> +	dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
> >> +
> >> +	txt_early_put_heap_table(sinit_mle_data, field_offset);
> >> +
> >> +	if (!dmar_size || !dmar_offset)
> >> +		slaunch_txt_reset(txt,
> >> +				  "Error invalid DMAR table values\n",
> >> +				  SL_ERROR_HEAP_INVALID_DMAR);
> >> +
> >> +	if (unlikely(dmar_size > PAGE_SIZE))
> >> +		slaunch_txt_reset(txt,
> >> +				  "Error DMAR too big to store\n",
> >> +				  SL_ERROR_HEAP_DMAR_SIZE);
> >> +
> >> +
> >> +	dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
> >> +					dmar_offset + dmar_size - 8);
> >> +	if (!dmar)
> >> +		slaunch_txt_reset(txt,
> >> +				  "Error early_ioremap of DMAR\n",
> >> +				  SL_ERROR_HEAP_DMAR_MAP);
> >> +
> >> +	memcpy(&txt_dmar[0], dmar + dmar_offset - 8, dmar_size);
> >> +
> >> +	txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
> >> +}
> >> +
> >> +/*
> >> + * The location of the safe AP wake code block is stored in the TXT heap.
> >> + * Fetch needed values here in the early init code for later use in SMP
> >> + * startup.
> >> + *
> >> + * Also get the TPM event log values are in the SLRT and have to be fetched.
> >> + * They will be put on the memblock reserve list later.
> >> + */
> >> +static void __init slaunch_fetch_values(void __iomem *txt)
> >> +{
> >> +	struct txt_os_mle_data *os_mle_data;
> >> +	struct slr_entry_log_info *log_info;
> >> +	struct slr_table *slrt;
> >> +	u8 *jmp_offset;
> >> +	u32 size;
> >> +
> >> +	os_mle_data = txt_early_get_heap_table(txt, TXT_OS_MLE_DATA_TABLE,
> >> +					       sizeof(*os_mle_data));
> >> +
> >> +	ap_wake_info.ap_wake_block = os_mle_data->ap_wake_block;
> >> +	ap_wake_info.ap_wake_block_size = os_mle_data->ap_wake_block_size;
> >> +
> >> +	jmp_offset = os_mle_data->mle_scratch + SL_SCRATCH_AP_JMP_OFFSET;
> >> +	ap_wake_info.ap_jmp_offset = *((u32 *)jmp_offset);
> >> +
> >> +	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, sizeof(*slrt));
> >> +	if (!slrt)
> >> +		slaunch_txt_reset(txt,
> >> +			"Error early_memremap of SLRT failed\n",
> >> +			SL_ERROR_SLRT_MAP);
> >> +
> >> +	size = slrt->size;
> >> +	early_memunmap(slrt, sizeof(*slrt));
> >> +
> >> +	slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, size);
> >> +	if (!slrt)
> >> +		slaunch_txt_reset(txt,
> >> +			"Error early_memremap of SLRT failed\n",
> >> +			SL_ERROR_SLRT_MAP);
> >> +
> >> +	log_info = (struct slr_entry_log_info *)
> >> +		slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
> >> +
> >> +	if (!log_info)
> >> +		slaunch_txt_reset(txt,
> >> +				  "SLRT missing logging info entry\n",
> >> +				  SL_ERROR_SLRT_MISSING_ENTRY);
> >> +
> >> +	evtlog_addr = log_info->addr;
> >> +	evtlog_size = log_info->size;
> >> +
> >> +	early_memunmap(slrt, size);
> >> +
> >> +	txt_early_put_heap_table(os_mle_data, sizeof(*os_mle_data));
> >> +}
> >> +
> >> +/*
> >> + * Intel TXT specific late stub setup and validation.
> >> + */
> >> +void __init slaunch_setup_txt(void)
> >> +{
> >> +	u64 one = TXT_REGVALUE_ONE, val;
> >> +	void __iomem *txt;
> >> +
> >> +	if (!boot_cpu_has(X86_FEATURE_SMX))
> >> +		return;
> >> +
> >> +	/*
> >> +	 * If booted through secure launch entry point, the loadflags
> >> +	 * option will be set.
> >> +	 */
> >> +	if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
> >> +		return;
> >> +
> >> +	/*
> >> +	 * See if SENTER was done by reading the status register in the
> >> +	 * public space. If the public register space cannot be read, TXT may
> >> +	 * be disabled.
> >> +	 */
> >> +	txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
> >> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> >> +	if (!txt)
> >> +		return;
> >> +
> >> +	memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
> >> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> >> +
> >> +	/* SENTER should have been done */
> >> +	if (!(val & TXT_SENTER_DONE_STS))
> >> +		panic("Error TXT.STS SENTER_DONE not set\n");
> >> +
> >> +	/* SEXIT should have been cleared */
> >> +	if (val & TXT_SEXIT_DONE_STS)
> >> +		panic("Error TXT.STS SEXIT_DONE set\n");
> >> +
> >> +	/* Now we want to use the private register space */
> >> +	txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
> >> +			    TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> >> +	if (!txt) {
> >> +		/* This is really bad, no where to go from here */
> >> +		panic("Error early_ioremap of TXT priv registers\n");
> >> +	}
> >> +
> >> +	/*
> >> +	 * Try to read the Intel VID from the TXT private registers to see if
> >> +	 * TXT measured launch happened properly and the private space is
> >> +	 * available.
> >> +	 */
> >> +	memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
> >> +	if ((val & 0xffff) != 0x8086) {
> >> +		/*
> >> +		 * Can't do a proper TXT reset since it appears something is
> >> +		 * wrong even though SENTER happened and it should be in SMX
> >> +		 * mode.
> >> +		 */
> >> +		panic("Invalid TXT vendor ID, not in SMX mode\n");
> >> +	}
> >> +
> >> +	/* Set flags so subsequent code knows the status of the launch */
> >> +	sl_flags |= (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT);
> >> +
> >> +	/*
> >> +	 * Reading the proper DIDVID from the private register space means we
> >> +	 * are in SMX mode and private registers are open for read/write.
> >> +	 */
> >> +
> >> +	/* On Intel, have to handle TPM localities via TXT */
> >> +	memcpy_toio(txt + TXT_CR_CMD_SECRETS, &one, sizeof(one));
> >> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> >> +	memcpy_toio(txt + TXT_CR_CMD_OPEN_LOCALITY1, &one, sizeof(one));
> >> +	memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
> >> +
> >> +	slaunch_fetch_values(txt);
> >> +
> >> +	slaunch_verify_pmrs(txt);
> >> +
> >> +	slaunch_txt_reserve(txt);
> >> +
> >> +	slaunch_copy_dmar_table(txt);
> >> +
> >> +	early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
> >> +
> >> +	pr_info("Intel TXT setup complete\n");
> >> +}
> >> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
> >> index a3414af..5d1ac8d 100644
> >> --- a/drivers/iommu/intel/dmar.c
> >> +++ b/drivers/iommu/intel/dmar.c
> >> @@ -28,6 +28,7 @@
> >>   #include <linux/iommu.h>
> >>   #include <linux/numa.h>
> >>   #include <linux/limits.h>
> >> +#include <linux/slaunch.h>
> >>   #include <asm/irq_remapping.h>
> >>   
> >>   #include "iommu.h"
> >> @@ -660,6 +661,9 @@ static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar,
> >>   	 */
> >>   	dmar_tbl = tboot_get_dmar_table(dmar_tbl);
> >>   
> >> +	/* If Secure Launch is active, it has similar logic */
> >> +	dmar_tbl = slaunch_get_dmar_table(dmar_tbl);
> >> +
> >>   	dmar = (struct acpi_table_dmar *)dmar_tbl;
> >>   	if (!dmar)
> >>   		return -ENODEV;
> >> -- 
> >> 1.8.3.1
> > 
> > Is it possible to test TXT in QEMU? Never done it so that's why I'm
> > asking.
>
> I would be if emulation of the GETSEC leaf functions were added to QEMU. 
> AFAIK there is no public implementation of this at present.

That's a shame. I have one NUC7 which I use sometimes to test SGX
patches but I don't think it scales to TXT (have to check).

BR, Jarkko

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-16  1:45           ` Matthew Garrett
@ 2023-06-15 18:00             ` Ross Philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-06-15 18:00 UTC (permalink / raw)
  To: Matthew Garrett, Daniel P. Smith
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel, Ross Philipson

On 5/15/23 21:45, Matthew Garrett wrote:
> On Mon, May 15, 2023 at 09:11:15PM -0400, Daniel P. Smith wrote:
>> On 5/12/23 12:17, Ross Philipson wrote:
>>> This is a good point. At this point it is really something we
>>> overlooked. We will have to revisit this and figure out the best way to
>>> find the final event log depending on how things booted.
>>
>> I believe Ross misunderstood what you were asking for here. There are two
>> reasons this is not possible or desired. The first reason is that on Intel,
>> the DRTM log is not initialized by TrenchBoot code in the preamble. It is
>> only responsible for allocating a buffer and recording the location in the
>> TXT structures. When the SINIT ACM is executed, it will initialize the log
>> and record the measurement that CPU sent directly to the TPM and then the
>> measurements the ACM makes of the environment. If you pointed at the SRTM
>> log, then the ACM would write over existing log, which I don't think you
>> want. Now if you pointed at the tail end of the SRTM log, you would still
>> end up with a second, separate log that just happens to be memory adjacent.
> 
> Ok. I think it would be clearer if either the function names or some
> comments expressly indicated that this refers to the DRTM event log and
> that that's a separate entity from the SRTM one, "event log" on its own
> is likely to cause people to think of the existing log rather than
> associate it with something else.
> 

That can be done, thanks.

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-06-15 18:00             ` Ross Philipson
  0 siblings, 0 replies; 200+ messages in thread
From: Ross Philipson @ 2023-06-15 18:00 UTC (permalink / raw)
  To: Matthew Garrett, Daniel P. Smith
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel, Ross Philipson

On 5/15/23 21:45, Matthew Garrett wrote:
> On Mon, May 15, 2023 at 09:11:15PM -0400, Daniel P. Smith wrote:
>> On 5/12/23 12:17, Ross Philipson wrote:
>>> This is a good point. At this point it is really something we
>>> overlooked. We will have to revisit this and figure out the best way to
>>> find the final event log depending on how things booted.
>>
>> I believe Ross misunderstood what you were asking for here. There are two
>> reasons this is not possible or desired. The first reason is that on Intel,
>> the DRTM log is not initialized by TrenchBoot code in the preamble. It is
>> only responsible for allocating a buffer and recording the location in the
>> TXT structures. When the SINIT ACM is executed, it will initialize the log
>> and record the measurement that CPU sent directly to the TPM and then the
>> measurements the ACM makes of the environment. If you pointed at the SRTM
>> log, then the ACM would write over existing log, which I don't think you
>> want. Now if you pointed at the tail end of the SRTM log, you would still
>> end up with a second, separate log that just happens to be memory adjacent.
> 
> Ok. I think it would be clearer if either the function names or some
> comments expressly indicated that this refers to the DRTM event log and
> that that's a separate entity from the SRTM one, "event log" on its own
> is likely to cause people to think of the existing log rather than
> associate it with something else.
> 

That can be done, thanks.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
  2023-05-12 10:47     ` Matthew Garrett
@ 2023-06-16 16:44       ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-06-16 16:44 UTC (permalink / raw)
  To: Matthew Garrett, Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel


On 5/12/23 06:47, Matthew Garrett wrote:
> On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
>> +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
>> +built with KASLR disabled::
> 
> Why does Secure Launch not interoperate with KASLR?
> 
> Re: IOMMUs

Until the IOMMU driver comes online, memory is protected by the PMRs 
regions requested by the Preamble (pre-launch code) in accordance with 
Intel TXT specifications and configured by the ACM. The KASLR randomizer 
will run before the IOMMU driver is able to come online and ensure 
frames used by the kernel are protected as well as frames that a driver 
may registered in a BAR are not blocked.

>> +It is recommended that no other command line options should be set to override
>> +the defaults above.
> 
> What happens if they are? Does doing so change the security posture of
> the system? If so, will the measurements be different in a way that
> demonstrates the system is in an insecure state?
> 

In an early version of the patch series this was enforced when turning 
on Secure Launch, but concerns were raised over this approach and was 
asked to allow the user to be able to shoot themselves in the foot. 
Overriding these values could render either an insecure state and/or an 
unstable system.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
@ 2023-06-16 16:44       ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-06-16 16:44 UTC (permalink / raw)
  To: Matthew Garrett, Ross Philipson
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel


On 5/12/23 06:47, Matthew Garrett wrote:
> On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
>> +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
>> +built with KASLR disabled::
> 
> Why does Secure Launch not interoperate with KASLR?
> 
> Re: IOMMUs

Until the IOMMU driver comes online, memory is protected by the PMRs 
regions requested by the Preamble (pre-launch code) in accordance with 
Intel TXT specifications and configured by the ACM. The KASLR randomizer 
will run before the IOMMU driver is able to come online and ensure 
frames used by the kernel are protected as well as frames that a driver 
may registered in a BAR are not blocked.

>> +It is recommended that no other command line options should be set to override
>> +the defaults above.
> 
> What happens if they are? Does doing so change the security posture of
> the system? If so, will the measurements be different in a way that
> demonstrates the system is in an insecure state?
> 

In an early version of the patch series this was enforced when turning 
on Secure Launch, but concerns were raised over this approach and was 
asked to allow the user to be able to shoot themselves in the foot. 
Overriding these values could render either an insecure state and/or an 
unstable system.

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
  2023-06-16 16:44       ` Daniel P. Smith
@ 2023-06-16 16:54         ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-06-16 16:54 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, Jun 16, 2023 at 12:44:27PM -0400, Daniel P. Smith wrote:
> 
> On 5/12/23 06:47, Matthew Garrett wrote:
> > On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
> > > +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
> > > +built with KASLR disabled::
> > 
> > Why does Secure Launch not interoperate with KASLR?
> > 
> > Re: IOMMUs
> 
> Until the IOMMU driver comes online, memory is protected by the PMRs regions
> requested by the Preamble (pre-launch code) in accordance with Intel TXT
> specifications and configured by the ACM. The KASLR randomizer will run
> before the IOMMU driver is able to come online and ensure frames used by the
> kernel are protected as well as frames that a driver may registered in a BAR
> are not blocked.

This seems unfortunate. Presumably we're not able to modify the PMRs at 
this point? This also seems like a potential issue for IOMMU config in 
general - the presumption is that the firmware should be configuring the 
IOMMU in such a way that DMA-capable devices can't attack the firmware 
while we're in the boot environment, and if KASLR is leaving a window 
there then it seems like we'd need to fix that?
 
> > > +It is recommended that no other command line options should be set to override
> > > +the defaults above.
> > 
> > What happens if they are? Does doing so change the security posture of
> > the system? If so, will the measurements be different in a way that
> > demonstrates the system is in an insecure state?
> > 
> 
> In an early version of the patch series this was enforced when turning on
> Secure Launch, but concerns were raised over this approach and was asked to
> allow the user to be able to shoot themselves in the foot. Overriding these
> values could render either an insecure state and/or an unstable system.

If we're in an insecure state, is that something that would show up in 
the form of different measurements?

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
@ 2023-06-16 16:54         ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-06-16 16:54 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, Jun 16, 2023 at 12:44:27PM -0400, Daniel P. Smith wrote:
> 
> On 5/12/23 06:47, Matthew Garrett wrote:
> > On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
> > > +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
> > > +built with KASLR disabled::
> > 
> > Why does Secure Launch not interoperate with KASLR?
> > 
> > Re: IOMMUs
> 
> Until the IOMMU driver comes online, memory is protected by the PMRs regions
> requested by the Preamble (pre-launch code) in accordance with Intel TXT
> specifications and configured by the ACM. The KASLR randomizer will run
> before the IOMMU driver is able to come online and ensure frames used by the
> kernel are protected as well as frames that a driver may registered in a BAR
> are not blocked.

This seems unfortunate. Presumably we're not able to modify the PMRs at 
this point? This also seems like a potential issue for IOMMU config in 
general - the presumption is that the firmware should be configuring the 
IOMMU in such a way that DMA-capable devices can't attack the firmware 
while we're in the boot environment, and if KASLR is leaving a window 
there then it seems like we'd need to fix that?
 
> > > +It is recommended that no other command line options should be set to override
> > > +the defaults above.
> > 
> > What happens if they are? Does doing so change the security posture of
> > the system? If so, will the measurements be different in a way that
> > demonstrates the system is in an insecure state?
> > 
> 
> In an early version of the patch series this was enforced when turning on
> Secure Launch, but concerns were raised over this approach and was asked to
> allow the user to be able to shoot themselves in the foot. Overriding these
> values could render either an insecure state and/or an unstable system.

If we're in an insecure state, is that something that would show up in 
the form of different measurements?

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
  2023-06-16 16:54         ` Matthew Garrett
@ 2023-06-16 18:21           ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-06-16 18:21 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 6/16/23 12:54, Matthew Garrett wrote:
> On Fri, Jun 16, 2023 at 12:44:27PM -0400, Daniel P. Smith wrote:
>>
>> On 5/12/23 06:47, Matthew Garrett wrote:
>>> On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
>>>> +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
>>>> +built with KASLR disabled::
>>>
>>> Why does Secure Launch not interoperate with KASLR?
>>>
>>> Re: IOMMUs
>>
>> Until the IOMMU driver comes online, memory is protected by the PMRs regions
>> requested by the Preamble (pre-launch code) in accordance with Intel TXT
>> specifications and configured by the ACM. The KASLR randomizer will run
>> before the IOMMU driver is able to come online and ensure frames used by the
>> kernel are protected as well as frames that a driver may registered in a BAR
>> are not blocked.
> 
> This seems unfortunate. Presumably we're not able to modify the PMRs at
> this point? This also seems like a potential issue for IOMMU config in
> general - the presumption is that the firmware should be configuring the
> IOMMU in such a way that DMA-capable devices can't attack the firmware
> while we're in the boot environment, and if KASLR is leaving a window
> there then it seems like we'd need to fix that?

While unfortunate, it is a bit of the nature of the problem KASLR is 
attempting to address. If you know in advance where kernel pages are 
going to live and the frames that will be used for DMA, then have you 
not defeated the purpose of the randomization? As for the firmware use 
of the IOMMU, I am fairly certain those tables will get invalidated by 
the ACM when it is setting up the PMRs.

>>>> +It is recommended that no other command line options should be set to override
>>>> +the defaults above.
>>>
>>> What happens if they are? Does doing so change the security posture of
>>> the system? If so, will the measurements be different in a way that
>>> demonstrates the system is in an insecure state?
>>>
>>
>> In an early version of the patch series this was enforced when turning on
>> Secure Launch, but concerns were raised over this approach and was asked to
>> allow the user to be able to shoot themselves in the foot. Overriding these
>> values could render either an insecure state and/or an unstable system.
> 
> If we're in an insecure state, is that something that would show up in
> the form of different measurements?

Yes, you would get a different measurement for the commandline. If you 
are thinking in terms of attestation, I would expect that the 
attestation measurement db would have a record for an acceptable 
commandline and would determine the system to be in an unknown state if 
it did not match.

While the idea could be explored to create measurements based on 
configurations of kernel subsystems, this would likely entail 
instrumentation in those subsystems to assert a measurement to their 
configuration. Maybe IMA could cover something like this? It would 
definitely enable the ability to make deeper assessments about the state 
of a system, but I think this is out of the scope of what Secure Launch 
is attempting to do.

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

* Re: [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation
@ 2023-06-16 18:21           ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-06-16 18:21 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 6/16/23 12:54, Matthew Garrett wrote:
> On Fri, Jun 16, 2023 at 12:44:27PM -0400, Daniel P. Smith wrote:
>>
>> On 5/12/23 06:47, Matthew Garrett wrote:
>>> On Thu, May 04, 2023 at 02:50:11PM +0000, Ross Philipson wrote:
>>>> +Secure Launch does not interoperate with KASLR. If possible, the MLE should be
>>>> +built with KASLR disabled::
>>>
>>> Why does Secure Launch not interoperate with KASLR?
>>>
>>> Re: IOMMUs
>>
>> Until the IOMMU driver comes online, memory is protected by the PMRs regions
>> requested by the Preamble (pre-launch code) in accordance with Intel TXT
>> specifications and configured by the ACM. The KASLR randomizer will run
>> before the IOMMU driver is able to come online and ensure frames used by the
>> kernel are protected as well as frames that a driver may registered in a BAR
>> are not blocked.
> 
> This seems unfortunate. Presumably we're not able to modify the PMRs at
> this point? This also seems like a potential issue for IOMMU config in
> general - the presumption is that the firmware should be configuring the
> IOMMU in such a way that DMA-capable devices can't attack the firmware
> while we're in the boot environment, and if KASLR is leaving a window
> there then it seems like we'd need to fix that?

While unfortunate, it is a bit of the nature of the problem KASLR is 
attempting to address. If you know in advance where kernel pages are 
going to live and the frames that will be used for DMA, then have you 
not defeated the purpose of the randomization? As for the firmware use 
of the IOMMU, I am fairly certain those tables will get invalidated by 
the ACM when it is setting up the PMRs.

>>>> +It is recommended that no other command line options should be set to override
>>>> +the defaults above.
>>>
>>> What happens if they are? Does doing so change the security posture of
>>> the system? If so, will the measurements be different in a way that
>>> demonstrates the system is in an insecure state?
>>>
>>
>> In an early version of the patch series this was enforced when turning on
>> Secure Launch, but concerns were raised over this approach and was asked to
>> allow the user to be able to shoot themselves in the foot. Overriding these
>> values could render either an insecure state and/or an unstable system.
> 
> If we're in an insecure state, is that something that would show up in
> the form of different measurements?

Yes, you would get a different measurement for the commandline. If you 
are thinking in terms of attestation, I would expect that the 
attestation measurement db would have a record for an acceptable 
commandline and would determine the system to be in an unknown state if 
it did not match.

While the idea could be explored to create measurements based on 
configurations of kernel subsystems, this would likely entail 
instrumentation in those subsystems to assert a measurement to their 
configuration. Maybe IMA could cover something like this? It would 
definitely enable the ability to make deeper assessments about the state 
of a system, but I think this is out of the scope of what Secure Launch 
is attempting to do.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-05-16  1:43             ` Matthew Garrett
@ 2023-06-16 20:01               ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-06-16 20:01 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/15/23 21:43, Matthew Garrett wrote:
> On Mon, May 15, 2023 at 08:41:00PM -0400, Daniel P. Smith wrote:
>> On 5/15/23 17:22, Matthew Garrett wrote:
>>> What if I don't use grub, but use something that behaves equivalently?
>>> Which value should be used here?
>>
>> Generally we would request that the bootloader submit a request to register
>> for a value to be reserved in the spec. That aside, the intent here is to
>> allow for the possibility for the DLE handler to be independent from the
>> bootloader, but this does not have to be this way. If a non-open entity
>> decides to produce their own implementation, they can freely use a
>> unallocated value at their own risk that it could be allocated to another
>> bootloader in the future. Though in this scenario it likely would not matter
>> as the non-open DLE handler would only be present when the non-open
>> bootloader was present.
> 
> Is the expectation that the DLE will always be shipped with the
> bootloader? I think I'm not entirely clear on what's consuming this and
> why.
> 

No, in fact, an early idea proposed by a pair of us in the TrenchBoot 
community was to have it live either as a Runtime Service that was 
loaded by a UEFI app or in the coreboot UEFI payload.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-06-16 20:01               ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-06-16 20:01 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/15/23 21:43, Matthew Garrett wrote:
> On Mon, May 15, 2023 at 08:41:00PM -0400, Daniel P. Smith wrote:
>> On 5/15/23 17:22, Matthew Garrett wrote:
>>> What if I don't use grub, but use something that behaves equivalently?
>>> Which value should be used here?
>>
>> Generally we would request that the bootloader submit a request to register
>> for a value to be reserved in the spec. That aside, the intent here is to
>> allow for the possibility for the DLE handler to be independent from the
>> bootloader, but this does not have to be this way. If a non-open entity
>> decides to produce their own implementation, they can freely use a
>> unallocated value at their own risk that it could be allocated to another
>> bootloader in the future. Though in this scenario it likely would not matter
>> as the non-open DLE handler would only be present when the non-open
>> bootloader was present.
> 
> Is the expectation that the DLE will always be shipped with the
> bootloader? I think I'm not entirely clear on what's consuming this and
> why.
> 

No, in fact, an early idea proposed by a pair of us in the TrenchBoot 
community was to have it live either as a Runtime Service that was 
loaded by a UEFI app or in the coreboot UEFI payload.

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-06-16 20:01               ` Daniel P. Smith
@ 2023-06-16 20:15                 ` Matthew Garrett
  -1 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-06-16 20:15 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, Jun 16, 2023 at 04:01:09PM -0400, Daniel P. Smith wrote:
> On 5/15/23 21:43, Matthew Garrett wrote:
> > On Mon, May 15, 2023 at 08:41:00PM -0400, Daniel P. Smith wrote:
> > > On 5/15/23 17:22, Matthew Garrett wrote:
> > > > What if I don't use grub, but use something that behaves equivalently?
> > > > Which value should be used here?
> > > 
> > > Generally we would request that the bootloader submit a request to register
> > > for a value to be reserved in the spec. That aside, the intent here is to
> > > allow for the possibility for the DLE handler to be independent from the
> > > bootloader, but this does not have to be this way. If a non-open entity
> > > decides to produce their own implementation, they can freely use a
> > > unallocated value at their own risk that it could be allocated to another
> > > bootloader in the future. Though in this scenario it likely would not matter
> > > as the non-open DLE handler would only be present when the non-open
> > > bootloader was present.
> > 
> > Is the expectation that the DLE will always be shipped with the
> > bootloader? I think I'm not entirely clear on what's consuming this and
> > why.
> > 
> 
> No, in fact, an early idea proposed by a pair of us in the TrenchBoot
> community was to have it live either as a Runtime Service that was loaded by
> a UEFI app or in the coreboot UEFI payload.

Ok, then I think I'm still confused. If I want to write a new bootloader 
but make use of the existing DLE, what contract am I establishing and 
what value should I be putting in here?

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-06-16 20:15                 ` Matthew Garrett
  0 siblings, 0 replies; 200+ messages in thread
From: Matthew Garrett @ 2023-06-16 20:15 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On Fri, Jun 16, 2023 at 04:01:09PM -0400, Daniel P. Smith wrote:
> On 5/15/23 21:43, Matthew Garrett wrote:
> > On Mon, May 15, 2023 at 08:41:00PM -0400, Daniel P. Smith wrote:
> > > On 5/15/23 17:22, Matthew Garrett wrote:
> > > > What if I don't use grub, but use something that behaves equivalently?
> > > > Which value should be used here?
> > > 
> > > Generally we would request that the bootloader submit a request to register
> > > for a value to be reserved in the spec. That aside, the intent here is to
> > > allow for the possibility for the DLE handler to be independent from the
> > > bootloader, but this does not have to be this way. If a non-open entity
> > > decides to produce their own implementation, they can freely use a
> > > unallocated value at their own risk that it could be allocated to another
> > > bootloader in the future. Though in this scenario it likely would not matter
> > > as the non-open DLE handler would only be present when the non-open
> > > bootloader was present.
> > 
> > Is the expectation that the DLE will always be shipped with the
> > bootloader? I think I'm not entirely clear on what's consuming this and
> > why.
> > 
> 
> No, in fact, an early idea proposed by a pair of us in the TrenchBoot
> community was to have it live either as a Runtime Service that was loaded by
> a UEFI app or in the coreboot UEFI payload.

Ok, then I think I'm still confused. If I want to write a new bootloader 
but make use of the existing DLE, what contract am I establishing and 
what value should I be putting in here?

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
  2023-06-16 20:15                 ` Matthew Garrett
@ 2023-07-07 19:31                   ` Daniel P. Smith
  -1 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-07-07 19:31 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 6/16/23 16:15, Matthew Garrett wrote:
> On Fri, Jun 16, 2023 at 04:01:09PM -0400, Daniel P. Smith wrote:
>> On 5/15/23 21:43, Matthew Garrett wrote:
>>> On Mon, May 15, 2023 at 08:41:00PM -0400, Daniel P. Smith wrote:
>>>> On 5/15/23 17:22, Matthew Garrett wrote:
>>>>> What if I don't use grub, but use something that behaves equivalently?
>>>>> Which value should be used here?
>>>>
>>>> Generally we would request that the bootloader submit a request to register
>>>> for a value to be reserved in the spec. That aside, the intent here is to
>>>> allow for the possibility for the DLE handler to be independent from the
>>>> bootloader, but this does not have to be this way. If a non-open entity
>>>> decides to produce their own implementation, they can freely use a
>>>> unallocated value at their own risk that it could be allocated to another
>>>> bootloader in the future. Though in this scenario it likely would not matter
>>>> as the non-open DLE handler would only be present when the non-open
>>>> bootloader was present.
>>>
>>> Is the expectation that the DLE will always be shipped with the
>>> bootloader? I think I'm not entirely clear on what's consuming this and
>>> why.
>>>
>>
>> No, in fact, an early idea proposed by a pair of us in the TrenchBoot
>> community was to have it live either as a Runtime Service that was loaded by
>> a UEFI app or in the coreboot UEFI payload.
> 
> Ok, then I think I'm still confused. If I want to write a new bootloader
> but make use of the existing DLE, what contract am I establishing and
> what value should I be putting in here?

Apologies on the delayed response, vacation and what not.

I believe I know where the confusion is coming from, let me see if I can 
explain better by why that field came about. The motivation for the SLRT 
came out of our agreement to use a callback mechanism to support 
entering efi-stub and then going back to a dynamic launch aware hook to 
complete the initiation of the dynamic launch. The SLRT was devised as a 
platform and kernel agnostic means to handle the launch. As such, there 
was a desire to use that interface, and the underlying DLE code, whether 
GRUB was launching the kernel via the UEFI interface or the traditional 
interface. Skipping the details, but it boils down to the fact that in 
the non-UEFI case, functionality from core GRUB was needed. As a result, 
to provide maximum flexibility for other bootloaders, and to make it 
easier on us, we add the ability to pass a context object across the 
interface. Thus allowing GRUB's DLE handler to have a single entry that 
could be called externally by efi-stub or directly from GRUB proper.

IOW, the bootloader context is a means to provide a bootloader with them 
means to implement a private interface between the bootloader proper and 
a DLE handler that it installed into memory should its implementation 
require it.

There is an underlying question within your question, and that is of 
reuse. In this case, we wrote GRUB's DLE handler was written 
specifically to be used by GRUB. It was written to provide a stable and 
demonstrable implementation of the SL interface. In the future it may 
get refactored or a common standalone implementation, e.g., the 
previously mentioned UEFI runtime service, may arise that would be 
reusable by multiple bootloaders.

I hope this helped explain the purpose and use of this area of the 
table. Please let me know if it did not.

V/r,
DPS

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 04/14] x86: Secure Launch Resource Table header file
@ 2023-07-07 19:31                   ` Daniel P. Smith
  0 siblings, 0 replies; 200+ messages in thread
From: Daniel P. Smith @ 2023-07-07 19:31 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi, tglx, mingo, bp, hpa,
	ardb, James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 6/16/23 16:15, Matthew Garrett wrote:
> On Fri, Jun 16, 2023 at 04:01:09PM -0400, Daniel P. Smith wrote:
>> On 5/15/23 21:43, Matthew Garrett wrote:
>>> On Mon, May 15, 2023 at 08:41:00PM -0400, Daniel P. Smith wrote:
>>>> On 5/15/23 17:22, Matthew Garrett wrote:
>>>>> What if I don't use grub, but use something that behaves equivalently?
>>>>> Which value should be used here?
>>>>
>>>> Generally we would request that the bootloader submit a request to register
>>>> for a value to be reserved in the spec. That aside, the intent here is to
>>>> allow for the possibility for the DLE handler to be independent from the
>>>> bootloader, but this does not have to be this way. If a non-open entity
>>>> decides to produce their own implementation, they can freely use a
>>>> unallocated value at their own risk that it could be allocated to another
>>>> bootloader in the future. Though in this scenario it likely would not matter
>>>> as the non-open DLE handler would only be present when the non-open
>>>> bootloader was present.
>>>
>>> Is the expectation that the DLE will always be shipped with the
>>> bootloader? I think I'm not entirely clear on what's consuming this and
>>> why.
>>>
>>
>> No, in fact, an early idea proposed by a pair of us in the TrenchBoot
>> community was to have it live either as a Runtime Service that was loaded by
>> a UEFI app or in the coreboot UEFI payload.
> 
> Ok, then I think I'm still confused. If I want to write a new bootloader
> but make use of the existing DLE, what contract am I establishing and
> what value should I be putting in here?

Apologies on the delayed response, vacation and what not.

I believe I know where the confusion is coming from, let me see if I can 
explain better by why that field came about. The motivation for the SLRT 
came out of our agreement to use a callback mechanism to support 
entering efi-stub and then going back to a dynamic launch aware hook to 
complete the initiation of the dynamic launch. The SLRT was devised as a 
platform and kernel agnostic means to handle the launch. As such, there 
was a desire to use that interface, and the underlying DLE code, whether 
GRUB was launching the kernel via the UEFI interface or the traditional 
interface. Skipping the details, but it boils down to the fact that in 
the non-UEFI case, functionality from core GRUB was needed. As a result, 
to provide maximum flexibility for other bootloaders, and to make it 
easier on us, we add the ability to pass a context object across the 
interface. Thus allowing GRUB's DLE handler to have a single entry that 
could be called externally by efi-stub or directly from GRUB proper.

IOW, the bootloader context is a means to provide a bootloader with them 
means to implement a private interface between the bootloader proper and 
a DLE handler that it installed into memory should its implementation 
require it.

There is an underlying question within your question, and that is of 
reuse. In this case, we wrote GRUB's DLE handler was written 
specifically to be used by GRUB. It was written to provide a stable and 
demonstrable implementation of the SL interface. In the future it may 
get refactored or a common standalone implementation, e.g., the 
previously mentioned UEFI runtime service, may arise that would be 
reusable by multiple bootloaders.

I hope this helped explain the purpose and use of this area of the 
table. Please let me know if it did not.

V/r,
DPS

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
  2023-05-12 18:04     ` Thomas Gleixner
@ 2023-09-20 21:40       ` ross.philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: ross.philipson @ 2023-09-20 21:40 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, mingo, bp, hpa, ardb, mjg59, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On 5/12/23 11:04 AM, Thomas Gleixner wrote:
> 
> On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
>> +
>> +/* CPUID: leaf 1, ECX, SMX feature bit */
>> +#define X86_FEATURE_BIT_SMX	(1 << 6)
>> +
>> +/* Can't include apiddef.h in asm */
> 
> Why not? All it needs is a #ifndef __ASSEMBLY__ guard around the C parts.
> 
>> +#define XAPIC_ENABLE	(1 << 11)
>> +#define X2APIC_ENABLE	(1 << 10)
>> +
>> +/* Can't include traps.h in asm */
> 
> NMI_VECTOR is defined in irq_vectors.h which just has a include
> <linux/threads.h> for no real good reason.
> 
>> +#define X86_TRAP_NMI	2
> 
> <SNIP>
> 
>> +/*
>> + * See the comment in head_64.S for detailed informatoin on what this macro
>> + * is used for.
>> + */
>> +#define rva(X) ((X) - sl_stub_entry)
> 
> I'm having a hard time to find that comment in head_64.S. At least it's
> not in this patch.
> 
>> +.Lsl_ap_cs:
>> +	/* Load the relocated AP IDT */
> [ 11 more citation lines. Click/Enter to show. ]
>> +	lidt	(sl_ap_idt_desc - sl_txt_ap_wake_begin)(%ecx)
>> +
>> +	/* Fixup MTRRs and misc enable MSR on APs too */
>> +	call	sl_txt_load_regs
>> +
>> +	/* Enable SMI with GETSEC[SMCTRL] */
>> +	GETSEC $(SMX_X86_GETSEC_SMCTRL)
>> +
>> +	/* IRET-to-self can be used to enable NMIs which SENTER disabled */
>> +	leal	rva(.Lnmi_enabled_ap)(%ebx), %eax
>> +	pushfl
>> +	pushl	$(__SL32_CS)
>> +	pushl	%eax
>> +	iret
> 
> So from here on any NMI which hits the AP before it can reach the wait
> loop will corrupt EDX...
> 
>> +/* This is the beginning of the relocated AP wake code block */
>> +	.global sl_txt_ap_wake_begin
> [ 10 more citation lines. Click/Enter to show. ]
>> +sl_txt_ap_wake_begin:
>> +
>> +	/*
>> +	 * Wait for NMI IPI in the relocated AP wake block which was provided
>> +	 * and protected in the memory map by the prelaunch code. Leave all
>> +	 * other interrupts masked since we do not expect anything but an NMI.
>> +	 */
>> +	xorl	%edx, %edx
>> +
>> +1:
>> +	hlt
>> +	testl	%edx, %edx
>> +	jz	1b
> 
> This really makes me nervous. A stray NMI and the AP starts going.
> 
> Can't this NMI just bring the AP out of HLT w/o changing any state and
> the AP evaluates a memory location which indicates whether it should
> start up or not.

I have switched the existing code to use MONITOR/MWAIT and got rid of 
the use of the NMIs here. I am currently using a monitor variable on the 
stack of each AP but I think I may refactor that. The next step is to 
rebase this work on top of your hotplug patchset. Is the code in your 
devel repo on the hotplug branch still the latest bits?

I had a question - more a request for your thoughts on this. I am 
currently assuming a cache line size and alignment of 64b for the 
monitor variable location. Do you think this is sufficient for x86 
platforms or do I need to dynamically find a way to read the CPUID 
information for MONITOR and get my size/alignment values from there?

Thanks
Ross Philipson

> 
>> +	/*
>> +	 * This is the long absolute jump to the 32b Secure Launch protected
>> +	 * mode stub code in the rmpiggy. The jump address will be fixed in
> 
> Providing an actual name for the stub might spare to rummage through
> code to figure out where this is supposed to jump to.
> 
>> +	 * the SMP boot code when the first AP is brought up. This whole area
>> +	 * is provided and protected in the memory map by the prelaunch code.
> [ 2 more citation lines. Click/Enter to show. ]
>> +	 */
>> +	.byte	0xea
>> +sl_ap_jmp_offset:
>> +	.long	0x00000000
>> +	.word	__SL32_CS
> 
> Thanks,
> 
> 	tglx


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

* Re: [PATCH v6 07/14] x86: Secure Launch kernel early boot stub
@ 2023-09-20 21:40       ` ross.philipson
  0 siblings, 0 replies; 200+ messages in thread
From: ross.philipson @ 2023-09-20 21:40 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel, x86, linux-integrity, linux-doc,
	linux-crypto, iommu, kexec, linux-efi
  Cc: dpsmith, mingo, bp, hpa, ardb, mjg59, James.Bottomley, luto,
	nivedita, kanth.ghatraju, trenchboot-devel

On 5/12/23 11:04 AM, Thomas Gleixner wrote:
> 
> On Thu, May 04 2023 at 14:50, Ross Philipson wrote:
>> +
>> +/* CPUID: leaf 1, ECX, SMX feature bit */
>> +#define X86_FEATURE_BIT_SMX	(1 << 6)
>> +
>> +/* Can't include apiddef.h in asm */
> 
> Why not? All it needs is a #ifndef __ASSEMBLY__ guard around the C parts.
> 
>> +#define XAPIC_ENABLE	(1 << 11)
>> +#define X2APIC_ENABLE	(1 << 10)
>> +
>> +/* Can't include traps.h in asm */
> 
> NMI_VECTOR is defined in irq_vectors.h which just has a include
> <linux/threads.h> for no real good reason.
> 
>> +#define X86_TRAP_NMI	2
> 
> <SNIP>
> 
>> +/*
>> + * See the comment in head_64.S for detailed informatoin on what this macro
>> + * is used for.
>> + */
>> +#define rva(X) ((X) - sl_stub_entry)
> 
> I'm having a hard time to find that comment in head_64.S. At least it's
> not in this patch.
> 
>> +.Lsl_ap_cs:
>> +	/* Load the relocated AP IDT */
> [ 11 more citation lines. Click/Enter to show. ]
>> +	lidt	(sl_ap_idt_desc - sl_txt_ap_wake_begin)(%ecx)
>> +
>> +	/* Fixup MTRRs and misc enable MSR on APs too */
>> +	call	sl_txt_load_regs
>> +
>> +	/* Enable SMI with GETSEC[SMCTRL] */
>> +	GETSEC $(SMX_X86_GETSEC_SMCTRL)
>> +
>> +	/* IRET-to-self can be used to enable NMIs which SENTER disabled */
>> +	leal	rva(.Lnmi_enabled_ap)(%ebx), %eax
>> +	pushfl
>> +	pushl	$(__SL32_CS)
>> +	pushl	%eax
>> +	iret
> 
> So from here on any NMI which hits the AP before it can reach the wait
> loop will corrupt EDX...
> 
>> +/* This is the beginning of the relocated AP wake code block */
>> +	.global sl_txt_ap_wake_begin
> [ 10 more citation lines. Click/Enter to show. ]
>> +sl_txt_ap_wake_begin:
>> +
>> +	/*
>> +	 * Wait for NMI IPI in the relocated AP wake block which was provided
>> +	 * and protected in the memory map by the prelaunch code. Leave all
>> +	 * other interrupts masked since we do not expect anything but an NMI.
>> +	 */
>> +	xorl	%edx, %edx
>> +
>> +1:
>> +	hlt
>> +	testl	%edx, %edx
>> +	jz	1b
> 
> This really makes me nervous. A stray NMI and the AP starts going.
> 
> Can't this NMI just bring the AP out of HLT w/o changing any state and
> the AP evaluates a memory location which indicates whether it should
> start up or not.

I have switched the existing code to use MONITOR/MWAIT and got rid of 
the use of the NMIs here. I am currently using a monitor variable on the 
stack of each AP but I think I may refactor that. The next step is to 
rebase this work on top of your hotplug patchset. Is the code in your 
devel repo on the hotplug branch still the latest bits?

I had a question - more a request for your thoughts on this. I am 
currently assuming a cache line size and alignment of 64b for the 
monitor variable location. Do you think this is sufficient for x86 
platforms or do I need to dynamically find a way to read the CPUID 
information for MONITOR and get my size/alignment values from there?

Thanks
Ross Philipson

> 
>> +	/*
>> +	 * This is the long absolute jump to the 32b Secure Launch protected
>> +	 * mode stub code in the rmpiggy. The jump address will be fixed in
> 
> Providing an actual name for the stub might spare to rummage through
> code to figure out where this is supposed to jump to.
> 
>> +	 * the SMP boot code when the first AP is brought up. This whole area
>> +	 * is provided and protected in the memory map by the prelaunch code.
> [ 2 more citation lines. Click/Enter to show. ]
>> +	 */
>> +	.byte	0xea
>> +sl_ap_jmp_offset:
>> +	.long	0x00000000
>> +	.word	__SL32_CS
> 
> Thanks,
> 
> 	tglx


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

* Re: [PATCH v6 05/14] x86: Secure Launch main header file
  2023-05-12 16:10       ` Ross Philipson
@ 2023-10-31 21:37         ` ross.philipson
  -1 siblings, 0 replies; 200+ messages in thread
From: ross.philipson @ 2023-10-31 21:37 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/12/23 9:10 AM, Ross Philipson wrote:
> On 5/12/23 07:00, Matthew Garrett wrote:
>> On Thu, May 04, 2023 at 02:50:14PM +0000, Ross Philipson wrote:
>>
>>> +static inline int tpm12_log_event(void *evtlog_base, u32 evtlog_size,
>>> +                  u32 event_size, void *event)
>>> +{
>>> +    struct tpm12_event_log_header *evtlog =
>>> +        (struct tpm12_event_log_header *)evtlog_base;
>>> +
>>> +    if (memcmp(evtlog->signature, TPM12_EVTLOG_SIGNATURE,
>>> +           sizeof(TPM12_EVTLOG_SIGNATURE)))
>>> +        return -EINVAL;
>>> +
>>> +    if (evtlog->container_size > evtlog_size)
>>> +        return -EINVAL;
>>> +
>>> +    if (evtlog->next_event_offset + event_size > 
>>> evtlog->container_size)
>>> +        return -E2BIG;
>>> +
>>> +    memcpy(evtlog_base + evtlog->next_event_offset, event, event_size);
>>> +    evtlog->next_event_offset += event_size;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static inline int tpm20_log_event(struct 
>>> txt_heap_event_log_pointer2_1_element *elem,
>>> +                  void *evtlog_base, u32 evtlog_size,
>>> +                  u32 event_size, void *event)
>>> +{
>>> +    struct tcg_pcr_event *header =
>>> +        (struct tcg_pcr_event *)evtlog_base;
>>> +
>>> +    /* Has to be at least big enough for the signature */
>>> +    if (header->event_size < sizeof(TCG_SPECID_SIG))
>>> +        return -EINVAL;
>>> +
>>> +    if (memcmp((u8 *)header + sizeof(struct tcg_pcr_event),
>>> +           TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
>>> +        return -EINVAL;
>>> +
>>> +    if (elem->allocated_event_container_size > evtlog_size)
>>> +        return -EINVAL;
>>> +
>>> +    if (elem->next_record_offset + event_size >
>>> +        elem->allocated_event_container_size)
>>> +        return -E2BIG;
>>> +
>>> +    memcpy(evtlog_base + elem->next_record_offset, event, event_size);
>>> +    elem->next_record_offset += event_size;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>
>> These seem like they'd potentially be useful outside the context of SL,
>> maybe put them in a more generic location? Very much a nice to have, not
>> a blocker from my side.
> 
> Yea we can look into finding a nice home somewhere in the TPM event log 
> code for these.

After looking at it, it seems we would have to drag a whole bunch of TXT 
related structures into the TPM event log code. I don't think this is 
really worth it for what these functions do.

Thanks
Ross

> 
>>
>>> +/*
>>> + * External functions avalailable in mainline kernel.
>>
>> Nit: "available"
> 
> Ack
> 
> Thanks
> 
>>
> 


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

* Re: [PATCH v6 05/14] x86: Secure Launch main header file
@ 2023-10-31 21:37         ` ross.philipson
  0 siblings, 0 replies; 200+ messages in thread
From: ross.philipson @ 2023-10-31 21:37 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-kernel, x86, linux-integrity, linux-doc, linux-crypto,
	iommu, kexec, linux-efi, dpsmith, tglx, mingo, bp, hpa, ardb,
	James.Bottomley, luto, nivedita, kanth.ghatraju,
	trenchboot-devel

On 5/12/23 9:10 AM, Ross Philipson wrote:
> On 5/12/23 07:00, Matthew Garrett wrote:
>> On Thu, May 04, 2023 at 02:50:14PM +0000, Ross Philipson wrote:
>>
>>> +static inline int tpm12_log_event(void *evtlog_base, u32 evtlog_size,
>>> +                  u32 event_size, void *event)
>>> +{
>>> +    struct tpm12_event_log_header *evtlog =
>>> +        (struct tpm12_event_log_header *)evtlog_base;
>>> +
>>> +    if (memcmp(evtlog->signature, TPM12_EVTLOG_SIGNATURE,
>>> +           sizeof(TPM12_EVTLOG_SIGNATURE)))
>>> +        return -EINVAL;
>>> +
>>> +    if (evtlog->container_size > evtlog_size)
>>> +        return -EINVAL;
>>> +
>>> +    if (evtlog->next_event_offset + event_size > 
>>> evtlog->container_size)
>>> +        return -E2BIG;
>>> +
>>> +    memcpy(evtlog_base + evtlog->next_event_offset, event, event_size);
>>> +    evtlog->next_event_offset += event_size;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static inline int tpm20_log_event(struct 
>>> txt_heap_event_log_pointer2_1_element *elem,
>>> +                  void *evtlog_base, u32 evtlog_size,
>>> +                  u32 event_size, void *event)
>>> +{
>>> +    struct tcg_pcr_event *header =
>>> +        (struct tcg_pcr_event *)evtlog_base;
>>> +
>>> +    /* Has to be at least big enough for the signature */
>>> +    if (header->event_size < sizeof(TCG_SPECID_SIG))
>>> +        return -EINVAL;
>>> +
>>> +    if (memcmp((u8 *)header + sizeof(struct tcg_pcr_event),
>>> +           TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
>>> +        return -EINVAL;
>>> +
>>> +    if (elem->allocated_event_container_size > evtlog_size)
>>> +        return -EINVAL;
>>> +
>>> +    if (elem->next_record_offset + event_size >
>>> +        elem->allocated_event_container_size)
>>> +        return -E2BIG;
>>> +
>>> +    memcpy(evtlog_base + elem->next_record_offset, event, event_size);
>>> +    elem->next_record_offset += event_size;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>
>> These seem like they'd potentially be useful outside the context of SL,
>> maybe put them in a more generic location? Very much a nice to have, not
>> a blocker from my side.
> 
> Yea we can look into finding a nice home somewhere in the TPM event log 
> code for these.

After looking at it, it seems we would have to drag a whole bunch of TXT 
related structures into the TPM event log code. I don't think this is 
really worth it for what these functions do.

Thanks
Ross

> 
>>
>>> +/*
>>> + * External functions avalailable in mainline kernel.
>>
>> Nit: "available"
> 
> Ack
> 
> Thanks
> 
>>
> 


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

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

end of thread, other threads:[~2023-10-31 21:38 UTC | newest]

Thread overview: 200+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-04 14:50 [PATCH v6 00/14] x86: Trenchboot secure dynamic launch Linux kernel support Ross Philipson
2023-05-04 14:50 ` Ross Philipson
2023-05-04 14:50 ` [PATCH v6 01/14] x86/boot: Place kernel_info at a fixed offset Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-04 14:50 ` [PATCH v6 02/14] Documentation/x86: Secure Launch kernel documentation Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-05 16:19   ` Simon Horman
2023-05-05 16:19     ` Simon Horman
2023-05-05 17:32     ` Ross Philipson
2023-05-05 17:32       ` Ross Philipson
2023-05-06  8:48   ` Bagas Sanjaya
2023-05-06  8:48     ` Bagas Sanjaya
2023-05-10 15:41     ` Ross Philipson
2023-05-10 15:41       ` Ross Philipson
2023-05-12 10:47   ` Matthew Garrett
2023-05-12 10:47     ` Matthew Garrett
2023-06-16 16:44     ` Daniel P. Smith
2023-06-16 16:44       ` Daniel P. Smith
2023-06-16 16:54       ` Matthew Garrett
2023-06-16 16:54         ` Matthew Garrett
2023-06-16 18:21         ` Daniel P. Smith
2023-06-16 18:21           ` Daniel P. Smith
2023-05-12 13:19   ` Thomas Gleixner
2023-05-12 13:19     ` Thomas Gleixner
2023-05-04 14:50 ` [PATCH v6 03/14] x86: Secure Launch Kconfig Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-04 14:50 ` [PATCH v6 04/14] x86: Secure Launch Resource Table header file Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-05 16:22   ` Simon Horman
2023-05-05 16:22     ` Simon Horman
2023-05-05 17:34     ` Ross Philipson
2023-05-05 17:34       ` Ross Philipson
2023-05-10 23:04   ` Jarkko Sakkinen
2023-05-10 23:04     ` Jarkko Sakkinen
2023-05-15 20:58     ` Daniel P. Smith
2023-05-15 20:58       ` Daniel P. Smith
2023-05-12 10:55   ` Matthew Garrett
2023-05-12 10:55     ` Matthew Garrett
2023-05-15 21:15     ` Daniel P. Smith
2023-05-15 21:15       ` Daniel P. Smith
2023-05-15 21:22       ` Matthew Garrett
2023-05-15 21:22         ` Matthew Garrett
2023-05-16  0:41         ` Daniel P. Smith
2023-05-16  0:41           ` Daniel P. Smith
2023-05-16  1:43           ` Matthew Garrett
2023-05-16  1:43             ` Matthew Garrett
2023-06-16 20:01             ` Daniel P. Smith
2023-06-16 20:01               ` Daniel P. Smith
2023-06-16 20:15               ` Matthew Garrett
2023-06-16 20:15                 ` Matthew Garrett
2023-07-07 19:31                 ` Daniel P. Smith
2023-07-07 19:31                   ` Daniel P. Smith
2023-05-04 14:50 ` [PATCH v6 05/14] x86: Secure Launch main " Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-05 16:25   ` Simon Horman
2023-05-05 16:25     ` Simon Horman
2023-05-05 17:37     ` Ross Philipson
2023-05-05 17:37       ` Ross Philipson
2023-05-12 11:00   ` Matthew Garrett
2023-05-12 11:00     ` Matthew Garrett
2023-05-12 16:10     ` Ross Philipson
2023-05-12 16:10       ` Ross Philipson
2023-10-31 21:37       ` ross.philipson
2023-10-31 21:37         ` ross.philipson
2023-05-04 14:50 ` [PATCH v6 06/14] x86: Add early SHA support for Secure Launch early measurements Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-05 16:34   ` Simon Horman
2023-05-05 16:34     ` Simon Horman
2023-05-09 16:09     ` Daniel P. Smith
2023-05-09 16:09       ` Daniel P. Smith
2023-05-10  1:21   ` Eric Biggers
2023-05-10  1:21     ` Eric Biggers
2023-05-10 22:28     ` Jarkko Sakkinen
2023-05-10 22:28       ` Jarkko Sakkinen
2023-05-12 11:04     ` Matthew Garrett
2023-05-12 11:04       ` Matthew Garrett
2023-05-12 11:18       ` Ard Biesheuvel
2023-05-12 11:18         ` Ard Biesheuvel
2023-05-12 11:28         ` Matthew Garrett
2023-05-12 11:28           ` Matthew Garrett
2023-05-12 11:58           ` Ard Biesheuvel
2023-05-12 11:58             ` Ard Biesheuvel
2023-05-12 12:24             ` Andrew Cooper
2023-05-12 12:24               ` Andrew Cooper
2023-05-14 18:18               ` Eric Biggers
2023-05-14 18:18                 ` Eric Biggers
2023-05-14 19:11                 ` Matthew Garrett
2023-05-14 19:11                   ` Matthew Garrett
2023-05-12 13:24           ` Thomas Gleixner
2023-05-12 13:24             ` Thomas Gleixner
2023-05-12 16:13             ` Matthew Garrett
2023-05-12 16:13               ` Matthew Garrett
2023-05-12 18:17               ` Thomas Gleixner
2023-05-12 18:17                 ` Thomas Gleixner
2023-05-12 19:12                 ` Matthew Garrett
2023-05-12 19:12                   ` Matthew Garrett
2023-05-12 19:42                   ` Andrew Cooper
2023-05-12 19:42                     ` Andrew Cooper
2023-05-15 21:23     ` Daniel P. Smith
2023-05-15 21:23       ` Daniel P. Smith
2023-05-11  3:33   ` Herbert Xu
2023-05-11  3:33     ` Herbert Xu
2023-05-16  0:50     ` Daniel P. Smith
2023-05-16  0:50       ` Daniel P. Smith
2023-05-04 14:50 ` [PATCH v6 07/14] x86: Secure Launch kernel early boot stub Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-05 17:47   ` Simon Horman
2023-05-05 17:47     ` Simon Horman
2023-05-05 18:58     ` Ross Philipson
2023-05-05 18:58       ` Ross Philipson
2023-05-05 19:46       ` Simon Horman
2023-05-05 19:46         ` Simon Horman
2023-05-12 11:26   ` Matthew Garrett
2023-05-12 11:26     ` Matthew Garrett
2023-05-12 16:17     ` Ross Philipson
2023-05-12 16:17       ` Ross Philipson
2023-05-12 16:27       ` Matthew Garrett
2023-05-12 16:27         ` Matthew Garrett
2023-05-16  1:11       ` Daniel P. Smith
2023-05-16  1:11         ` Daniel P. Smith
2023-05-16  1:45         ` Matthew Garrett
2023-05-16  1:45           ` Matthew Garrett
2023-06-15 18:00           ` Ross Philipson
2023-06-15 18:00             ` Ross Philipson
2023-05-12 18:04   ` Thomas Gleixner
2023-05-12 18:04     ` Thomas Gleixner
2023-05-15 20:13     ` Ross Philipson
2023-05-15 20:13       ` Ross Philipson
2023-09-20 21:40     ` ross.philipson
2023-09-20 21:40       ` ross.philipson
2023-05-04 14:50 ` [PATCH v6 08/14] x86: Secure Launch kernel late " Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-05 17:52   ` Simon Horman
2023-05-05 17:52     ` Simon Horman
2023-05-05 18:59     ` Ross Philipson
2023-05-05 18:59       ` Ross Philipson
2023-05-10 23:02   ` Jarkko Sakkinen
2023-05-10 23:02     ` Jarkko Sakkinen
2023-05-12 15:58     ` Ross Philipson
2023-05-12 15:58       ` Ross Philipson
2023-05-24  2:55       ` Jarkko Sakkinen
2023-05-24  2:55         ` Jarkko Sakkinen
2023-05-12 15:44   ` Thomas Gleixner
2023-05-12 15:44     ` Thomas Gleixner
2023-05-15 20:06     ` Ross Philipson
2023-05-15 20:06       ` Ross Philipson
2023-05-04 14:50 ` [PATCH v6 09/14] x86: Secure Launch SMP bringup support Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-05 17:54   ` Simon Horman
2023-05-05 17:54     ` Simon Horman
2023-05-05 18:59     ` Ross Philipson
2023-05-05 18:59       ` Ross Philipson
2023-05-10 22:55   ` Jarkko Sakkinen
2023-05-10 22:55     ` Jarkko Sakkinen
2023-05-11 16:21     ` Ross Philipson
2023-05-11 16:21       ` Ross Philipson
2023-05-12 18:02   ` Thomas Gleixner
2023-05-12 18:02     ` Thomas Gleixner
2023-05-15 20:19     ` Ross Philipson
2023-05-15 20:19       ` Ross Philipson
2023-05-04 14:50 ` [PATCH v6 10/14] kexec: Secure Launch kexec SEXIT support Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-04 14:50 ` [PATCH v6 11/14] reboot: Secure Launch SEXIT support on reboot paths Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-12 11:40   ` Matthew Garrett
2023-05-12 11:40     ` Matthew Garrett
2023-05-15 18:16     ` Ross Philipson
2023-05-15 18:16       ` Ross Philipson
2023-05-16  1:23       ` Daniel P. Smith
2023-05-16  1:23         ` Daniel P. Smith
2023-05-04 14:50 ` [PATCH v6 12/14] x86: Secure Launch late initcall platform module Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-05 19:42   ` Simon Horman
2023-05-05 19:42     ` Simon Horman
2023-05-08 15:07     ` Ross Philipson
2023-05-08 15:07       ` Ross Philipson
2023-05-10 22:39   ` Jarkko Sakkinen
2023-05-10 22:39     ` Jarkko Sakkinen
2023-05-12 15:53     ` Ross Philipson
2023-05-12 15:53       ` Ross Philipson
2023-05-10 22:40   ` Jarkko Sakkinen
2023-05-10 22:40     ` Jarkko Sakkinen
2023-05-12 15:54     ` Ross Philipson
2023-05-12 15:54       ` Ross Philipson
2023-05-04 14:50 ` [PATCH v6 13/14] tpm: Allow locality 2 to be set when initializing the TPM for Secure Launch Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-12 11:43   ` Matthew Garrett
2023-05-12 11:43     ` Matthew Garrett
2023-05-12 16:22     ` Ross Philipson
2023-05-12 16:22       ` Ross Philipson
2023-05-16  1:37       ` Daniel P. Smith
2023-05-16  1:37         ` Daniel P. Smith
2023-05-04 14:50 ` [PATCH v6 14/14] x86: EFI stub DRTM launch support " Ross Philipson
2023-05-04 14:50   ` Ross Philipson
2023-05-05  8:39 ` [PATCH v6 00/14] x86: Trenchboot secure dynamic launch Linux kernel support Bagas Sanjaya
2023-05-05  8:39   ` Bagas Sanjaya
2023-05-05 15:45   ` Ross Philipson
2023-05-05 15:45     ` Ross Philipson
2023-05-06  7:56     ` Bagas Sanjaya
2023-05-06  7:56       ` Bagas Sanjaya

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.