diff options
author | Eric Richter <erichte@linux.ibm.com> | 2020-09-16 11:21:25 -0500 |
---|---|---|
committer | Oliver O'Halloran <oohall@gmail.com> | 2020-10-01 13:44:06 +1000 |
commit | d560710cd4da91569f82caa7899dd180c4a6c3a2 (patch) | |
tree | 2c12f1587a047e2c148f938b48299118867c8d3a | |
parent | 1d9fb3ee24648cf0aff8fc6aaadf9730262605ca (diff) | |
download | skiboot-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>
-rw-r--r-- | libstb/secvar/storage/Makefile.inc | 3 | ||||
-rw-r--r-- | libstb/secvar/storage/fakenv_ops.c | 175 |
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, +}; |