Implement TPMLIB_ValidateState() to test state blobs early

Implement TPMLIB_ValidateState(), which is supposed to be used
for checking usability of state blobs before TPMLIB_MainInit()
is called or TPM_Startup has been sent to the TPM.

This function is useful to be called once TPM state blobs
have been migrated to a destination and we need to check
whether libtpms can use these state blobs and if not
we have a chance to fall back to the migration source host.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
This commit is contained in:
Stefan Berger 2018-02-17 13:10:12 -05:00
parent d77f29d64e
commit e11dbf255b
9 changed files with 284 additions and 0 deletions

View File

@ -136,6 +136,15 @@ uint32_t TPMLIB_SetBufferSize(uint32_t wanted_size,
uint32_t *min_size,
uint32_t *max_size);
enum TPMLIB_StateType {
TPMLIB_STATE_PERMANENT = (1 << 0),
TPMLIB_STATE_VOLATILE = (1 << 1),
TPMLIB_STATE_SAVE_STATE = (1 << 2),
};
TPM_RESULT TPMLIB_ValidateState(enum TPMLIB_StateType st,
unsigned int flags);
#ifdef __cplusplus
}
#endif

View File

@ -136,6 +136,15 @@ uint32_t TPMLIB_SetBufferSize(uint32_t wanted_size,
uint32_t *min_size,
uint32_t *max_size);
enum TPMLIB_StateType {
TPMLIB_STATE_PERMANENT = (1 << 0),
TPMLIB_STATE_VOLATILE = (1 << 1),
TPMLIB_STATE_SAVE_STATE = (1 << 2),
};
TPM_RESULT TPMLIB_ValidateState(enum TPMLIB_StateType st,
unsigned int flags);
#ifdef __cplusplus
}
#endif

View File

@ -16,6 +16,7 @@ man3_PODS = \
TPMLIB_RegisterCallbacks.pod \
TPMLIB_SetBufferSize.pod \
TPMLIB_SetDebugFD.pod \
TPMLIB_ValidateState.pod \
TPMLIB_VolatileAll_Store.pod \
TPM_Malloc.pod
@ -39,6 +40,7 @@ man3_MANS += \
TPMLIB_SetDebugFD.3 \
TPMLIB_SetBufferSize.3 \
TPMLIB_RegisterCallbacks.3 \
TPMLIB_ValidateState.3 \
TPMLIB_VolatileAll_Store.3 \
TPM_Malloc.3

View File

@ -0,0 +1,173 @@
.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.31)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
. ds C`
. ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{
. if \nF \{
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. if !\nF==2 \{
. nr % 0
. nr F 2
. \}
. \}
.\}
.rr rF
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "TPMLIB_ValidateState 3"
.TH TPMLIB_ValidateState 3 "2018-02-17" "libtpms" ""
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
TPMLIB_ValidateState \- Validate the state blobs of the TPM
.SH "LIBRARY"
.IX Header "LIBRARY"
\&\s-1TPM\s0 library (libtpms, \-ltpms)
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
\&\fB#include <libtpms/tpm_library.h\fR>
.PP
\&\fBuint32_t TPMLIB_ValidateState(TPMLIB_StateType st,
unsigned int flags);
\&\fR
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
The \fB\f(BITPMLIB_ValidateState()\fB\fR function allows to validate the
state blobs that the \s-1TPM\s0 would read upon \fB\f(BITPMLIB_MainInit()\fB\fR or
once the TPM_Startup command has been sent to it.
.PP
This function is useful for \s-1TPM\s0 state migration between possibly
different version of libtpms. Here the target libtpms needs to be
able to determine whether it can support the version of blobs that were
migrated and if this is not the case, the caller can refuse the
migration.
.PP
The \fBtpmlib_state\fR parameter can be a logical 'or' of one or
multiple of of the following: \fB\s-1TPMLIB_STATE_PERMANENT\s0\fR,
\&\fB\s-1TPMLIB_STATE_VOLATILE\s0\fR, or \fB\s-1TPMLIB_STATE_SAVE_STATE\s0\fR.
The \fBflags\fR parameter is curretnly not used and should be set to 0.
.PP
This function should be called before \fB\f(BITPMLIB_MainInit()\fB\fR is invoked.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fBTPMLIB_MainInit\fR(3), \fBTPMLIB_Terminate\fR(3)

View File

@ -0,0 +1,40 @@
=head1 NAME
TPMLIB_ValidateState - Validate the state blobs of the TPM
=head1 LIBRARY
TPM library (libtpms, -ltpms)
=head1 SYNOPSIS
B<#include <libtpms/tpm_library.h>>
B<uint32_t TPMLIB_ValidateState(TPMLIB_StateType st,
unsigned int flags);
>
=head1 DESCRIPTION
The B<TPMLIB_ValidateState()> function allows to validate the
state blobs that the TPM would read upon B<TPMLIB_MainInit()> or
once the TPM_Startup command has been sent to it.
This function is useful for TPM state migration between possibly
different version of libtpms. Here the target libtpms needs to be
able to determine whether it can support the version of blobs that were
migrated and if this is not the case, the caller can refuse the
migration.
The B<tpmlib_state> parameter can be a logical 'or' of one or
multiple of of the following: B<TPMLIB_STATE_PERMANENT>,
B<TPMLIB_STATE_VOLATILE>, or B<TPMLIB_STATE_SAVE_STATE>.
The B<flags> parameter is curretnly not used and should be set to 0.
This function should be called before B<TPMLIB_MainInit()> is invoked.
=head1 SEE ALSO
B<TPMLIB_MainInit>(3), B<TPMLIB_Terminate>(3)
=cut

View File

@ -27,6 +27,7 @@ LIBTPMS_0.6.0 {
TPMLIB_SetDebugFD;
TPMLIB_SetDebugLevel;
TPMLIB_SetDebugPrefix;
TPMLIB_ValidateState;
local:
*;
} LIBTPMS_0.5.1;

View File

@ -172,6 +172,12 @@ uint32_t TPMLIB_SetBufferSize(uint32_t wanted_size,
return tpm_iface[0]->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);
}
static struct libtpms_callbacks libtpms_cbs;
struct libtpms_callbacks *TPMLIB_GetCallbacks(void)

View File

@ -65,6 +65,8 @@ struct tpm_interface {
TPM_RESULT (*HashData)(const unsigned char *data,
uint32_t data_length);
TPM_RESULT (*HashEnd)(void);
TPM_RESULT (*ValidateState)(enum TPMLIB_StateType st,
unsigned int flags);
};
extern const struct tpm_interface TPM12Interface;

View File

@ -48,6 +48,8 @@
#include "tpm_library_intern.h"
#include "tpm12/tpm_process.h"
#include "tpm12/tpm_startup.h"
#include "tpm12/tpm_global.h"
#include "tpm12/tpm_permanent.h"
TPM_RESULT TPM12_MainInit(void)
{
@ -194,6 +196,45 @@ uint32_t TPM12_GetBufferSize(void)
return TPM12_SetBufferSize(0, NULL, NULL);
}
TPM_RESULT TPM12_ValidateState(enum TPMLIB_StateType st,
unsigned int flags)
{
TPM_RESULT ret = TPM_SUCCESS;
tpm_state_t tpm_state;
#ifdef TPM_LIBTPMS_CALLBACKS
struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
if (cbs->tpm_nvram_init) {
ret = cbs->tpm_nvram_init();
if (ret != TPM_SUCCESS)
return ret;
}
#endif
ret = TPM_Global_Init(&tpm_state);
tpm_state.tpm_number = 0;
if ((ret == TPM_SUCCESS) &
(st & TPMLIB_STATE_PERMANENT)) {
ret = TPM_PermanentAll_NVLoad(&tpm_state);
}
if ((ret == TPM_SUCCESS) &
(st & TPMLIB_STATE_VOLATILE)) {
ret = TPM_SaveState_NVLoad(&tpm_state);
}
if ((ret == TPM_SUCCESS) &
(st & TPMLIB_STATE_SAVE_STATE)) {
ret = TPM_VolatileAll_NVLoad(&tpm_state);
}
TPM_Global_Delete(&tpm_state);
return ret;
}
const struct tpm_interface TPM12Interface = {
.MainInit = TPM12_MainInit,
.Terminate = TPM12_Terminate,
@ -205,4 +246,5 @@ const struct tpm_interface TPM12Interface = {
.HashData = TPM12_IO_Hash_Data,
.HashEnd = TPM12_IO_Hash_End,
.SetBufferSize = TPM12_SetBufferSize,
.ValidateState = TPM12_ValidateState,
};