Add interface for using TPM through the Linux device driver

Signed-off-by: Dimitar Tomov <dimi@designfirst.ee>
pull/91/head
Dimitar Tomov 2020-04-27 21:54:59 +03:00 committed by David Garske
parent f5b06ec1bc
commit 68d1f95d1e
4 changed files with 169 additions and 1 deletions

View File

@ -162,6 +162,19 @@ then
fi
# Linux kernel TPM device Support
AC_ARG_ENABLE([devtpm],
[AS_HELP_STRING([--enable-devtpm],[Enable use of TPM through the Linux kernel driver (default: disabled)])],
[ ENABLED_DEVTPM=$enableval ],
[ ENABLED_DEVTPM=no ]
)
if test "x$ENABLED_DEVTPM" = "xyes"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_LINUX_DEV"
fi
# STM ST33 Support
AC_ARG_ENABLE([st33],
[AS_HELP_STRING([--enable-st33],[Enable ST33 TPM Support (default: disabled)])],

View File

@ -8,7 +8,8 @@ src_libwolftpm_la_SOURCES = \
src/tpm2.c \
src/tpm2_packet.c \
src/tpm2_tis.c \
src/tpm2_wrap.c
src/tpm2_wrap.c \
src/tpm2_linux.c
src_libwolftpm_la_CFLAGS = -DBUILDING_WOLFTPM $(AM_CFLAGS)
src_libwolftpm_la_CPPFLAGS = -DBUILDING_WOLFTPM $(AM_CPPFLAGS)
src_libwolftpm_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${WOLFTPM_LIBRARY_VERSION}

116
src/tpm2_linux.c 100644
View File

@ -0,0 +1,116 @@
/* tpm2_linux.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfTPM.
*
* wolfTPM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfTPM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <wolftpm/tpm2_linux.h>
#include <wolftpm/tpm2_packet.h>
#include <wolftpm/tpm2_wrap.h> /* Needed only for WOLFTPM2_MAX_BUFFER */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
#include <errno.h>
#include <string.h>
#define TPM2_LINUX_DEV "/dev/tpm0"
#define TPM2_LINUX_DEV_POLL_TIMEOUT -1 /* Infinite time for poll events */
#define TPM2_LINUX_DEV_RSP_SIZE WOLFTPM2_MAX_BUFFER
/* Linux kernels older than v4.20 (before December 2018) do not support
* partial reads. The only way to receive a complete response is to read
* the maximum allowed TPM response from the kernel, which is 4K. And most
* of the ARM systems use older kernels, such as the RPI that uses v4.12
*
* The caller knows what the expected outcome of the operation is. Therefore,
* the response size is limited only by the WOLFTPM2_MAX_BUFFER used to limit
* the WOLFTPM2_BUFFER in wolfTPM wrappers */
/* Talk to a TPM device exposed by the Linux tpm_tis driver */
int TPM2_LINUX_SendCommand(TPM2_CTX* ctx, byte* cmd, word16 cmdSz)
{
int rc = TPM_RC_FAILURE;
int fd, rspSz;
int rc_poll, nfds= 1; /* Polling single TPM dev file */
struct pollfd fds;
#ifdef DEBUG_WOLFTPM /* TODO: Change to WOLFTPM_DEBUG_VERBOSE */
printf("Command size: %d\n", cmdSz);
TPM2_PrintBin(cmd, cmdSz);
#endif
fd = open(TPM2_LINUX_DEV, O_RDWR | O_NONBLOCK);
if (fd > 0) {
/* Send the TPM command */
if (write(fd, cmd, cmdSz) == cmdSz) {
fds.fd = fd;
fds.events = POLLIN;
/* Wait for response to be available */
rc_poll = poll(&fds, nfds, TPM2_LINUX_DEV_POLL_TIMEOUT);
if (rc_poll > 0 && fds.revents == POLLIN) {
rspSz = read(fd, cmd, TPM2_LINUX_DEV_RSP_SIZE);
if (rspSz > 0) {
UINT32 tmpSz;
XMEMCPY(&tmpSz, &cmd[2], sizeof(UINT32));
rspSz = TPM2_Packet_SwapU32(tmpSz);
/* Enough bytes for a TPM response? */
if (rspSz >= TPM2_HEADER_SIZE) {
rc = TPM_RC_SUCCESS;
}
#ifdef DEBUG_WOLFTPM
else
{
printf("Response size is %d bytes, not enough to "
"hold TPM response.\n", rspSz);
}
}
else if (rspSz == 0) {
printf("Received EOF instead of TPM response.\n");
}
else {
printf("Failed to read from TPM device %d, got errno %d"
" = %s\n", fd, errno, strerror(errno));
#endif
}
}
#ifdef DEBUG_WOLFTPM /* TODO: Change to WOLFTPM_DEBUG_TIMEOUT */
else {
printf("Failed to get a response from fd %d, got errno %d ="
"%s\n", fd, errno, strerror(errno));
}
#endif
}
close(fd);
}
#ifdef DEBUG_WOLFTPM /* TODO: Change to WOLFTPM_DEBUG_VERBOSE */
if (rspSz > 0) {
printf("Response size: %d\n", rspSz);
TPM2_PrintBin(cmd, rspSz);
}
#endif
(void)ctx;
return rc;
}

View File

@ -0,0 +1,38 @@
/* tpm2_linux.h
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfTPM.
*
* wolfTPM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfTPM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _TPM2_LINUX_H_
#define _TPM2_LINUX_H_
#include <wolftpm/tpm2.h>
#ifdef __cplusplus
extern "C" {
#endif
/* TPM2 IO for using TPM through the Linux kernel driver */
int TPM2_LINUX_SendCommand(TPM2_CTX* ctx, byte* cmd, word16 cmdSz);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _TPM2_LINUX_H_ */