From 2d3deaef291e045a2188287d18d42f2dd58173bf Mon Sep 17 00:00:00 2001 From: Eiichi Tsukata Date: Fri, 25 Jun 2021 11:29:44 +0900 Subject: [PATCH] swtpm: Abstract NVRAM interface for pluggable state store Related GH issue: https://github.com/stefanberger/swtpm/issues/461 This patch adds an abstraction layer to NVRAM state store implementation for pluggable storage backends. No functional changes are intended in this change. The default state store backend ("dir backend") keeps current behavior. To make swtpm ready for pluggable store, this patch moves file related operations to the seperate file (swtpm_nvstore_dir.c) and defined the interface for plugins (nvram_backend_ops in swtpm_nvstore.h). The interface can be used by each plugin which will be added later. With the interface, each plugin can access its "backend_uri" which points to the location of the backend storage, for example S3 bucket URL or iSCSI URL, and decide how it stores TPM state data. Signed-off-by: Eiichi Tsukata --- src/swtpm/Makefile.am | 6 +- src/swtpm/common.c | 13 +- src/swtpm/ctrlchannel.c | 2 +- src/swtpm/cuse_tpm.c | 13 +- src/swtpm/swtpm.c | 4 +- src/swtpm/swtpm_chardev.c | 4 +- src/swtpm/{swtpm_nvfile.c => swtpm_nvstore.c} | 397 +------------- src/swtpm/{swtpm_nvfile.h => swtpm_nvstore.h} | 37 +- src/swtpm/swtpm_nvstore_dir.c | 484 ++++++++++++++++++ src/swtpm/swtpm_nvstore_dir.h | 78 +++ src/swtpm/tpmlib.c | 2 +- src/swtpm/tpmstate.c | 59 ++- src/swtpm/tpmstate.h | 9 +- 13 files changed, 685 insertions(+), 423 deletions(-) rename src/swtpm/{swtpm_nvfile.c => swtpm_nvstore.c} (74%) rename src/swtpm/{swtpm_nvfile.h => swtpm_nvstore.h} (84%) create mode 100644 src/swtpm/swtpm_nvstore_dir.c create mode 100644 src/swtpm/swtpm_nvstore_dir.h diff --git a/src/swtpm/Makefile.am b/src/swtpm/Makefile.am index 662bcd7..5c16e48 100644 --- a/src/swtpm/Makefile.am +++ b/src/swtpm/Makefile.am @@ -24,7 +24,8 @@ noinst_HEADERS = \ swtpm_aes.h \ swtpm_debug.h \ swtpm_io.h \ - swtpm_nvfile.h \ + swtpm_nvstore.h \ + swtpm_nvstore_dir.h \ threadpool.h \ tlv.h \ tpmlib.h \ @@ -49,7 +50,8 @@ libswtpm_libtpms_la_SOURCES = \ swtpm_aes.c \ swtpm_debug.c \ swtpm_io.c \ - swtpm_nvfile.c \ + swtpm_nvstore.c \ + swtpm_nvstore_dir.c \ tlv.c \ tpmlib.c \ tpmstate.c \ diff --git a/src/swtpm/common.c b/src/swtpm/common.c index 8cd4403..33cdeaf 100644 --- a/src/swtpm/common.c +++ b/src/swtpm/common.c @@ -37,6 +37,7 @@ #include "config.h" +#define _GNU_SOURCE #include #include #include @@ -62,7 +63,7 @@ #include "key.h" #include "locality.h" #include "logging.h" -#include "swtpm_nvfile.h" +#include "swtpm_nvstore.h" #include "pidfile.h" #include "tpmstate.h" #include "ctrlchannel.h" @@ -656,6 +657,7 @@ int handle_tpmstate_options(char *options) { char *tpmstatedir = NULL; + char *tpmbackend_uri = NULL; int ret = 0; mode_t mode; @@ -665,11 +667,18 @@ handle_tpmstate_options(char *options) if (parse_tpmstate_options(options, &tpmstatedir, &mode) < 0) return -1; - if (tpmstate_set_dir(tpmstatedir) < 0 || + if (asprintf(&tpmbackend_uri, "dir://%s", tpmstatedir) < 0) { + logprintf(STDERR_FILENO, + "Could not asprintf TPM backend uri\n"); + return -1; + } + + if (tpmstate_set_backend_uri(tpmbackend_uri) < 0 || tpmstate_set_mode(mode) < 0) ret = -1; free(tpmstatedir); + free(tpmbackend_uri); return ret; } diff --git a/src/swtpm/ctrlchannel.c b/src/swtpm/ctrlchannel.c index 5b14405..6ddc735 100644 --- a/src/swtpm/ctrlchannel.c +++ b/src/swtpm/ctrlchannel.c @@ -56,7 +56,7 @@ #include "logging.h" #include "tpm_ioctl.h" #include "tpmlib.h" -#include "swtpm_nvfile.h" +#include "swtpm_nvstore.h" #include "locality.h" #include "mainloop.h" #include "utils.h" diff --git a/src/swtpm/cuse_tpm.c b/src/swtpm/cuse_tpm.c index 5dbbf91..21aa44a 100644 --- a/src/swtpm/cuse_tpm.c +++ b/src/swtpm/cuse_tpm.c @@ -70,7 +70,7 @@ #include "locality.h" #include "logging.h" #include "tpm_ioctl.h" -#include "swtpm_nvfile.h" +#include "swtpm_nvstore.h" #include "tpmlib.h" #include "main.h" #include "utils.h" @@ -432,7 +432,8 @@ static int tpm_start(uint32_t flags, TPMLIB_TPMVersion l_tpmversion, TPM_RESULT *res) { DIR *dir; - const char *tpmdir = tpmstate_get_dir(); + const char *uri = tpmstate_get_backend_uri(); + const char *tpmdir = uri + strlen("dir://"); *res = TPM_FAIL; @@ -1461,7 +1462,7 @@ int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *ifac char *cinfo_argv[1] = { 0 }; unsigned int num; struct passwd *passwd; - const char *tpmdir; + const char *uri = NULL; int n, tpmfd; char path[PATH_MAX]; int ret = 0; @@ -1598,7 +1599,7 @@ int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *ifac goto exit; } - SWTPM_NVRAM_Set_TPMVersion(tpmversion); + tpmstate_set_version(tpmversion); if (!cinfo.dev_info_argv) { logprintf(STDERR_FILENO, "Error: device name missing\n"); @@ -1635,8 +1636,8 @@ int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *ifac } } - tpmdir = tpmstate_get_dir(); - if (tpmdir == NULL) { + uri = tpmstate_get_backend_uri(); + if (uri == NULL) { logprintf(STDERR_FILENO, "Error: No TPM state directory is defined; " "TPM_PATH is not set\n"); diff --git a/src/swtpm/swtpm.c b/src/swtpm/swtpm.c index 6c76a2d..a101509 100644 --- a/src/swtpm/swtpm.c +++ b/src/swtpm/swtpm.c @@ -57,7 +57,7 @@ #include "main.h" #include "swtpm_debug.h" #include "swtpm_io.h" -#include "swtpm_nvfile.h" +#include "swtpm_nvstore.h" #include "server.h" #include "common.h" #include "logging.h" @@ -431,7 +431,7 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface) goto exit_failure; } - SWTPM_NVRAM_Set_TPMVersion(mlp.tpmversion); + tpmstate_set_version(mlp.tpmversion); if (handle_log_options(logdata) < 0 || handle_key_options(keydata) < 0 || diff --git a/src/swtpm/swtpm_chardev.c b/src/swtpm/swtpm_chardev.c index a875de5..34b36a4 100644 --- a/src/swtpm/swtpm_chardev.c +++ b/src/swtpm/swtpm_chardev.c @@ -57,7 +57,7 @@ #include "main.h" #include "swtpm_debug.h" #include "swtpm_io.h" -#include "swtpm_nvfile.h" +#include "swtpm_nvstore.h" #include "common.h" #include "locality.h" #include "logging.h" @@ -474,7 +474,7 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i exit(EXIT_FAILURE); } - SWTPM_NVRAM_Set_TPMVersion(mlp.tpmversion); + tpmstate_set_version(mlp.tpmversion); if (mlp.fd < 0) { logprintf(STDERR_FILENO, diff --git a/src/swtpm/swtpm_nvfile.c b/src/swtpm/swtpm_nvstore.c similarity index 74% rename from src/swtpm/swtpm_nvfile.c rename to src/swtpm/swtpm_nvstore.c index 51c009d..183684a 100644 --- a/src/swtpm/swtpm_nvfile.c +++ b/src/swtpm/swtpm_nvstore.c @@ -82,7 +82,8 @@ #include "swtpm.h" #include "swtpm_aes.h" #include "swtpm_debug.h" -#include "swtpm_nvfile.h" +#include "swtpm_nvstore.h" +#include "swtpm_nvstore_dir.h" #include "key.h" #include "logging.h" #include "tpmstate.h" @@ -128,15 +129,10 @@ static encryptionkey migrationkey = { static uint32_t g_ivec_length; static unsigned char *g_ivec; +static struct nvram_backend_ops *g_nvram_backend_ops; /* local prototypes */ -static TPM_RESULT SWTPM_NVRAM_GetFilenameForName(char *filename, - size_t bufsize, - uint32_t tpm_number, - const char *name, - bool is_tempfile); - static TPM_RESULT SWTPM_NVRAM_EncryptData(const encryptionkey *key, tlv_data *td, size_t *td_len, @@ -167,74 +163,6 @@ static TPM_RESULT SWTPM_NVRAM_CheckHeader(unsigned char *data, uint32_t length, uint8_t *hdrversion, bool quiet); -/* A file name in NVRAM is composed of 3 parts: - - 1 - 'state_directory' is the rooted path to the TPM state home directory - 2 = 'tpm_number' is the TPM instance, 00 for a single TPM - 2 - the file name - - For the IBM cryptographic coprocessor version, the root path is hard coded. - - For the Linux and Windows versions, the path comes from an environment variable. This variable is - used once in SWTPM_NVRAM_Init(). - - One root path is used for all virtual TPM's, so it can be a static variable. -*/ - -static int lockfile_fd = -1; - -char state_directory[FILENAME_MAX]; -static TPMLIB_TPMVersion tpmversion = TPMLIB_TPM_VERSION_1_2; - -/* - * SWTPM_NVRAM_Set_TPMVersion() - set the version of the TPM being used - */ -void SWTPM_NVRAM_Set_TPMVersion(TPMLIB_TPMVersion version) -{ - tpmversion = version; -} - -static TPM_RESULT SWTPM_NVRAM_Lock_Lockfile(const char *directory, - int *fd) -{ - TPM_RESULT rc = 0; - char *lockfile = NULL; - struct flock flock = { - .l_type = F_WRLCK, - .l_whence = SEEK_SET, - .l_start = 0, - .l_len = 0, - }; - - if (asprintf(&lockfile, "%s/.lock", directory) < 0) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_Lock_Lockfile: Could not asprintf lock filename\n"); - return TPM_FAIL; - } - - *fd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, 0660); - if (*fd < 0) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_Lock_Lockfile: Could not open lockfile: %s\n", - strerror(errno)); - rc = TPM_FAIL; - goto exit; - } - - if (fcntl(*fd, F_SETLK, &flock) < 0) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_Lock_Lockfile: Could not lock access to lockfile: %s\n", - strerror(errno)); - rc = TPM_FAIL; - close(*fd); - *fd = -1; - } -exit: - free(lockfile); - - return rc; -} - /* SWTPM_NVRAM_Init() is called once at startup. It does any NVRAM required initialization. This function sets some static variables that are used by all TPM's. @@ -242,40 +170,21 @@ exit: TPM_RESULT SWTPM_NVRAM_Init(void) { + const char *backend_uri; TPM_RESULT rc = 0; - const char *tpm_state_path; - size_t length; - TPM_DEBUG(" SWTPM_NVRAM_Init:\n"); - /* TPM_NV_DISK TPM emulation stores in local directory determined by environment variable. */ - if (rc == 0) { - tpm_state_path = tpmstate_get_dir(); - if (tpm_state_path == NULL) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_Init: Error (fatal), TPM_PATH environment " - "variable not set\n"); - rc = TPM_FAIL; - } + backend_uri = tpmstate_get_backend_uri(); + if (strncmp(backend_uri, "dir://", 6) == 0) { + g_nvram_backend_ops = &nvram_dir_ops; + } else { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_Init: Unsupported backend.\n"); + rc = TPM_FAIL; } - /* check that the directory name plus a file name will not overflow FILENAME_MAX */ - if (rc == 0) { - length = strlen(tpm_state_path); - if ((length + TPM_FILENAME_MAX) > FILENAME_MAX) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_Init: Error (fatal), TPM state path name " - "%s too large\n", tpm_state_path); - rc = TPM_FAIL; - } - } - if (rc == 0) { - strcpy(state_directory, tpm_state_path); - TPM_DEBUG("SWTPM_NVRAM_Init: Rooted state path %s\n", state_directory); - } - - if (rc == 0 && lockfile_fd < 0) - rc = SWTPM_NVRAM_Lock_Lockfile(state_directory, &lockfile_fd); + if (rc == 0) + rc = g_nvram_backend_ops->prepare(backend_uri); return rc; } @@ -297,101 +206,22 @@ SWTPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */ const char *name) { TPM_RESULT rc = 0; - size_t src; int irc; - int fd = -1; - char filename[FILENAME_MAX]; /* rooted file name from name */ unsigned char *decrypt_data = NULL; uint32_t decrypt_length; uint32_t dataoffset = 0; uint8_t hdrversion = 0; uint16_t hdrflags; - struct stat statbuf; + const char *backend_uri = NULL; TPM_DEBUG(" SWTPM_NVRAM_LoadData: From file %s\n", name); *data = NULL; *length = 0; - /* open the file */ - if (rc == 0) { - /* map name to the rooted filename */ - rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename), - tpm_number, name, false); - } if (rc == 0) { - TPM_DEBUG(" SWTPM_NVRAM_LoadData: Opening file %s\n", filename); - fd = open(filename, O_RDONLY); /* closed @1 */ - if (fd < 0) { /* if failure, determine cause */ - if (errno == ENOENT) { - TPM_DEBUG("SWTPM_NVRAM_LoadData: No such file %s\n", - filename); - rc = TPM_RETRY; /* first time start up */ - } - else { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_LoadData: Error (fatal) opening " - "%s for read, %s\n", filename, strerror(errno)); - rc = TPM_FAIL; - } - } - } - - if (rc == 0) { - if (fchmod(fd, tpmstate_get_mode()) < 0) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_LoadData: Could not fchmod %s : %s\n", - filename, strerror(errno)); - rc = TPM_FAIL; - } - } - - /* determine the file length */ - if (rc == 0) { - irc = fstat(fd, &statbuf); - if (irc == -1L) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_LoadData: Error (fatal) fstat'ing %s, %s\n", - filename, strerror(errno)); - rc = TPM_FAIL; - } - } - if (rc == 0) { - *length = statbuf.st_size; /* save the length */ - } - /* allocate a buffer for the actual data */ - if ((rc == 0) && *length != 0) { - TPM_DEBUG(" SWTPM_NVRAM_LoadData: Reading %u bytes of data\n", *length); - *data = malloc(*length); - if (!*data) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_LoadData: Error (fatal) allocating %u " - "bytes\n", *length); - rc = TPM_FAIL; - } - } - /* read the contents of the file into the data buffer */ - if ((rc == 0) && *length != 0) { - src = read(fd, *data, *length); - if (src != *length) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_LoadData: Error (fatal), data read of %u " - "only read %lu\n", *length, (unsigned long)src); - rc = TPM_FAIL; - } - } - /* close the file */ - if (fd >= 0) { - TPM_DEBUG(" SWTPM_NVRAM_LoadData: Closing file %s\n", filename); - irc = close(fd); /* @1 */ - if (irc != 0) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_LoadData: Error (fatal) closing file %s\n", - filename); - rc = TPM_FAIL; - } - else { - TPM_DEBUG(" SWTPM_NVRAM_LoadData: Closed file %s\n", filename); - } + backend_uri = tpmstate_get_backend_uri(); + rc = g_nvram_backend_ops->load(data, length, tpm_number, name, + backend_uri); } if (rc == 0) { @@ -455,44 +285,14 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, TPM_BOOL encrypt /* encrypt if key is set */) { TPM_RESULT rc = 0; - uint32_t lrc; - int irc; - int fd = -1; - int dir_fd = -1; - char tmpfile[FILENAME_MAX]; /* rooted temporary file */ - char filename[FILENAME_MAX]; /* rooted file name from name */ unsigned char *filedata = NULL; uint32_t filedata_length = 0; tlv_data td[3]; size_t td_len = 0; uint16_t flags = 0; + const char *backend_uri = NULL; TPM_DEBUG(" SWTPM_NVRAM_StoreData: To name %s\n", name); - if (rc == 0) { - /* map name to the rooted filename */ - rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename), - tpm_number, name, false); - } - - if (rc == 0) { - /* map name to the rooted temporary file */ - rc = SWTPM_NVRAM_GetFilenameForName(tmpfile, sizeof(tmpfile), - tpm_number, name, true); - } - - - if (rc == 0) { - /* open the file */ - TPM_DEBUG(" SWTPM_NVRAM_StoreData: Opening file %s\n", tmpfile); - fd = open(tmpfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, - tpmstate_get_mode()); /* closed @1 */ - if (fd < 0) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_StoreData: Error (fatal) opening %s for " - "write failed, %s\n", tmpfile, strerror(errno)); - rc = TPM_FAIL; - } - } if (rc == 0) { if (encrypt && SWTPM_NVRAM_Has_FileKey()) { @@ -523,96 +323,10 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, if (rc == 0) rc = SWTPM_NVRAM_PrependHeader(&filedata, &filedata_length, flags); - /* write the data to the file */ if (rc == 0) { - TPM_DEBUG(" SWTPM_NVRAM_StoreData: Writing %u bytes of data\n", length); - lrc = write_full(fd, filedata, filedata_length); - if (lrc != filedata_length) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_StoreData: Error (fatal), data write " - "of %u only wrote %u\n", filedata_length, lrc); - rc = TPM_FAIL; - } - } - if (rc == 0 && fd >= 0) { - TPM_DEBUG(" SWTPM_NVRAM_StoreData: Syncing file %s\n", tmpfile); - irc = fsync(fd); - if (irc != 0) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_StoreData: Error (fatal) syncing file, %s\n", - strerror(errno)); - rc = TPM_FAIL; - } else { - TPM_DEBUG(" SWTPM_NVRAM_StoreData: Synced file %s\n", tmpfile); - } - } - if (fd >= 0) { - TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closing file %s\n", tmpfile); - irc = close(fd); /* @1 */ - if (irc != 0) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_StoreData: Error (fatal) closing file\n"); - rc = TPM_FAIL; - } - else { - TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closed file %s\n", tmpfile); - } - } - - if (rc == 0 && fd >= 0) { - irc = rename(tmpfile, filename); - if (irc != 0) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_StoreData: Error (fatal) renaming file: %s\n", - strerror(errno)); - rc = TPM_FAIL; - } else { - TPM_DEBUG(" SWTPM_NVRAM_StoreData: Renamed file to %s\n", filename); - } - } - - /* - * Quote from linux man 2 fsync: - * Calling fsync() does not necessarily ensure that the entry in the - * directory containing the file has also reached disk. For that an - * explicit fsync() on a file descriptor for the directory is also needed. - */ - if (rc == 0 && fd >= 0) { - TPM_DEBUG(" SWTPM_NVRAM_StoreData: Opening dir %s\n", state_directory); - dir_fd = open(state_directory, O_RDONLY); - if (dir_fd < 0) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_StoreData: Error (fatal) opening %s for " - "fsync failed, %s\n", state_directory, strerror(errno)); - rc = TPM_FAIL; - } - } - if (rc == 0 && dir_fd >= 0) { - TPM_DEBUG(" SWTPM_NVRAM_StoreData: Syncing dir %s\n", state_directory); - irc = fsync(dir_fd); - if (irc != 0) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_StoreData: Error (fatal) syncing dir, %s\n", - strerror(errno)); - rc = TPM_FAIL; - } else { - TPM_DEBUG(" SWTPM_NVRAM_StoreData: Synced dir %s\n", state_directory); - } - } - if (dir_fd >= 0) { - TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closing dir %s\n", state_directory); - irc = close(dir_fd); - if (irc != 0) { - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_StoreData: Error (fatal) closing dir\n"); - rc = TPM_FAIL; - } else { - TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closed dir %s\n", state_directory); - } - } - - if (rc != 0 && fd >= 0) { - unlink(tmpfile); + backend_uri = tpmstate_get_backend_uri(); + rc = g_nvram_backend_ops->store(filedata, filedata_length, tpm_number, name, + backend_uri); } tlv_data_free(td, td_len); @@ -631,52 +345,6 @@ TPM_RESULT SWTPM_NVRAM_StoreData(const unsigned char *data, return SWTPM_NVRAM_StoreData_Intern(data, length, tpm_number, name, TRUE); } -/* SWTPM_NVRAM_GetFilenameForName() constructs a rooted file name from the name. - - The filename is of the form: - - state_directory/tpm_number.name - - A temporary filename used to write to may be created. It shold be rename()'d to - the non-temporary filename. -*/ - -static TPM_RESULT SWTPM_NVRAM_GetFilenameForName(char *filename, /* output: rooted filename */ - size_t bufsize, - uint32_t tpm_number, - const char *name, /* input: abstract name */ - bool is_tempfile) /* input: is temporary file? */ -{ - TPM_RESULT res = TPM_SUCCESS; - int n; - const char *suffix = ""; - - TPM_DEBUG(" SWTPM_NVRAM_GetFilenameForName: For name %s\n", name); - - switch (tpmversion) { - case TPMLIB_TPM_VERSION_1_2: - break; - case TPMLIB_TPM_VERSION_2: - suffix = "2"; - break; - } - - if (is_tempfile) { - n = snprintf(filename, bufsize, "%s/TMP%s-%02lx.%s", - state_directory, suffix, (unsigned long)tpm_number, name); - } else { - n = snprintf(filename, bufsize, "%s/tpm%s-%02lx.%s", - state_directory, suffix, (unsigned long)tpm_number, name); - } - if ((size_t)n > bufsize) { - res = TPM_FAIL; - } - - TPM_DEBUG(" SWTPM_NVRAM_GetFilenameForName: File name %s\n", filename); - - return res; -} - /* SWTPM_NVRAM_DeleteName() deletes the 'name' from NVRAM Returns: @@ -691,26 +359,11 @@ TPM_RESULT SWTPM_NVRAM_DeleteName(uint32_t tpm_number, const char *name, TPM_BOOL mustExist) { - TPM_RESULT rc = 0; - int irc; - char filename[FILENAME_MAX]; /* rooted file name from name */ + const char *backend_uri = NULL; + backend_uri = tpmstate_get_backend_uri(); - TPM_DEBUG(" SWTPM_NVRAM_DeleteName: Name %s\n", name); - /* map name to the rooted filename */ - rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename), - tpm_number, name, false); - if (rc == 0) { - irc = remove(filename); - if ((irc != 0) && /* if the remove failed */ - (mustExist || /* if any error is a failure, or */ - (errno != ENOENT))) { /* if error other than no such file */ - logprintf(STDERR_FILENO, - "SWTPM_NVRAM_DeleteName: Error, (fatal) file " - "remove failed, errno %d\n", errno); - rc = TPM_FAIL; - } - } - return rc; + return g_nvram_backend_ops->delete(tpm_number, name, mustExist, + backend_uri); } diff --git a/src/swtpm/swtpm_nvfile.h b/src/swtpm/swtpm_nvstore.h similarity index 84% rename from src/swtpm/swtpm_nvfile.h rename to src/swtpm/swtpm_nvstore.h index 3d9f0f3..73b61c5 100644 --- a/src/swtpm/swtpm_nvfile.h +++ b/src/swtpm/swtpm_nvstore.h @@ -36,27 +36,17 @@ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ -#ifndef _SWTPM_NVFILE_H -#define _SWTPM_NVFILE_H +#ifndef _SWTPM_NVSTORE_H +#define _SWTPM_NVSTORE_H +#include #include +#include #include "key.h" -/* characters in the TPM base file name, 14 for file name, slash, NUL terminator, etc. - - This macro is used once during initialization to ensure that the TPM_PATH environment variable - length will not cause the rooted file name to overflow file name buffers. -*/ - -#define TPM_FILENAME_MAX 20 - -#include - TPM_RESULT SWTPM_NVRAM_Init(void); -void SWTPM_NVRAM_Set_TPMVersion(TPMLIB_TPMVersion version); - /* Basic abstraction for read and write */ @@ -107,5 +97,22 @@ static inline TPM_BOOL SWTPM_NVRAM_Has_MigrationKey(void) return SWTPM_NVRAM_MigrationKey_Size() > 0; } -#endif /* _SWTPM_NVFILE_H */ +struct nvram_backend_ops { + TPM_RESULT (*prepare)(const char *uri); + TPM_RESULT (*load)(unsigned char **data, + uint32_t *length, + uint32_t tpm_number, + const char *name, + const char *uri); + TPM_RESULT (*store)(unsigned char *edata, + uint32_t data_length, + uint32_t tpm_number, + const char *name, + const char *uri); + TPM_RESULT (*delete)(uint32_t tpm_number, + const char *name, + TPM_BOOL mustExist, + const char *uri); +}; +#endif /* _SWTPM_NVSTORE_H */ diff --git a/src/swtpm/swtpm_nvstore_dir.c b/src/swtpm/swtpm_nvstore_dir.c new file mode 100644 index 0000000..bb7ef64 --- /dev/null +++ b/src/swtpm/swtpm_nvstore_dir.c @@ -0,0 +1,484 @@ +/********************************************************************************/ +/* */ +/* NVRAM File Abstraction Layer */ +/* Written by Ken Goldman */ +/* Adapted to SWTPM by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010, 2014, 2015. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include "config.h" + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include + +#include "swtpm.h" +#include "swtpm_debug.h" +#include "swtpm_nvstore.h" +#include "swtpm_nvstore_dir.h" +#include "key.h" +#include "logging.h" +#include "tpmstate.h" +#include "utils.h" + +struct nvram_backend_ops nvram_dir_ops = { + .prepare = SWTPM_NVRAM_Prepare_Dir, + .load = SWTPM_NVRAM_LoadData_Dir, + .store = SWTPM_NVRAM_StoreData_Dir, + .delete = SWTPM_NVRAM_DeleteName_Dir, +}; + +/* SWTPM_NVRAM_GetFilenameForName() constructs a rooted file name from the name. + + The filename is of the form: + + tpm_state_path/tpm_number.name + + A temporary filename used to write to may be created. It should be rename()'d to + the non-temporary filename. +*/ + +static TPM_RESULT +SWTPM_NVRAM_GetFilenameForName(char *filename, /* output: rooted filename */ + size_t bufsize, + uint32_t tpm_number, + const char *name, /* input: abstract name */ + bool is_tempfile, /* input: is temporary file? */ + const char *tpm_state_path) +{ + TPM_RESULT res = TPM_SUCCESS; + int n; + const char *suffix = ""; + + TPM_DEBUG(" SWTPM_NVRAM_GetFilenameForName: For name %s\n", name); + + switch (tpmstate_get_version()) { + case TPMLIB_TPM_VERSION_1_2: + break; + case TPMLIB_TPM_VERSION_2: + suffix = "2"; + break; + } + + if (is_tempfile) { + n = snprintf(filename, bufsize, "%s/TMP%s-%02lx.%s", + tpm_state_path, suffix, (unsigned long)tpm_number, name); + } else { + n = snprintf(filename, bufsize, "%s/tpm%s-%02lx.%s", + tpm_state_path, suffix, (unsigned long)tpm_number, name); + } + if ((size_t)n > bufsize) { + res = TPM_FAIL; + } + + TPM_DEBUG(" SWTPM_NVRAM_GetFilenameForName: File name %s\n", filename); + + return res; +} + +static const char * +SWTPM_NVRAM_Uri_to_Dir(const char *uri) +{ + return uri + strlen("dir://"); +} + +static TPM_RESULT +SWTPM_NVRAM_Validate_Dir(const char *tpm_state_path) +{ + TPM_RESULT rc = 0; + size_t length; + + /* TPM_NV_DISK TPM emulation stores in local directory determined by environment variable. */ + if (rc == 0) { + if (tpm_state_path == NULL) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_Validate_Dir: Error (fatal), TPM_PATH environment " + "variable not set\n"); + rc = TPM_FAIL; + } + } + + /* check that the directory name plus a file name will not overflow FILENAME_MAX */ + if (rc == 0) { + length = strlen(tpm_state_path); + if ((length + TPM_FILENAME_MAX) > FILENAME_MAX) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_Validate_Dir: Error (fatal), TPM state path name " + "%s too large\n", tpm_state_path); + rc = TPM_FAIL; + } + } + if (rc == 0) + TPM_DEBUG("SWTPM_NVRAM_Validate_Dir: Rooted state path %s\n", tpm_state_path); + + return rc; +} + +static TPM_RESULT +SWTPM_NVRAM_Lock_Dir(const char *tpm_state_path) +{ + TPM_RESULT rc = 0; + int fd; + char *lockfile = NULL; + struct flock flock = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0, + }; + + if (asprintf(&lockfile, "%s/.lock", tpm_state_path) < 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_Lock_Dir: Could not asprintf lock filename\n"); + return TPM_FAIL; + } + + fd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, 0660); + if (fd < 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_Lock_Dir: Could not open lockfile: %s\n", + strerror(errno)); + rc = TPM_FAIL; + goto exit; + } + + if (fcntl(fd, F_SETLK, &flock) < 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_Lock_Dir: Could not lock access to lockfile: %s\n", + strerror(errno)); + rc = TPM_FAIL; + close(fd); + } +exit: + free(lockfile); + + return rc; +} + +TPM_RESULT +SWTPM_NVRAM_Prepare_Dir(const char *uri) +{ + TPM_RESULT rc = 0; + const char *tpm_state_path = NULL; + + tpm_state_path = SWTPM_NVRAM_Uri_to_Dir(uri); + if (rc == 0) + rc = SWTPM_NVRAM_Validate_Dir(tpm_state_path); + if (rc == 0) + rc = SWTPM_NVRAM_Lock_Dir(tpm_state_path); + + return rc; +} + +TPM_RESULT +SWTPM_NVRAM_LoadData_Dir(unsigned char **data, + uint32_t *length, + uint32_t tpm_number, + const char *name, + const char *uri) +{ + TPM_RESULT rc = 0; + int irc; + size_t src; + int fd = -1; + char filename[FILENAME_MAX]; /* rooted file name from name */ + struct stat statbuf; + const char *tpm_state_path = NULL; + + tpm_state_path = SWTPM_NVRAM_Uri_to_Dir(uri); + + /* open the file */ + if (rc == 0) { + /* map name to the rooted filename */ + rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename), + tpm_number, name, false, + tpm_state_path); + } + + if (rc == 0) { + TPM_DEBUG(" SWTPM_NVRAM_LoadData: Opening file %s\n", filename); + fd = open(filename, O_RDONLY); /* closed @1 */ + if (fd < 0) { /* if failure, determine cause */ + if (errno == ENOENT) { + TPM_DEBUG("SWTPM_NVRAM_LoadData: No such file %s\n", + filename); + rc = TPM_RETRY; /* first time start up */ + } + else { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_LoadData: Error (fatal) opening " + "%s for read, %s\n", filename, strerror(errno)); + rc = TPM_FAIL; + } + } + } + + if (rc == 0) { + if (fchmod(fd, tpmstate_get_mode()) < 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_LoadData: Could not fchmod %s : %s\n", + filename, strerror(errno)); + rc = TPM_FAIL; + } + } + + /* determine the file length */ + if (rc == 0) { + irc = fstat(fd, &statbuf); + if (irc == -1L) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_LoadData: Error (fatal) fstat'ing %s, %s\n", + filename, strerror(errno)); + rc = TPM_FAIL; + } + } + if (rc == 0) { + *length = statbuf.st_size; /* save the length */ + } + /* allocate a buffer for the actual data */ + if ((rc == 0) && *length != 0) { + TPM_DEBUG(" SWTPM_NVRAM_LoadData: Reading %u bytes of data\n", *length); + *data = malloc(*length); + if (!*data) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_LoadData: Error (fatal) allocating %u " + "bytes\n", *length); + rc = TPM_FAIL; + } + } + /* read the contents of the file into the data buffer */ + if ((rc == 0) && *length != 0) { + src = read(fd, *data, *length); + if (src != *length) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_LoadData: Error (fatal), data read of %u " + "only read %lu\n", *length, (unsigned long)src); + rc = TPM_FAIL; + } + } + /* close the file */ + if (fd >= 0) { + TPM_DEBUG(" SWTPM_NVRAM_LoadData: Closing file %s\n", filename); + irc = close(fd); /* @1 */ + if (irc != 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_LoadData: Error (fatal) closing file %s\n", + filename); + rc = TPM_FAIL; + } + else { + TPM_DEBUG(" SWTPM_NVRAM_LoadData: Closed file %s\n", filename); + } + } + + return rc; +} + +TPM_RESULT +SWTPM_NVRAM_StoreData_Dir(unsigned char *filedata, + uint32_t filedata_length, + uint32_t tpm_number, + const char *name, + const char *uri) +{ + TPM_RESULT rc = 0; + int fd = -1; + int dir_fd = -1; + uint32_t lrc; + int irc; + char tmpfile[FILENAME_MAX]; /* rooted temporary file */ + char filename[FILENAME_MAX]; /* rooted file name from name */ + const char *tpm_state_path = NULL; + + tpm_state_path = SWTPM_NVRAM_Uri_to_Dir(uri); + + if (rc == 0) { + /* map name to the rooted filename */ + rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename), + tpm_number, name, false, + tpm_state_path); + } + + if (rc == 0) { + /* map name to the rooted temporary file */ + rc = SWTPM_NVRAM_GetFilenameForName(tmpfile, sizeof(tmpfile), + tpm_number, name, true, + tpm_state_path); + } + + if (rc == 0) { + /* open the file */ + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Opening file %s\n", tmpfile); + fd = open(tmpfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, + tpmstate_get_mode()); /* closed @1 */ + if (fd < 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_StoreData: Error (fatal) opening %s for " + "write failed, %s\n", tmpfile, strerror(errno)); + rc = TPM_FAIL; + } + } + + /* write the data to the file */ + if (rc == 0) { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Writing %u bytes of data\n", + filedata_length); + lrc = write_full(fd, filedata, filedata_length); + if (lrc != filedata_length) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_StoreData: Error (fatal), data write " + "of %u only wrote %u\n", filedata_length, lrc); + rc = TPM_FAIL; + } + } + if (rc == 0 && fd >= 0) { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Syncing file %s\n", tmpfile); + irc = fsync(fd); + if (irc != 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_StoreData: Error (fatal) syncing file, %s\n", + strerror(errno)); + rc = TPM_FAIL; + } else { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Synced file %s\n", tmpfile); + } + } + if (fd >= 0) { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closing file %s\n", tmpfile); + irc = close(fd); /* @1 */ + if (irc != 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_StoreData: Error (fatal) closing file\n"); + rc = TPM_FAIL; + } + else { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closed file %s\n", tmpfile); + } + } + + if (rc == 0 && fd >= 0) { + irc = rename(tmpfile, filename); + if (irc != 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_StoreData: Error (fatal) renaming file: %s\n", + strerror(errno)); + rc = TPM_FAIL; + } else { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Renamed file to %s\n", filename); + } + } + + /* + * Quote from linux man 2 fsync: + * Calling fsync() does not necessarily ensure that the entry in the + * directory containing the file has also reached disk. For that an + * explicit fsync() on a file descriptor for the directory is also needed. + */ + if (rc == 0 && fd >= 0) { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Opening dir %s\n", tpm_state_path); + dir_fd = open(tpm_state_path, O_RDONLY); + if (dir_fd < 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_StoreData: Error (fatal) opening %s for " + "fsync failed, %s\n", tpm_state_path, strerror(errno)); + rc = TPM_FAIL; + } + } + if (rc == 0 && dir_fd >= 0) { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Syncing dir %s\n", tpm_state_path); + irc = fsync(dir_fd); + if (irc != 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_StoreData: Error (fatal) syncing dir, %s\n", + strerror(errno)); + rc = TPM_FAIL; + } else { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Synced dir %s\n", tpm_state_path); + } + } + if (dir_fd >= 0) { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closing dir %s\n", tpm_state_path); + irc = close(dir_fd); + if (irc != 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_StoreData: Error (fatal) closing dir\n"); + rc = TPM_FAIL; + } else { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closed dir %s\n", tpm_state_path); + } + } + + if (rc != 0 && fd >= 0) { + unlink(tmpfile); + } + + return rc; +} + +TPM_RESULT SWTPM_NVRAM_DeleteName_Dir(uint32_t tpm_number, + const char *name, + TPM_BOOL mustExist, + const char *uri) +{ + TPM_RESULT rc = 0; + int irc; + char filename[FILENAME_MAX]; /* rooted file name from name */ + const char *tpm_state_path = NULL; + + tpm_state_path = SWTPM_NVRAM_Uri_to_Dir(uri); + + TPM_DEBUG(" SWTPM_NVRAM_DeleteName: Name %s\n", name); + /* map name to the rooted filename */ + rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename), + tpm_number, name, false, + tpm_state_path); + if (rc == 0) { + irc = remove(filename); + if ((irc != 0) && /* if the remove failed */ + (mustExist || /* if any error is a failure, or */ + (errno != ENOENT))) { /* if error other than no such file */ + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_DeleteName: Error, (fatal) file " + "remove failed, errno %d\n", errno); + rc = TPM_FAIL; + } + } + return rc; +} diff --git a/src/swtpm/swtpm_nvstore_dir.h b/src/swtpm/swtpm_nvstore_dir.h new file mode 100644 index 0000000..eec1dfd --- /dev/null +++ b/src/swtpm/swtpm_nvstore_dir.h @@ -0,0 +1,78 @@ +/********************************************************************************/ +/* */ +/* NVRAM Utilities */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef _SWTPM_NVSTORE_DIR_H +#define _SWTPM_NVSTORE_DIR_H + +#include +#include + +/* characters in the TPM base file name, 14 for file name, slash, NUL terminator, etc. + + This macro is used once during initialization to ensure that the TPM_PATH environment variable + length will not cause the rooted file name to overflow file name buffers. +*/ + +#define TPM_FILENAME_MAX 20 + +TPM_RESULT +SWTPM_NVRAM_Prepare_Dir(const char *uri); + +TPM_RESULT +SWTPM_NVRAM_LoadData_Dir(unsigned char **data, + uint32_t *length, + uint32_t tpm_number, + const char *name, + const char *uri); + +TPM_RESULT +SWTPM_NVRAM_StoreData_Dir(unsigned char *filedata, + uint32_t filedata_length, + uint32_t tpm_number, + const char *name, + const char *uri); + +TPM_RESULT +SWTPM_NVRAM_DeleteName_Dir(uint32_t tpm_number, + const char *name, + TPM_BOOL mustExist, + const char *uri); + +extern struct nvram_backend_ops nvram_dir_ops; + +#endif /* _SWTPM_NVSTORE_DIR_H */ diff --git a/src/swtpm/tpmlib.c b/src/swtpm/tpmlib.c index 569a645..b9eb83f 100644 --- a/src/swtpm/tpmlib.c +++ b/src/swtpm/tpmlib.c @@ -51,7 +51,7 @@ #include "tpmlib.h" #include "logging.h" #include "tpm_ioctl.h" -#include "swtpm_nvfile.h" +#include "swtpm_nvstore.h" #include "locality.h" #ifdef WITH_VTPM_PROXY #include "vtpm_proxy.h" diff --git a/src/swtpm/tpmstate.c b/src/swtpm/tpmstate.c index 7437db1..2eefdbc 100644 --- a/src/swtpm/tpmstate.c +++ b/src/swtpm/tpmstate.c @@ -37,6 +37,7 @@ #include "config.h" +#define _GNU_SOURCE #include #include #include @@ -45,32 +46,44 @@ #include "tpmstate.h" #include "logging.h" +#include "swtpm_nvstore.h" -static char *g_tpmstatedir; +static char *g_backend_uri; static mode_t g_tpmstate_mode = 0640; - -int tpmstate_set_dir(char *tpmstatedir) -{ - g_tpmstatedir = strdup(tpmstatedir); - if (!g_tpmstatedir) { - logprintf(STDERR_FILENO, "Out of memory.\n"); - return -1; - } - - return 0; -} +static TPMLIB_TPMVersion g_tpmstate_version = TPMLIB_TPM_VERSION_1_2; void tpmstate_global_free(void) { - free(g_tpmstatedir); - g_tpmstatedir = NULL; + free(g_backend_uri); + g_backend_uri = NULL; } -const char *tpmstate_get_dir(void) +int tpmstate_set_backend_uri(char *backend_uri) { - if (g_tpmstatedir) - return g_tpmstatedir; - return getenv("TPM_PATH"); + g_backend_uri = strdup(backend_uri); + if (!g_backend_uri) { + logprintf(STDERR_FILENO, "Out of memory.\n"); + return -1; + } + + return 0; +} + +const char *tpmstate_get_backend_uri(void) +{ + if (g_backend_uri) + return g_backend_uri; + + if (getenv("TPM_PATH")) { + if (asprintf(&g_backend_uri, "dir://%s", getenv("TPM_PATH")) < 0) { + logprintf(STDERR_FILENO, + "Could not asprintf TPM backend uri\n"); + return NULL; + } + return g_backend_uri; + } + + return NULL; } int tpmstate_set_mode(mode_t mode) @@ -84,3 +97,13 @@ mode_t tpmstate_get_mode(void) { return g_tpmstate_mode; } + +void tpmstate_set_version(TPMLIB_TPMVersion version) +{ + g_tpmstate_version = version; +} + +TPMLIB_TPMVersion tpmstate_get_version(void) +{ + return g_tpmstate_version; +} diff --git a/src/swtpm/tpmstate.h b/src/swtpm/tpmstate.h index a958598..9e37d8e 100644 --- a/src/swtpm/tpmstate.h +++ b/src/swtpm/tpmstate.h @@ -39,11 +39,16 @@ #define _SWTPM_TPMSTATE_H_ #include +#include + +int tpmstate_set_backend_uri(char *backend_uri); +const char *tpmstate_get_backend_uri(void); -int tpmstate_set_dir(char *tpmstatdir); -const char *tpmstate_get_dir(void); int tpmstate_set_mode(mode_t mode); mode_t tpmstate_get_mode(void); void tpmstate_global_free(void); +void tpmstate_set_version(TPMLIB_TPMVersion version); +TPMLIB_TPMVersion tpmstate_get_version(void); + #endif /* _SWTPM_TPMSTATE_H_ */