Integrate the TPM 2 into the library; do not compile with TPM 2 yet

Introduce --with-tpm2 for ./configure to enable building with
TPM 2 functionality. Delay the building of TPM 2 code until more
patches are applied and the vTPM state that's created has a chance
of being backwards compatible.

Extend the libtpms API to allow user to choose version of TPM.

Missing functionality at this point:
- TPM 2 needs to be extended to serialize and deserialize its volatile state
- Handling of the establishment bit

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
This commit is contained in:
Stefan Berger 2016-12-21 16:26:19 -05:00
parent 7675c9371c
commit 3cf528aaac
22 changed files with 810 additions and 22 deletions

View File

@ -125,6 +125,18 @@ openssl)
;;
esac
AC_ARG_WITH([tpm2],
AC_HELP_STRING([--with-tpm2],
[build libtpms with TPM2 support (experimental)]),
AC_MSG_RESULT([Building with TPM2 support])
if test "x$cryptolib" = "xfreebl"; then
AC_MSG_ERROR([TPM2 support requires openssl crypto library])
fi
AC_DEFINE_UNQUOTED([WITH_TPM2], 1, [whether to support TPM2])
AM_CONDITIONAL(WITH_TPM2, true),
AM_CONDITIONAL(WITH_TPM2, false)
)
LT_INIT
AC_PROG_CC
AC_PROG_INSTALL
@ -181,14 +193,24 @@ AC_OUTPUT
if test -z "$enable_debug" ; then
enable_debug="no"
fi
if test -z "$with_tpm2"; then
with_tpm2=no
fi
if test "x$with_tpm2" = "xyes"; then
# remove the following to compile anyway; created vTPM state
# will not be compatible
AC_MSG_ERROR([Not compiling with TPM2 support])
exit 1
fi
echo
echo "CFLAGS=$CFLAGS"
echo "HARDENING_CFLAGS=$HARDENING_CFLAGS"
echo "LDFLAGS=$LDFLAGS"
echo
echo "Version to build : $PACKAGE_VERSION"
echo "Crypto library : $cryptolib"
echo "Debug build : $enable_debug"
echo "Version to build : $PACKAGE_VERSION"
echo "Crypto library : $cryptolib"
echo "Debug build : $enable_debug"
echo "With TPM2 support : $with_tpm2"
echo
echo

8
dist/libtpms.spec vendored
View File

@ -5,8 +5,8 @@
%define release 1
# Valid crypto subsystems are 'freebl' and 'openssl'
%if "%{crypto_subsystem}" == ""
%define crypto_subsystem freebl
%if "%{?crypto_subsystem}" == ""
%define crypto_subsystem openssl
%endif
# Valid build types are 'production' or 'debug'
@ -83,7 +83,11 @@ Libtpms header files and documentation.
%endif
./bootstrap.sh
%if %{build_type} == debug
CFLAGS=-O0
%endif
%configure \
--with-tpm2 \
--disable-static \
--prefix=/usr \
--libdir=%{_libdir} \

View File

@ -5,8 +5,8 @@
%define release 1
# Valid crypto subsystems are 'freebl' and 'openssl'
%if "%{crypto_subsystem}" == ""
%define crypto_subsystem freebl
%if "%{?crypto_subsystem}" == ""
%define crypto_subsystem openssl
%endif
# Valid build types are 'production' or 'debug'
@ -83,7 +83,11 @@ Libtpms header files and documentation.
%endif
./bootstrap.sh
%if %{build_type} == debug
CFLAGS=-O0
%endif
%configure \
--with-tpm2 \
--disable-static \
--prefix=/usr \
--libdir=%{_libdir} \

View File

@ -63,6 +63,13 @@ extern "C" {
uint32_t TPMLIB_GetVersion(void);
/* TPM implementation version to choose */
typedef enum TPMLIB_TPMVersion {
TPMLIB_TPM_VERSION_1_2,
TPMLIB_TPM_VERSION_2,
} TPMLIB_TPMVersion;
TPM_RESULT TPMLIB_ChooseTPMVersion(TPMLIB_TPMVersion ver);
TPM_RESULT TPMLIB_MainInit(void);
void TPMLIB_Terminate(void);
@ -73,6 +80,8 @@ TPM_RESULT TPMLIB_Process(unsigned char **respbuffer, uint32_t *resp_size,
TPM_RESULT TPMLIB_VolatileAll_Store(unsigned char **buffer, uint32_t *buflen);
TPM_RESULT TPMLIB_CancelCommand(void);
enum TPMLIB_TPMProperty {
TPMPROP_TPM_RSA_KEY_LENGTH_MAX = 1,
TPMPROP_TPM_BUFFER_MAX,

View File

@ -63,6 +63,13 @@ extern "C" {
uint32_t TPMLIB_GetVersion(void);
/* TPM implementation version to choose */
typedef enum TPMLIB_TPMVersion {
TPMLIB_TPM_VERSION_1_2,
TPMLIB_TPM_VERSION_2,
} TPMLIB_TPMVersion;
TPM_RESULT TPMLIB_ChooseTPMVersion(TPMLIB_TPMVersion ver);
TPM_RESULT TPMLIB_MainInit(void);
void TPMLIB_Terminate(void);
@ -73,6 +80,8 @@ TPM_RESULT TPMLIB_Process(unsigned char **respbuffer, uint32_t *resp_size,
TPM_RESULT TPMLIB_VolatileAll_Store(unsigned char **buffer, uint32_t *buflen);
TPM_RESULT TPMLIB_CancelCommand(void);
enum TPMLIB_TPMProperty {
TPMPROP_TPM_RSA_KEY_LENGTH_MAX = 1,
TPMPROP_TPM_BUFFER_MAX,

View File

@ -52,6 +52,7 @@ TPM_RESULT TPM_IO_Hash_Data(const unsigned char *data,
TPM_RESULT TPM_IO_Hash_End(void);
TPM_RESULT TPM_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished);
TPM_RESULT TPM_IO_TpmEstablished_Reset(void);
#ifdef __cplusplus
}

View File

@ -8,6 +8,8 @@
man3_PODS = \
TPM_IO_Hash_Start.pod \
TPM_IO_TpmEstablished_Get.pod \
TPMLIB_CancelCommand.pod \
TPMLIB_ChooseTPMVersion.pod \
TPMLIB_DecodeBlob.pod \
TPMLIB_GetInfo.pod \
TPMLIB_GetTPMProperty.pod \
@ -29,12 +31,15 @@ man3_MANS = \
TPMLIB_GetState.3 \
TPMLIB_SetDebugPrefix.3 \
TPMLIB_SetDebugLevel.3 \
TPM_IO_TpmEstablished_Reset.3 \
TPMLIB_Terminate.3 \
TPM_Realloc.3
man3_MANS += \
TPM_IO_Hash_Start.3 \
TPM_IO_TpmEstablished_Get.3 \
TPMLIB_CancelCommand.3 \
TPMLIB_ChooseTPMVersion.3 \
TPMLIB_DecodeBlob.3 \
TPMLIB_GetInfo.3 \
TPMLIB_GetTPMProperty.3 \

View File

@ -0,0 +1,29 @@
=head1 NAME
TPMLIB_CancelCommand - Cancel a TPM command
=head1 LIBRARY
TPM library (libtpms, -ltpms)
=head1 SYNOPSIS
B<#include <libtpms/tpm_library.h>>
B<uint32_t TPMLIB_CancelCommand(void);>
=head1 DESCRIPTION
The B<TPMLIB_CancelCommand()> function indicates that the ongoing processing
of a TPM command is to be cancelled. The cancellation will only
be effective for certain time consuming operations, such as the creation
of keys.
Note that an implementation that wants to support cancellation of commands
needs to process TPM commands in one thread and cancel them in another.
=head1 SEE ALSO
B<TPMLIB_Process>(3)
=cut

View File

@ -0,0 +1,52 @@
=head1 NAME
TPMLIB_ChooseTPMVersion - Choose the version of the TPM
=head1 SYNOPSIS
B<#include <libtpms/tpm_types.h>>
B<#include <libtpms/tpm_library.h>>
B<TPM_RESULT TPMLIB_ChooseTPMVersion(TPMLIB_TPMVersion> I<ver>B<);>
typedef enum TPMLIB_TPMVersion {
TPMLIB_TPM_VERSION_1_2,
TPMLIB_TPM_VERSION_2,
} TPMLIB_TPMVersion;
=head1 DESCRIPTION
The B<TPMLIB_ChooseTPMVersion()> function is used to choose the version
of the TPM, either a TPM 1.2 or TPM 2.
This function must be called before B<TPMLIB_MainInit()> is called and
will otherwise return an error. This function may be called again once
B<TPMLIB_Terminate()> has been called.
If this function is not called, the last chosen TPM version will be
started with B<TPMLIB_MainInit()>. If this function is not called,
a TPM 1.2 will be used.
=head1 ERRORS
=over 4
=item B<TPM_SUCCESS>
The version of the TPM was chosen successfully.
=item B<TPM_FAIL>
The choice of the TPM was wrong, or TPMLIB_MainInit() has already been called.
=back
For a complete list of TPM error codes please consult the include file
B<libtpms/tpm_error.h>
=head1 SEE ALSO
B<TPMLIB_MainInit>(3), B<TPMLIB_Terminate>(3)
=cut

View File

@ -22,6 +22,11 @@ This function can be called before or after the TPM has been created.
The current implementation of libtpms will return the same value before
and after the TPM was started.
With the introduction of the function B<TPMLIB_ChooseTPMVersion()>,
the call to this function should be executed after the TPM version
has been chosen. The reason is that different TPM versions may return
different values.
The following properties have been defined:
=over 4
@ -142,6 +147,7 @@ B<libtpms/tpm_error.h>
=head1 SEE ALSO
B<TPMLIB_MainInit>(3), B<TPMLIB_Terminate>(3),
B<TPMLIB_Process>(3), B<TPMLIB_RegisterCallbacks>(3), B<TPMLIB_GetVersion>(3)
B<TPMLIB_Process>(3), B<TPMLIB_RegisterCallbacks>(3), B<TPMLIB_GetVersion>(3),
B<TPMLIB_ChooseTPMVersion>(3)
=cut

View File

@ -143,10 +143,15 @@ TPM_IO_TpmEstablished_Get \- get the value of the TPMEstablished flag
\&\fB#include <libtpms/tpm_error.h\fR>
.PP
\&\fB\s-1TPM_RESULT\s0 TPM_IO_TpmEstablished_Get(\s-1TPM_BOOL\s0\fR *\fItpmEstablished\fR\fB);\fR
.PP
\&\fB\s-1TPM_RESULT\s0 TPM_IO_TpmEstablished_Reset(void);\fR
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
The \fB\f(BITPM_IO_TpmEstablished_Get()\fB\fR function returns the value of the
TPMEstablished flag of the \s-1TPM\s0's permanent data.
.PP
The \fB\f(BITPM_IO_TpmEstablished_Reset()\fB\fR function resets the TPMEstablished
flag.
.SH "ERRORS"
.IX Header "ERRORS"
.IP "\fB\s-1TPM_SUCCESS\s0\fR" 4
@ -155,6 +160,9 @@ The function completed sucessfully.
.IP "\fB\s-1TPM_FAIL\s0\fR" 4
.IX Item "TPM_FAIL"
General failure.
.IP "\fB\s-1TPM_BAD_LOCALITY\s0\fR" 4
.IX Item "TPM_BAD_LOCALITY"
The locality used for resetting the flags is wrong.
.PP
For a complete list of \s-1TPM\s0 error codes please consult the include file
\&\fBlibtpms/tpm_error.h\fR

View File

@ -1,6 +1,8 @@
=head1 NAME
TPM_IO_TpmEstablished_Get - get the value of the TPMEstablished flag
TPM_IO_TpmEstablished_Get - get the value of the TPMEstablished flag
TPM_IO_TpmEstablished_Reset - reset the TPMEstablished flag
=head1 LIBRARY
@ -16,11 +18,16 @@ B<#include <libtpms/tpm_error.h>>
B<TPM_RESULT TPM_IO_TpmEstablished_Get(TPM_BOOL> *I<tpmEstablished>B<);>
B<TPM_RESULT TPM_IO_TpmEstablished_Reset(void);>
=head1 DESCRIPTION
The B<TPM_IO_TpmEstablished_Get()> function returns the value of the
TPMEstablished flag of the TPM's permanent data.
The B<TPM_IO_TpmEstablished_Reset()> function resets the TPMEstablished
flag.
=head1 ERRORS
=over 4
@ -33,6 +40,10 @@ The function completed sucessfully.
General failure.
=item B<TPM_BAD_LOCALITY>
The locality used for resetting the flags is wrong.
=back
For a complete list of TPM error codes please consult the include file

View File

@ -0,0 +1 @@
.so man3/TPM_IO_TpmEstablished_Get.3

View File

@ -159,6 +159,8 @@ endif # LIBTPMS_USE_FREEBL
# TPM2
#
if WITH_TPM2
noinst_LTLIBRARIES += libtpms_tpm2.la
libtpms_la_LIBADD += libtpms_tpm2.la
@ -174,6 +176,8 @@ libtpms_tpm2_la_CFLAGS = $(common_CFLAGS) \
libtpms_tpm2_la_CFLAGS += -D_POSIX_
libtpms_tpm2_la_CFLAGS += -DTPM_POSIX
# build with libtpms callback support
libtpms_tpm2_la_CFLAGS += -DTPM_LIBTPMS_CALLBACKS
libtpms_tpm2_la_SOURCES = \
tpm2/AlgorithmCap.c \
@ -256,7 +260,9 @@ libtpms_tpm2_la_SOURCES = \
tpm2/TpmFail.c \
tpm2/Unique.c \
tpm2/Unmarshal.c \
tpm2/Vendor_TCG_Test.c
tpm2/Vendor_TCG_Test.c \
tpm_tpm2_interface.c \
tpm_tpm2_tis.c
noinst_HEADERS += \
tpm2/crypto/CryptDes_fp.h \
@ -503,6 +509,34 @@ libtpms_tpm2_la_CFLAGS += \
endif # LIBTPMS_USE_OPENSSL
# some of the original TPM2 files have been modified; in case of an update
# we do not want to loose these modifications
check:
n=`grep "TPM_LIBTPMS_CALLBACK" $(libtpms_tpm2_la_SOURCES) | wc -l`; \
exp=16; \
if test $$n -ne $$exp; then \
echo "TPM_LIBTPMS_CALLBACK occurrence has changed to $$n from $$exp"; \
exit 1; \
fi; \
n=`grep TPM_BUFFER_MAX tpm2/Implementation.h | grep -E "^#define" | wc -l`; \
exp=2; \
if test $$n -ne $$exp; then \
echo "Lost patches to tpm2/Implementation.h ?"; \
exit 1; \
fi
.PHONY: srccheck
srccheck:
@n=`grep -i "nuvo" $(libtpms_tpm2_la_SOURCES) | wc -l`; \
if test $$n -ne 0; then \
echo "Filter sources!"; \
exit 1; \
fi
all: srccheck
endif # WITH_TPM2
#
# Library API layer
#

View File

@ -23,6 +23,9 @@ LIBTPMS_0.5.1 {
LIBTPMS_0.6.0 {
global:
TPM_IO_TpmEstablished_Reset;
TPMLIB_CancelCommand;
TPMLIB_ChooseTPMVersion;
TPMLIB_GetInfo;
TPMLIB_GetState;
TPMLIB_SetBufferSize;

View File

@ -70,6 +70,12 @@
#include <assert.h>
#include "PlatformData.h"
#include "Platform_fp.h"
#include "tpm_library_intern.h"
#include "tpm_error.h"
#include "tpm_nvfilename.h"
#include "tpm_memory.h"
/* C.6.3. Functions */
/* C.6.3.1. _plat__NvErrors() */
/* This function is used by the simulator to set the error flags in the NV subsystem to simulate an
@ -104,6 +110,49 @@ _plat__NVEnable(
// Start assuming everything is OK
s_NV_unrecoverable = FALSE;
s_NV_recoverable = FALSE;
#ifdef TPM_LIBTPMS_CALLBACKS
struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
if (cbs->tpm_nvram_loaddata) {
unsigned char *data = NULL;
uint32_t length = 0;
uint32_t tpm_number = 0;
const char *name = TPM_PERMANENT_ALL_NAME;
TPM_RESULT ret;
ret = cbs->tpm_nvram_loaddata(&data, &length, tpm_number, name);
switch (ret) {
case TPM_RETRY:
if (!cbs->tpm_nvram_storedata) {
return -1;
}
memset(s_NV, 0, NV_MEMORY_SIZE);
/* first time; no file exists */
ret = cbs->tpm_nvram_storedata(s_NV, NV_MEMORY_SIZE,
tpm_number, name);
if (ret == TPM_SUCCESS) {
return 0;
}
return -1;
case TPM_SUCCESS:
/* got the data -- copy them to final dest. */
if (length != NV_MEMORY_SIZE) {
TPM_Free(data);
return -1;
}
memcpy(s_NV, data, length);
TPM_Free(data);
return 0;
case TPM_FAIL:
default:
return -1;
}
}
#endif /* TPM_LIBTPMS_CALLBACKS */
#ifdef FILE_BACKED_NV
if(s_NVFile != NULL)
return 0;
@ -166,6 +215,13 @@ _plat__NVDisable(
void
)
{
#ifdef TPM_LIBTPMS_CALLBACKS
struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
if (cbs->tpm_nvram_loaddata)
return;
#endif /* TPM_LIBTPMS_CALLBACKS */
#ifdef FILE_BACKED_NV
assert(s_NVFile != NULL);
// Close NV file
@ -189,6 +245,16 @@ _plat__IsNvAvailable(
// NV is not available if the TPM is in failure mode
if(!s_NvIsAvailable)
return 1;
#ifdef TPM_LIBTPMS_CALLBACKS
struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
if (cbs->tpm_nvram_loaddata &&
cbs->tpm_nvram_storedata) {
return 0;
}
#endif /* TPM_LIBTPMS_CALLBACKS */
#ifdef FILE_BACKED_NV
if(s_NVFile == NULL)
return 1;
@ -280,6 +346,23 @@ _plat__NvCommit(
void
)
{
#ifdef TPM_LIBTPMS_CALLBACKS
struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
if (cbs->tpm_nvram_storedata) {
uint32_t tpm_number = 0;
const char *name = TPM_PERMANENT_ALL_NAME;
TPM_RESULT ret;
ret = cbs->tpm_nvram_storedata(s_NV, NV_MEMORY_SIZE,
tpm_number, name);
if (ret == TPM_SUCCESS)
return 0;
return -1;
}
#endif /* TPM_LIBTPMS_CALLBACKS */
#ifdef FILE_BACKED_NV
// If NV file is not available, return failure
if(s_NVFile == NULL)

View File

@ -65,6 +65,10 @@
/* C.10.2. Includes */
#include "PlatformData.h"
#include "Platform_fp.h"
#include "tpm_library_intern.h"
#include "tpm_error.h"
/* C.10.3. Functions */
/* C.10.3.1. _plat__PhysicalPresenceAsserted() */
/* Check if physical presence is signaled */
@ -76,6 +80,21 @@ _plat__PhysicalPresenceAsserted(
void
)
{
#ifdef TPM_LIBTPMS_CALLBACKS
struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
if (cbs->tpm_io_getphysicalpresence) {
TPM_BOOL pp = 0;
uint32_t tpm_number = 0;
TPM_RESULT res;
res = cbs->tpm_io_getphysicalpresence(&pp, tpm_number);
if (res == TPM_SUCCESS) {
return pp;
}
}
#endif /* TPM_LIBTPMS_CALLBACKS */
// Do not know how to check physical presence without real hardware.
// so always return TRUE;
return s_physicalPresence;

View File

@ -77,6 +77,10 @@ static const struct tags_and_indices {
static const struct tpm_interface *const tpm_iface[] = {
&TPM12Interface,
#if WITH_TPM2
&TPM2Interface,
#endif
NULL,
};
static int debug_fd = -1;
@ -85,19 +89,50 @@ static char *debug_prefix = NULL;
static struct sized_buffer cached_blobs[TPMLIB_STATE_SAVE_STATE + 1];
static int tpmvers_choice = 0; /* default is TPM1.2 */
static TPM_BOOL tpmvers_locked = FALSE;
uint32_t TPMLIB_GetVersion(void)
{
return TPM_LIBRARY_VERSION;
}
TPM_RESULT TPMLIB_ChooseTPMVersion(TPMLIB_TPMVersion ver)
{
TPM_RESULT ret = TPM_SUCCESS;
/* TPMLIB_Terminate will reset previous choice */
if (tpmvers_locked)
return TPM_FAIL;
switch (ver) {
case TPMLIB_TPM_VERSION_1_2:
tpmvers_choice = 0; // entry 0 in tpm_iface
break;
case TPMLIB_TPM_VERSION_2:
#if WITH_TPM2
tpmvers_choice = 1; // entry 1 in tpm_iface
break;
#endif
default:
ret = TPM_FAIL;
}
return ret;
}
TPM_RESULT TPMLIB_MainInit(void)
{
return tpm_iface[0]->MainInit();
tpmvers_locked = TRUE;
return tpm_iface[tpmvers_choice]->MainInit();
}
void TPMLIB_Terminate(void)
{
tpm_iface[0]->Terminate();
tpm_iface[tpmvers_choice]->Terminate();
tpmvers_locked = FALSE;
}
/*
@ -113,7 +148,8 @@ TPM_RESULT TPMLIB_Process(unsigned char **respbuffer, uint32_t *resp_size,
uint32_t *respbufsize,
unsigned char *command, uint32_t command_size)
{
return tpm_iface[0]->Process(respbuffer, resp_size, respbufsize,
return tpm_iface[tpmvers_choice]->Process(respbuffer,
resp_size, respbufsize,
command, command_size);
}
@ -125,7 +161,15 @@ TPM_RESULT TPMLIB_Process(unsigned char **respbuffer, uint32_t *resp_size,
TPM_RESULT TPMLIB_VolatileAll_Store(unsigned char **buffer,
uint32_t *buflen)
{
return tpm_iface[0]->VolatileAllStore(buffer, buflen);
return tpm_iface[tpmvers_choice]->VolatileAllStore(buffer, buflen);
}
/*
* Have the TPM cancel an ongoing command
*/
TPM_RESULT TPMLIB_CancelCommand(void)
{
return tpm_iface[tpmvers_choice]->CancelCommand();
}
/*
@ -143,7 +187,7 @@ TPM_RESULT TPMLIB_GetTPMProperty(enum TPMLIB_TPMProperty prop,
break;
default:
return tpm_iface[0]->GetTPMProperty(prop, result);
return tpm_iface[tpmvers_choice]->GetTPMProperty(prop, result);
}
return TPM_SUCCESS;
@ -151,7 +195,7 @@ TPM_RESULT TPMLIB_GetTPMProperty(enum TPMLIB_TPMProperty prop,
char *TPMLIB_GetInfo(enum TPMLIB_InfoFlags flags)
{
return tpm_iface[0]->GetInfo(flags);
return tpm_iface[tpmvers_choice]->GetInfo(flags);
}
TPM_RESULT TPMLIB_SetState(enum TPMLIB_StateType st,
@ -168,35 +212,42 @@ TPM_RESULT TPMLIB_GetState(enum TPMLIB_StateType st,
TPM_RESULT TPM_IO_Hash_Start(void)
{
return tpm_iface[0]->HashStart();
return tpm_iface[tpmvers_choice]->HashStart();
}
TPM_RESULT TPM_IO_Hash_Data(const unsigned char *data, uint32_t data_length)
{
return tpm_iface[0]->HashData(data, data_length);
return tpm_iface[tpmvers_choice]->HashData(data, data_length);
}
TPM_RESULT TPM_IO_Hash_End(void)
{
return tpm_iface[0]->HashEnd();
return tpm_iface[tpmvers_choice]->HashEnd();
}
TPM_RESULT TPM_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished)
{
return tpm_iface[0]->TpmEstablishedGet(tpmEstablished);
return tpm_iface[tpmvers_choice]->TpmEstablishedGet(tpmEstablished);
}
TPM_RESULT TPM_IO_TpmEstablished_Reset(void)
{
return tpm_iface[tpmvers_choice]->TpmEstablishedReset();
}
uint32_t TPMLIB_SetBufferSize(uint32_t wanted_size,
uint32_t *min_size,
uint32_t *max_size)
{
return tpm_iface[0]->SetBufferSize(wanted_size, min_size, max_size);
return tpm_iface[tpmvers_choice]->SetBufferSize(wanted_size,
min_size,
max_size);
}
TPM_RESULT TPMLIB_ValidateState(enum TPMLIB_StateType st,
unsigned int flags)
{
return tpm_iface[0]->ValidateState(st, flags);
return tpm_iface[tpmvers_choice]->ValidateState(st, flags);
}
static struct libtpms_callbacks libtpms_cbs;

View File

@ -45,6 +45,9 @@
#define ROUNDUP(VAL, SIZE) \
( ( (VAL) + (SIZE) - 1 ) / (SIZE) ) * (SIZE)
#define _STRINGIFY(x) #x
#define STRINGIFY(x) _STRINGIFY(x)
struct libtpms_callbacks *TPMLIB_GetCallbacks(void);
/*
@ -59,10 +62,12 @@ struct tpm_interface {
uint32_t *respbufsize,
unsigned char *command, uint32_t command_size);
TPM_RESULT (*VolatileAllStore)(unsigned char **buffer, uint32_t *buflen);
TPM_RESULT (*CancelCommand)(void);
TPM_RESULT (*GetTPMProperty)(enum TPMLIB_TPMProperty prop,
int *result);
char *(*GetInfo)(enum TPMLIB_InfoFlags flags);
TPM_RESULT (*TpmEstablishedGet)(TPM_BOOL *tpmEstablished);
TPM_RESULT (*TpmEstablishedReset)(void);
TPM_RESULT (*HashStart)(void);
TPM_RESULT (*HashData)(const unsigned char *data,
uint32_t data_length);
@ -76,6 +81,7 @@ struct tpm_interface {
};
extern const struct tpm_interface TPM12Interface;
extern const struct tpm_interface TPM2Interface;
/* prototypes for TPM 1.2 */
TPM_RESULT TPM12_IO_Hash_Start(void);
@ -86,6 +92,8 @@ TPM_RESULT TPM12_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished);
uint32_t TPM12_GetBufferSize(void);
TPM_RESULT TPM12_IO_TpmEstablished_Reset(void);
/* internal logging function */
int TPMLIB_LogPrintf(const char *format, ...);
void TPMLIB_LogPrintfA(unsigned int indent, const char *format, ...);
@ -94,6 +102,16 @@ void TPMLIB_LogPrintfA(unsigned int indent, const char *format, ...);
TPMLIB_LogPrintfA(~0, "libtpms: "format, __VA_ARGS__)
#define TPMLIB_LogTPM12Error(format, ...) \
TPMLIB_LogPrintfA(~0, "libtpms/tpm12: "format, __VA_ARGS__)
#define TPMLIB_LogTPM2Error(format, ...) \
TPMLIB_LogPrintfA(~0, "libtpms/tpm2: "format, __VA_ARGS__)
/* prototypes for TPM2 */
TPM_RESULT TPM2_IO_Hash_Start(void);
TPM_RESULT TPM2_IO_Hash_Data(const unsigned char *data,
uint32_t data_length);
TPM_RESULT TPM2_IO_Hash_End(void);
TPM_RESULT TPM2_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished);
TPM_RESULT TPM2_IO_TpmEstablished_Reset(void);
struct sized_buffer {
unsigned char *buffer;

View File

@ -103,6 +103,12 @@ TPM_RESULT TPM12_VolatileAllStore(unsigned char **buffer,
return rc;
}
TPM_RESULT TPM12_CancelCommand(void)
{
return TPM_FAIL; /* not supported */
}
TPM_RESULT TPM12_GetTPMProperty(enum TPMLIB_TPMProperty prop,
int *result)
{
@ -510,9 +516,11 @@ const struct tpm_interface TPM12Interface = {
.Terminate = TPM12_Terminate,
.Process = TPM12_Process,
.VolatileAllStore = TPM12_VolatileAllStore,
.CancelCommand = TPM12_CancelCommand,
.GetTPMProperty = TPM12_GetTPMProperty,
.GetInfo = TPM12_GetInfo,
.TpmEstablishedGet = TPM12_IO_TpmEstablished_Get,
.TpmEstablishedReset = TPM12_IO_TpmEstablished_Reset,
.HashStart = TPM12_IO_Hash_Start,
.HashData = TPM12_IO_Hash_Data,
.HashEnd = TPM12_IO_Hash_End,

324
src/tpm_tpm2_interface.c Normal file
View File

@ -0,0 +1,324 @@
/********************************************************************************/
/* */
/* LibTPM TPM 2 call interface functions */
/* Written by Stefan Berger */
/* IBM Thomas J. Watson Research Center */
/* */
/* (c) Copyright IBM Corporation 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 <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "tpm_error.h"
#include "tpm_memory.h"
#include "tpm_library_intern.h"
#include "tpm_nvfilename.h"
#ifndef LIB_EXPORT
#define LIB_EXPORT
#endif
#include "tpm2/Tpm.h"
#include "tpm2/Manufacture_fp.h"
#include "tpm2/Platform_fp.h"
#include "tpm2/ExecCommand_fp.h"
#include "tpm2/TpmTcpProtocol.h"
#include "tpm2/Simulator_fp.h"
#include "tpm2/_TPM_Hash_Data_fp.h"
#include "tpm2/_TPM_Init_fp.h"
/*
* Check whether the main NVRAM file exists. Return TRUE if it doesn, FALSE otherwise
*/
TPM_BOOL _TPM2_CheckNVRAMFileExists(void)
{
#ifdef TPM_LIBTPMS_CALLBACKS
struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
const char *name = TPM_PERMANENT_ALL_NAME;
unsigned char *data = NULL;
uint32_t length = 0;
uint32_t tpm_number = 0;
TPM_RESULT ret;
if (cbs->tpm_nvram_loaddata) {
ret = cbs->tpm_nvram_loaddata(&data, &length, tpm_number, name);
TPM_Free(data);
if (ret == TPM_SUCCESS)
return TRUE;
}
#endif /* TPM_LIBTPMS_CALLBACKS */
return FALSE;
}
TPM_RESULT TPM2_MainInit(void)
{
TPM_RESULT ret = TPM_SUCCESS;
#ifdef TPM_LIBTPMS_CALLBACKS
struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
if (cbs->tpm_io_init) {
ret = cbs->tpm_io_init();
if (ret != TPM_SUCCESS)
return ret;
}
if (cbs->tpm_nvram_init) {
ret = cbs->tpm_nvram_init();
if (ret != TPM_SUCCESS)
return ret;
}
#endif /* TPM_LIBTPMS_CALLBACKS */
_rpc__Signal_PowerOff();
if (!_TPM2_CheckNVRAMFileExists()) {
_plat__NVEnable(NULL);
TPM_Manufacture(TRUE);
}
_rpc__Signal_PowerOn(FALSE);
_rpc__Signal_NvOn();
return ret;
}
void TPM2_Terminate(void)
{
TPM_TearDown();
}
TPM_RESULT TPM2_Process(unsigned char **respbuffer, uint32_t *resp_size,
uint32_t *respbufsize,
unsigned char *command, uint32_t command_size)
{
TPM_RESULT res = 0;
uint8_t locality = 0;
_IN_BUFFER req;
_OUT_BUFFER resp;
#ifdef TPM_LIBTPMS_CALLBACKS
struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
if (cbs->tpm_io_getlocality) {
TPM_MODIFIER_INDICATOR locty;
locality = cbs->tpm_io_getlocality(&locty, 0);
locality = locty;
}
#endif /* TPM_LIBTPMS_CALLBACKS */
req.BufferSize = command_size;
req.Buffer = command;
/* have the TPM 2 write directly into the response buffer */
if (*respbufsize < TPM_BUFFER_MAX) {
res = TPM_Realloc(respbuffer, TPM_BUFFER_MAX);
if (res)
return res;
*respbufsize = TPM_BUFFER_MAX;
}
resp.BufferSize = *respbufsize;
resp.Buffer = *respbuffer;
/*
* signals for cancellation have to come after we start processing
*/
_rpc__Signal_CancelOff();
_rpc__Send_Command(locality, req, &resp);
*resp_size = resp.BufferSize;
return TPM_SUCCESS;
}
TPM_RESULT TPM2_VolatileAllStore(unsigned char **buffer,
uint32_t *buflen)
{
// FIXME: Is there a function for this?
return TPM_FAIL;
}
TPM_RESULT TPM2_CancelCommand(void)
{
_rpc__Signal_CancelOn();
return TPM_SUCCESS;
}
TPM_RESULT TPM2_GetTPMProperty(enum TPMLIB_TPMProperty prop,
int *result)
{
switch (prop) {
case TPMPROP_TPM_RSA_KEY_LENGTH_MAX:
*result = MAX_RSA_KEY_BITS;
break;
case TPMPROP_TPM_KEY_HANDLES:
*result = MAX_HANDLE_NUM;
break;
/* not supported for TPM 2 */
case TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES:
case TPMPROP_TPM_MIN_AUTH_SESSIONS:
case TPMPROP_TPM_MIN_TRANS_SESSIONS:
case TPMPROP_TPM_MIN_DAA_SESSIONS:
case TPMPROP_TPM_MIN_SESSION_LIST:
case TPMPROP_TPM_MIN_COUNTERS:
case TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN:
case TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN:
case TPMPROP_TPM_SPACE_SAFETY_MARGIN:
case TPMPROP_TPM_MAX_NV_SPACE:
case TPMPROP_TPM_MAX_SAVESTATE_SPACE:
case TPMPROP_TPM_MAX_VOLATILESTATE_SPACE:
default:
return TPM_FAIL;
}
return TPM_SUCCESS;
}
/*
* TPM2_GetInfo:
*
* @flags: logical or of flags that query for information
*
* Return a JSON document with contents queried for by the user's passed flags
*/
char *TPM2_GetInfo(enum TPMLIB_InfoFlags flags)
{
const char *tpmspec =
"\"TPMSpecification\":{"
"\"family\":\"2.0\","
"\"level\":" STRINGIFY(SPEC_LEVEL) ","
"\"revision\":" STRINGIFY(SPEC_VERSION)
"}";
const char *tpmattrs_temp =
"\"TPMAttributes\":{"
"\"manufacturer\":\"id:00001014\","
"\"version\":\"id:%08X\","
"\"model\":\"swtpm\""
"}";
char *fmt = NULL, *buffer;
bool printed = false;
char *tpmattrs = NULL;
if (!(buffer = strdup("{%s%s%s}")))
return NULL;
if ((flags & TPMLIB_INFO_TPMSPECIFICATION)) {
fmt = buffer;
buffer = NULL;
if (asprintf(&buffer, fmt, "", tpmspec, "%s%s%s") < 0)
goto error;
free(fmt);
printed = true;
}
if ((flags & TPMLIB_INFO_TPMATTRIBUTES)) {
fmt = buffer;
buffer = NULL;
if (asprintf(&tpmattrs, tpmattrs_temp, FIRMWARE_V1) < 0)
goto error;
if (asprintf(&buffer, fmt, printed ? "," : "",
tpmattrs, "%s%s%s") < 0)
goto error;
free(fmt);
printed = true;
}
/* nothing else to add */
fmt = buffer;
buffer = NULL;
if (asprintf(&buffer, fmt, "", "", "") < 0)
goto error;
free(fmt);
free(tpmattrs);
return buffer;
error:
free(fmt);
free(buffer);
free(tpmattrs);
return NULL;
}
uint32_t TPM2_SetBufferSize(uint32_t wanted_size,
uint32_t *min_size,
uint32_t *max_size)
{
/* FIXME: this needs to become adjustable */
if (min_size)
*min_size = MAX_COMMAND_SIZE;
if (max_size)
*max_size = MAX_COMMAND_SIZE;
return MAX_COMMAND_SIZE;
}
/*
* Validate the state blobs to check whether they can be
* successfully used by a TPM_INIT.
*/
TPM_RESULT TPM2_ValidateState(enum TPMLIB_StateType st,
unsigned int flags)
{
return TPM_SUCCESS;
}
const struct tpm_interface TPM2Interface = {
.MainInit = TPM2_MainInit,
.Terminate = TPM2_Terminate,
.Process = TPM2_Process,
.VolatileAllStore = TPM2_VolatileAllStore,
.CancelCommand = TPM2_CancelCommand,
.GetTPMProperty = TPM2_GetTPMProperty,
.GetInfo = TPM2_GetInfo,
.TpmEstablishedGet = TPM2_IO_TpmEstablished_Get,
.TpmEstablishedReset = TPM2_IO_TpmEstablished_Reset,
.HashStart = TPM2_IO_Hash_Start,
.HashData = TPM2_IO_Hash_Data,
.HashEnd = TPM2_IO_Hash_End,
.SetBufferSize = TPM2_SetBufferSize,
.ValidateState = TPM2_ValidateState,
};

87
src/tpm_tpm2_tis.c Normal file
View File

@ -0,0 +1,87 @@
/********************************************************************************/
/* */
/* TPM TIS I/O */
/* Written by Stefan Berger */
/* IBM Thomas J. Watson Research Center */
/* */
/* (c) Copyright IBM Corporation 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>
#include <stdint.h>
/* tpm2/TPM_Types.h gives type definition clashes with TPM 1.2 headers */
typedef uint32_t UINT32;
#include "tpm_library_intern.h"
#include "tpm_error.h"
#include "tpm2/TpmBuildSwitches.h"
#include "tpm2/_TPM_Hash_Start_fp.h"
#include "tpm2/_TPM_Hash_Data_fp.h"
#include "tpm2/_TPM_Hash_End_fp.h"
TPM_RESULT TPM2_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished)
{
// FIXME: Missing
*tpmEstablished = FALSE;
return TPM_SUCCESS;
}
TPM_RESULT TPM2_IO_TpmEstablished_Reset(void)
{
// FIXME: Missing
return TPM_SUCCESS;
}
TPM_RESULT TPM2_IO_Hash_Start(void)
{
_TPM_Hash_Start();
return TPM_SUCCESS;
}
TPM_RESULT TPM2_IO_Hash_Data(const unsigned char *data,
uint32_t data_length)
{
_TPM_Hash_Data(data_length, (unsigned char *)data);
return TPM_SUCCESS;
}
TPM_RESULT TPM2_IO_Hash_End(void)
{
_TPM_Hash_End();
return TPM_SUCCESS;
}