[SLOF] [PATCH v3 10/17] Add support for a TPM menu to control the state of the TPM

Stefan Berger stefanb at us.ibm.com
Tue Dec 1 09:01:53 AEDT 2015


From: Stefan Berger <stefanb at linux.vnet.ibm.com>

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 | 194 ++++++++++++++++++++++++++++++++++++++++++++
 lib/libtpm/tcgbios.c        |  39 ++++++++-
 lib/libtpm/tcgbios.h        |   9 ++
 lib/libtpm/tpm.code         |  20 +++++
 lib/libtpm/tpm.in           |   2 +
 slof/fs/start-up.fs         |   9 ++
 7 files changed, 273 insertions(+), 3 deletions(-)

diff --git a/board-qemu/slof/OF.fs b/board-qemu/slof/OF.fs
index 561d892..1c4080e 100644
--- a/board-qemu/slof/OF.fs
+++ b/board-qemu/slof/OF.fs
@@ -176,6 +176,9 @@ CREATE version-str 10 ALLOT
     version-str 8 + @               \ end
     over - terminal-write drop
     " Press 's' to enter Open Firmware." terminal-write drop
+    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 193b567..3e17c82 100644
--- a/board-qemu/slof/vtpm-sml.fs
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -120,6 +120,200 @@ 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
+\
+: 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
+;
+
+\ wait for keyboard input
+: menu-key-get
+    0 0 DO
+       key? IF
+           key
+           UNLOOP EXIT
+       THEN
+       100 MS
+    LOOP
+    1b
+;
+
+\ 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
+: vtpm-menu
+    tpm-is-working IF
+        \ vtpm-empty-keybuffer
+        menu-show
+        0 0  DO
+            CASE menu-key-get
+            [char] e OF  tpm-get-state                                  ( -- flags )
+                         TPM_ST_ENABLED AND TPM_ST_ENABLED <> IF
+                             0 PPI_OP_ENABLE     process-opcode
+                             menu-show
+                         THEN
+                     ENDOF
+            [char] d OF  tpm-get-state                                  ( -- flags )
+                         TPM_ST_ENABLED AND TPM_ST_ENABLED = IF
+                             0 PPI_OP_DISABLE    process-opcode
+                             menu-show
+                         THEN
+                     ENDOF
+            [char] a OF  tpm-get-state                                  ( -- 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                                  ( -- flags )
+                         TPM_ST_ACTIVE AND TPM_ST_ACTIVE = IF
+                             0 PPI_OP_DEACTIVATE process-opcode
+                             menu-show
+                         THEN
+                     ENDOF
+            [char] c OF  tpm-get-state                                  ( -- flags )
+                         TPM_ST_OWNED AND TPM_ST_OWNED = IF
+                             0 PPI_OP_CLEAR      process-opcode
+                             menu-show
+                         THEN
+                     ENDOF
+            [char] s OF  tpm-get-state
+                         \ 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
+                                 menu-show
+                             THEN
+                         THEN
+                     ENDOF
+            [char] p OF  tpm-get-state
+                         \ 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
+                                 menu-show
+                             THEN
+                         THEN
+                     ENDOF
+            1b OF UNLOOP EXIT ENDOF
+            ENDCASE
+        LOOP
+    THEN
+;
+
 : open  true ;
 : close ;
 
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index 05abdda..d4aa792 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -184,6 +184,11 @@ static bool has_working_tpm(void)
 	return tpm_state.tpm_working;
 }
 
+bool tpm_is_working(void)
+{
+	return has_working_tpm();
+}
+
 static uint32_t transmit(struct tpm_req_header *req,
 			 uint8_t *respbuffer, uint32_t *respbufferlen,
 			 enum tpm_duration_type to_t)
@@ -544,8 +549,8 @@ static uint32_t tpm_add_measurement_to_log(uint32_t pcrindex,
 					   uint32_t eventtype,
 					   const char *info,
 					   uint32_t infolen,
-					   const uint8_t *data,
-					   uint32_t datalen)
+					   const uint8_t *hashdata,
+					   uint32_t hashdatalen)
 {
 	struct pcpes pcpes;
 
@@ -553,7 +558,7 @@ static uint32_t tpm_add_measurement_to_log(uint32_t pcrindex,
 	pcpes.eventtype = eventtype;
 	memset(&pcpes.digest, 0, sizeof(pcpes.digest));
 
-	return hash_log_extend_event(data, datalen, &pcpes,
+	return hash_log_extend_event(hashdata, hashdatalen, &pcpes,
 				     info, infolen, pcrindex);
 }
 
@@ -1082,3 +1087,31 @@ uint32_t tpm_process_opcode(uint8_t op, bool verbose)
 
 	return tpm_process_cfg(op, verbose, &return_code);
 }
+
+int tpm_get_state(void)
+{
+	int state = 0;
+	struct tpm_permanent_flags pf;
+	bool has_owner;
+
+	if (read_permanent_flags((char *)&pf, sizeof(pf)) ||
+	    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 797fc0e..f60b7bf 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 f115b89..7d2a2f1 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
@@ -154,6 +162,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.4.3



More information about the SLOF mailing list