[SLOF] [PATCH v4 10/33] tpm: Add support for a TPM menu to control the state of the TPM

Stefan Berger stefanb at linux.vnet.ibm.com
Thu Dec 12 07:27:05 AEDT 2019


This patch provides an addtional menu that enables the user to control
certain aspects of the TPM's state.

If a working TPM has been detected, the menu will look like this:

The TPM is enabled, active, does not have an owner but one can be installed.

To configure the TPM, choose one of the following actions:

d. Disable the TPM
v. Deactivate the TPM
p. Prevent installation of an owner

Note: To fully use the TPM it must be enabled and activated.

Press escape to continue boot.

This menu can be access by pressing the 't' key during boot. The menu will not
be shown if no TPM is available.

Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
---
 board-qemu/slof/OF.fs       |   3 +
 board-qemu/slof/vtpm-sml.fs | 189 ++++++++++++++++++++++++++++++++++++
 lib/libtpm/tcgbios.c        |  30 +++++-
 lib/libtpm/tcgbios.h        |   9 ++
 lib/libtpm/tpm.code         |  20 ++++
 lib/libtpm/tpm.in           |   2 +
 slof/fs/start-up.fs         |   9 ++
 7 files changed, 261 insertions(+), 1 deletion(-)

diff --git a/board-qemu/slof/OF.fs b/board-qemu/slof/OF.fs
index 3e117ad..7bdd6ea 100644
--- a/board-qemu/slof/OF.fs
+++ b/board-qemu/slof/OF.fs
@@ -175,6 +175,9 @@ CREATE version-str 10 ALLOT
     version-str 8 + @               \ end
     over - dump-display-write
     " Press 's' to enter Open Firmware." dump-display-write
+    s" /ibm,vtpm" find-node IF
+        "  Press 't' to enter TPM menu." terminal-write drop
+    THEN
     cr cr
     temp-ptr disp-size > IF
         temp-ptr disp-size MOD
diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
index b4a0fc1..60bd03c 100644
--- a/board-qemu/slof/vtpm-sml.fs
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -120,6 +120,195 @@ log-base LOG-SIZE tpm-set-log-parameters
     THEN
 ;
 
+\
+\  TPM menu
+\
+
+1 CONSTANT TPM_ST_ENABLED
+2 CONSTANT TPM_ST_ACTIVE
+4 CONSTANT TPM_ST_OWNED
+8 CONSTANT TPM_ST_OWNERINSTALL
+
+\ helper to test whether the TPM is enabled and active
+: is-enabled-active? ( state -- ok? )
+    TPM_ST_ENABLED TPM_ST_ACTIVE OR dup rot AND =
+;
+
+\ display the menu for manipulating TPM state; we get
+\ the state of the TPM in form of flags from the C-driver
+\
+\ Some info about the TPM's states:
+\ - enabling/disabling can be done at any time
+\ - activating/deactivating the TPM requires an enabled TPM
+\ - clearing ownership can be done even if the TPM is deactivated and disabled
+\ - allowing/preventing owner installation requires an enabled and active TPM
+\
+: tpm12-menu-show ( -- )
+    tpm-is-working IF
+        ." The TPM is "
+
+        tpm-get-state                   ( flags )
+
+        dup TPM_ST_ENABLED AND TPM_ST_ENABLED <> IF
+            ." disabled"
+        ELSE
+            ." enabled"
+        THEN
+
+        dup TPM_ST_ACTIVE AND TPM_ST_ACTIVE <> IF
+            ." , deactivated"
+        ELSE
+            ." , active"
+        THEN
+
+        dup TPM_ST_OWNED AND TPM_ST_OWNED <> IF
+            ." , does not have an owner "
+            dup TPM_ST_OWNERINSTALL AND TPM_ST_OWNERINSTALL <> IF
+                ." and an owner cannot be installed."
+            ELSE
+                ." but one can be installed."
+            THEN
+        ELSE
+            ." , and has an owner."
+        THEN
+
+        cr cr
+        ." To configure the TPM, choose one of the following actions:"
+        cr cr
+
+        dup TPM_ST_ENABLED AND TPM_ST_ENABLED <> IF
+            ." e. Enable the TPM" cr
+        ELSE
+            ." d. Disable the TPM" cr
+
+            dup TPM_ST_ACTIVE AND TPM_ST_ACTIVE <> IF
+                ." a. Activate the TPM" cr
+            ELSE
+                ." v. Deactivate the TPM" cr
+
+                dup TPM_ST_OWNERINSTALL AND TPM_ST_OWNERINSTALL <> IF
+                    ." s. Allow installation of an owner" cr
+                ELSE
+                    ." p. Prevent installation of an owner" cr
+                THEN
+            THEN
+
+        THEN
+
+        dup TPM_ST_OWNED AND TPM_ST_OWNED = IF
+           ." c. Clear ownership" cr
+        THEN
+
+        cr
+        \ If the TPM is either disabled or deactivated, show message
+        is-enabled-active? 0= IF
+            ." Note: To be able to use all features of the TPM, it must be enabled and active."
+            cr cr
+        THEN
+
+    ELSE
+       ." The TPM is not working correctly." cr
+    THEN
+
+    ." Press escape to continue boot." cr cr
+;
+
+\ Send a code to the C-driver to change the state of the vTPM
+: process-opcode ( verbose? opcode -- )
+    tpm-process-opcode
+    dup 0<> IF
+        ." VTPM: Error code from tpm-process-opcode: " . cr
+    ELSE
+        drop
+    THEN
+;
+
+1  CONSTANT PPI_OP_ENABLE
+2  CONSTANT PPI_OP_DISABLE
+3  CONSTANT PPI_OP_ACTIVATE
+4  CONSTANT PPI_OP_DEACTIVATE
+5  CONSTANT PPI_OP_CLEAR
+8  CONSTANT PPI_OP_SETOWNERINSTALL_TRUE
+9  CONSTANT PPI_OP_SETOWNERINSTALL_FALSE
+
+\ if there's a vtpm available, display the menu
+\ wait for keyboard input and have the C-driver
+\ process opcodes we derive from the chosen menu
+\ item
+: vtpm12-menu
+    tpm-is-working IF
+        \ vtpm-empty-keybuffer
+        tpm12-menu-show
+        BEGIN
+            0 \ loop end-flag                                           ( 0 )
+            key CASE
+            [char] e OF  tpm-get-state                                  ( 0 flags )
+                         TPM_ST_ENABLED AND TPM_ST_ENABLED <> IF
+                             0 PPI_OP_ENABLE     process-opcode
+                             tpm12-menu-show
+                         THEN
+                     ENDOF
+            [char] d OF  tpm-get-state                                  ( 0 flags )
+                         TPM_ST_ENABLED AND TPM_ST_ENABLED = IF
+                             0 PPI_OP_DISABLE    process-opcode
+                             tpm12-menu-show
+                         THEN
+                     ENDOF
+            [char] a OF  tpm-get-state                                  ( 0 flags )
+                         TPM_ST_ACTIVE AND TPM_ST_ACTIVE <> IF
+                             0 PPI_OP_ACTIVATE   process-opcode
+                             tpm-get-state
+                             TPM_ST_ACTIVE AND TPM_ST_ACTIVE = IF
+                                 ." The system needs to reboot to activate the TPM."
+                                 100 MS \ so the message shows
+                                 reset-all
+                             THEN
+                         THEN
+                     ENDOF
+            [char] v OF  tpm-get-state                                  ( 0 flags )
+                         TPM_ST_ACTIVE AND TPM_ST_ACTIVE = IF
+                             0 PPI_OP_DEACTIVATE process-opcode
+                             tpm12-menu-show
+                         THEN
+                     ENDOF
+            [char] c OF  tpm-get-state                                  ( 0 flags )
+                         TPM_ST_OWNED AND TPM_ST_OWNED = IF
+                             0 PPI_OP_CLEAR      process-opcode
+                             tpm12-menu-show
+                         THEN
+                     ENDOF
+            [char] s OF  tpm-get-state                                  ( 0 flags )
+                         \ The TPM must be enabled and active to allow
+                         \ owner installation mods
+                         dup is-enabled-active? IF
+                             TPM_ST_OWNERINSTALL AND TPM_ST_OWNERINSTALL <> IF
+                                 0 PPI_OP_SETOWNERINSTALL_TRUE  process-opcode
+                                 tpm12-menu-show
+                             THEN
+                         THEN
+                     ENDOF
+            [char] p OF  tpm-get-state                                  ( 0 flags )
+                         \ The TPM must be enabled and active to allow
+                         \ owner installation mods
+                         dup is-enabled-active? IF
+                             TPM_ST_OWNERINSTALL AND TPM_ST_OWNERINSTALL = IF
+                                 0 PPI_OP_SETOWNERINSTALL_FALSE process-opcode
+                                 tpm12-menu-show
+                             THEN
+                         THEN
+                     ENDOF
+            1b       OF                                                ( 0 )
+                         drop 1                                        ( 1 )
+                     ENDOF
+            ENDCASE
+        UNTIL
+    THEN
+;
+
+: vtpm-menu
+    vtpm12-menu
+;
+
 : open  true ;
 : close ;
 
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index 8bd684c..3c9d2d7 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -206,7 +206,7 @@ static int tpm_extend(uint8_t *hash, uint32_t pcrindex)
  * Setup and Measurements
  ****************************************************************/
 
-static bool tpm_is_working(void)
+bool tpm_is_working(void)
 {
 	if (!tpm_state.tpm_probed)
 		probe_tpm();
@@ -749,3 +749,31 @@ uint32_t tpm_process_opcode(uint8_t op, bool verbose)
 {
 	return tpm12_process_cfg(op, verbose);
 }
+
+int tpm_get_state(void)
+{
+	int state = 0;
+	struct tpm_permanent_flags pf;
+	bool has_owner;
+
+	if (tpm12_read_permanent_flags((char *)&pf, sizeof(pf)) ||
+	    tpm12_read_has_owner(&has_owner))
+		return ~0;
+
+	if (!pf.flags[PERM_FLAG_IDX_DISABLE])
+		state |= TPM_STATE_ENABLED; /* enabled */
+
+	if (!pf.flags[PERM_FLAG_IDX_DEACTIVATED])
+		state |= TPM_STATE_ACTIVE; /* active */
+
+	if (has_owner) {
+		state |= TPM_STATE_OWNED; /* has owner */
+	} else {
+		if (pf.flags[PERM_FLAG_IDX_OWNERSHIP])
+			state |= TPM_STATE_OWNERINSTALL; /* owner can be installed */
+	}
+
+	dprintf("TPM state flags = 0x%x\n", state);
+
+	return state;
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index b288778..956df43 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -34,4 +34,13 @@ uint32_t tpm_measure_bcv_mbr(uint32_t bootdrv, const uint8_t *addr,
 uint32_t tpm_add_event_separators(uint32_t start_pcr, uint32_t end_pcr);
 uint32_t tpm_process_opcode(uint8_t op, bool verbose);
 
+/* flags returned by tpm_get_state */
+#define TPM_STATE_ENABLED        1
+#define TPM_STATE_ACTIVE         2
+#define TPM_STATE_OWNED          4
+#define TPM_STATE_OWNERINSTALL   8
+
+int tpm_get_state(void);
+bool tpm_is_working(void);
+
 #endif /* TCGBIOS_H */
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index 1a5273f..3957028 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -132,3 +132,23 @@ PRIM(tpm_X2d_process_X2d_opcode)
 	bool verbose = TOS.u;
 	TOS.n = tpm_process_opcode(opcode, verbose);
 MIRP
+
+/************************************************/
+/* Get state of the TPM in form of flags        */
+/* SLOF:   tpm-get-state  ( -- flags )          */
+/* LIBTPM: state = tpm_get_state()              */
+/************************************************/
+PRIM(tpm_X2d_get_X2d_state)
+	PUSH;
+	TOS.n = tpm_get_state();
+MIRP
+
+/************************************************/
+/* Check whether the TPM is working             */
+/* SLOF:   tpm-is-working  ( -- true | false )  */
+/* LIBTPM: bool = tpm_is_working()              */
+/************************************************/
+PRIM(tpm_X2d_is_X2d_working)
+	PUSH;
+	TOS.n = tpm_is_working();
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index 9fb30bb..0e942bc 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -24,3 +24,5 @@ cod(tpm-hash-all)
 cod(tpm-add-event-separators)
 cod(tpm-measure-bcv-mbr)
 cod(tpm-process-opcode)
+cod(tpm-get-state)
+cod(tpm-is-working)
diff --git a/slof/fs/start-up.fs b/slof/fs/start-up.fs
index 0715357..d72579b 100644
--- a/slof/fs/start-up.fs
+++ b/slof/fs/start-up.fs
@@ -55,6 +55,14 @@
    nvramlog-write-string-cr
 ;
 
+: (t-pressed) ( -- )
+   s" /ibm,vtpm" find-node dup IF
+      s" vtpm-menu" rot $call-static
+   ELSE
+      drop
+   THEN
+;
+
 : (boot?) ( -- )
    \ last step before we boot we give up physical presence on the TPM
    s" /ibm,vtpm" find-node dup IF
@@ -107,6 +115,7 @@ TRUE VALUE use-load-watchdog?
    key? IF
       key CASE
 	 [char] s  OF (s-pressed) ENDOF
+	 [char] t  OF (t-pressed) (boot?) ENDOF
 	 1b        OF
 	     (esc-sequence) CASE
 		 1   OF
-- 
2.17.1



More information about the SLOF mailing list