aboutsummaryrefslogtreecommitdiff
path: root/libstb
diff options
context:
space:
mode:
authorEric Richter <erichte@linux.ibm.com>2020-09-16 11:21:25 -0500
committerOliver O'Halloran <oohall@gmail.com>2020-10-01 13:44:06 +1000
commitd560710cd4da91569f82caa7899dd180c4a6c3a2 (patch)
tree2c12f1587a047e2c148f938b48299118867c8d3a /libstb
parent1d9fb3ee24648cf0aff8fc6aaadf9730262605ca (diff)
downloadskiboot-d560710cd4da91569f82caa7899dd180c4a6c3a2.zip
skiboot-d560710cd4da91569f82caa7899dd180c4a6c3a2.tar.gz
skiboot-d560710cd4da91569f82caa7899dd180c4a6c3a2.tar.bz2
secvar/storage/fakenv: add fake tpm operations for testing
The secboot_tpm storage driver heavily relies on the TPM to ensure data integrity, which makes it difficult to test in userspace or on hardware without a TPM. This patch adds a bunch of functions that implement the tssskiboot interface, and simulates the expected TPM behavior utilizing PNOR space instead. THIS IS NOT INTENDED FOR PRODUCTION USE. Signed-off-by: Eric Richter <erichte@linux.ibm.com> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Diffstat (limited to 'libstb')
-rw-r--r--libstb/secvar/storage/Makefile.inc3
-rw-r--r--libstb/secvar/storage/fakenv_ops.c175
2 files changed, 178 insertions, 0 deletions
diff --git a/libstb/secvar/storage/Makefile.inc b/libstb/secvar/storage/Makefile.inc
index 35fba72..99f7b07 100644
--- a/libstb/secvar/storage/Makefile.inc
+++ b/libstb/secvar/storage/Makefile.inc
@@ -5,8 +5,11 @@ SECVAR_STORAGE_DIR = $(SRC)/libstb/secvar/storage
SUBDIRS += $(SECVAR_STORAGE_DIR)
+# Swap the comment on these two lines to use the fake TPM NV
+# implementation hardware without a TPM
SECVAR_STORAGE_SRCS = secboot_tpm.c tpmnv_ops.c
#SECVAR_STORAGE_SRCS = secboot_tpm.c fakenv_ops.c
+
SECVAR_STORAGE_OBJS = $(SECVAR_STORAGE_SRCS:%.c=%.o)
SECVAR_STORAGE = $(SECVAR_STORAGE_DIR)/built-in.a
diff --git a/libstb/secvar/storage/fakenv_ops.c b/libstb/secvar/storage/fakenv_ops.c
new file mode 100644
index 0000000..64d5d51
--- /dev/null
+++ b/libstb/secvar/storage/fakenv_ops.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/* Copyright 2020 IBM Corp. */
+#include <skiboot.h>
+#include "secboot_tpm.h"
+
+/* Offset into the SECBOOT PNOR partition to write "TPMNV" data */
+static size_t fakenv_offset = sizeof(struct secboot);
+
+struct fake_tpmnv {
+ struct {
+ struct secboot_header header;
+ char vars[1024]; // Hardcode the size to 1024 for now
+ } vars;
+ struct tpmnv_control control;
+ int defined[2];
+} __attribute__((packed));
+
+static struct fake_tpmnv fakenv = {0};
+static int tpm_ready = 0;
+
+
+static inline void *nv_index_address(int index)
+{
+ switch (index) {
+ case SECBOOT_TPMNV_VARS_INDEX:
+ return &fakenv.vars;
+ case SECBOOT_TPMNV_CONTROL_INDEX:
+ return &fakenv.control;
+ default:
+ return 0;
+ }
+}
+
+
+static int tpm_init(void)
+{
+ int rc;
+
+ if (tpm_ready)
+ return 0;
+
+ rc = flash_secboot_read(&fakenv, fakenv_offset, sizeof(struct fake_tpmnv));
+ if (rc)
+ return rc;
+
+ tpm_ready = 1;
+
+ return 0;
+}
+
+static int fakenv_read(TPMI_RH_NV_INDEX nvIndex, void *buf,
+ size_t bufsize, uint16_t off)
+{
+ if (tpm_init())
+ return OPAL_INTERNAL_ERROR;
+
+ memcpy(buf, nv_index_address(nvIndex) + off, bufsize);
+
+ return 0;
+}
+
+static int fakenv_write(TPMI_RH_NV_INDEX nvIndex, void *buf,
+ size_t bufsize, uint16_t off)
+{
+ if (tpm_init())
+ return OPAL_INTERNAL_ERROR;
+
+ memcpy(nv_index_address(nvIndex) + off, buf, bufsize);
+
+ /* Just write the whole NV struct for now */
+ return flash_secboot_write(fakenv_offset, &fakenv, sizeof(struct fake_tpmnv));
+}
+
+static int fakenv_definespace(TPMI_RH_NV_INDEX nvIndex, uint16_t dataSize)
+{
+ if (tpm_init())
+ return OPAL_INTERNAL_ERROR;
+
+ (void) dataSize;
+
+ switch (nvIndex) {
+ case SECBOOT_TPMNV_VARS_INDEX:
+ fakenv.defined[0] = 1;
+ return 0;
+ case SECBOOT_TPMNV_CONTROL_INDEX:
+ fakenv.defined[1] = 1;
+ return 0;
+ }
+
+ return OPAL_INTERNAL_ERROR;
+}
+
+static int fakenv_writelock(TPMI_RH_NV_INDEX nvIndex)
+{
+ if (tpm_init())
+ return OPAL_INTERNAL_ERROR;
+
+ (void) nvIndex;
+
+ return 0;
+}
+
+static int fakenv_get_defined_indices(TPMI_RH_NV_INDEX **indices, size_t *count)
+{
+ if (tpm_init())
+ return OPAL_INTERNAL_ERROR;
+
+ *indices = zalloc(sizeof(fakenv.defined));
+ if (*indices == NULL)
+ return OPAL_NO_MEM;
+
+ *count = 0;
+
+ if (fakenv.defined[0]) {
+ *indices[0] = SECBOOT_TPMNV_VARS_INDEX;
+ (*count)++;
+ }
+ if (fakenv.defined[1]) {
+ *indices[1] = SECBOOT_TPMNV_CONTROL_INDEX;
+ (*count)++;
+ }
+
+ return 0;
+}
+
+static int fakenv_undefinespace(TPMI_RH_NV_INDEX index)
+{
+ if (tpm_init())
+ return OPAL_INTERNAL_ERROR;
+
+ switch (index) {
+ case SECBOOT_TPMNV_VARS_INDEX:
+ fakenv.defined[0] = 0;
+ memset(&fakenv.vars, 0, sizeof(fakenv.vars));
+ return 0;
+ case SECBOOT_TPMNV_CONTROL_INDEX:
+ fakenv.defined[1] = 0;
+ memset(&fakenv.control, 0, sizeof(fakenv.control));
+ return 0;
+ }
+
+ return -1;
+}
+
+static int fakenv_readpublic(TPMI_RH_NV_INDEX index, TPMS_NV_PUBLIC *nv_public,
+ TPM2B_NAME *nv_name)
+{
+ if (tpm_init())
+ return OPAL_INTERNAL_ERROR;
+
+ (void) nv_public;
+
+ switch (index) {
+ case SECBOOT_TPMNV_VARS_INDEX:
+ memcpy(&nv_name->t.name, tpmnv_vars_name, sizeof(TPM2B_NAME));
+ break;
+ case SECBOOT_TPMNV_CONTROL_INDEX:
+ memcpy(&nv_name->t.name, tpmnv_control_name, sizeof(TPM2B_NAME));
+ break;
+ default:
+ return OPAL_INTERNAL_ERROR;
+ }
+
+ return 0;
+}
+
+struct tpmnv_ops_s tpmnv_ops = {
+ .read = fakenv_read,
+ .write = fakenv_write,
+ .writelock = fakenv_writelock,
+ .definespace = fakenv_definespace,
+ .getindices = fakenv_get_defined_indices,
+ .undefinespace = fakenv_undefinespace,
+ .readpublic = fakenv_readpublic,
+};