Add APIs for getting and setting all state blobs

This patch adds APIs for getting and setting all types of state
blobs. We cache these blobs and allow them to be picked up when
the TPM starts. It will get any of these state blobs, if they
were set, before we go out and try to read the state blob from
a file.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
This commit is contained in:
Stefan Berger 2018-03-10 18:45:36 -05:00
parent 3238742947
commit c76f52efd3
11 changed files with 519 additions and 11 deletions

View File

@ -151,6 +151,10 @@ enum TPMLIB_StateType {
TPM_RESULT TPMLIB_ValidateState(enum TPMLIB_StateType st,
unsigned int flags);
TPM_RESULT TPMLIB_SetState(enum TPMLIB_StateType st,
const unsigned char *buffer, uint32_t buflen);
TPM_RESULT TPMLIB_GetState(enum TPMLIB_StateType st,
const unsigned char **buffer, uint32_t *buflen);
#ifdef __cplusplus
}

View File

@ -151,6 +151,10 @@ enum TPMLIB_StateType {
TPM_RESULT TPMLIB_ValidateState(enum TPMLIB_StateType st,
unsigned int flags);
TPM_RESULT TPMLIB_SetState(enum TPMLIB_StateType st,
const unsigned char *buffer, uint32_t buflen);
TPM_RESULT TPMLIB_GetState(enum TPMLIB_StateType st,
const unsigned char **buffer, uint32_t *buflen);
#ifdef __cplusplus
}

View File

@ -17,6 +17,7 @@ man3_PODS = \
TPMLIB_RegisterCallbacks.pod \
TPMLIB_SetBufferSize.pod \
TPMLIB_SetDebugFD.pod \
TPMLIB_SetState.pod \
TPMLIB_ValidateState.pod \
TPMLIB_VolatileAll_Store.pod \
TPM_Malloc.pod
@ -25,6 +26,7 @@ man3_MANS = \
TPM_Free.3 \
TPM_IO_Hash_Data.3 \
TPM_IO_Hash_End.3 \
TPMLIB_GetState.3 \
TPMLIB_SetDebugPrefix.3 \
TPMLIB_SetDebugLevel.3 \
TPMLIB_Terminate.3 \
@ -41,6 +43,7 @@ man3_MANS += \
TPMLIB_Process.3 \
TPMLIB_SetDebugFD.3 \
TPMLIB_SetBufferSize.3 \
TPMLIB_SetState.3 \
TPMLIB_RegisterCallbacks.3 \
TPMLIB_ValidateState.3 \
TPMLIB_VolatileAll_Store.3 \

View File

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

View File

@ -1,4 +1,4 @@
.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.31)
.\"
.\" Standard preamble:
.\" ========================================================================
@ -38,6 +38,8 @@
. ds PI \(*p
. ds L" ``
. ds R" ''
. ds C`
. ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
@ -48,17 +50,24 @@
.\" 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.
.ie \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
. nr % 0
. rr F
.\}
.el \{\
. 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.
@ -123,8 +132,8 @@
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "TPMLIB_GETTPMPROPERTY 1"
.TH TPMLIB_GETTPMPROPERTY 1 "2011-03-24" "libtpms-0.5.1" "libtpms documentation"
.IX Title "TPMLIB_GetTPMProperty 3"
.TH TPMLIB_GetTPMProperty 3 "2018-03-16" "libtpms" ""
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l

181
man/man3/TPMLIB_SetState.3 Normal file
View File

@ -0,0 +1,181 @@
.\" 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_SetState 3"
.TH TPMLIB_SetState 3 "2018-05-10" "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_SetState \- Set the TPM's volatile, permanent, or save state
.PP
TPMLIB_GetState \- Get the TPM's volatile, permanent, or save state
.SH "LIBRARY"
.IX Header "LIBRARY"
\&\s-1TPM\s0 library (libtpms, \-ltpms)
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
\&\fB#include <libtpms/tpm_library.h\fR>
.PP
\&\fB\s-1TPM_RESULT\s0 TPMLIB_SetState(enum TPMLIB_StateType st,
const unsigned char *buffer, uint32_t buflen);\fR
.PP
\&\fB\s-1TPM_RESULT\s0 TPMLIB_GetState(enum TPMLIB_StateType st,
const unsigned char **buffer, uint32_t *buflen);\fR
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
The \fB\f(BITPMLIB_SetState()\fB\fR function allows to set either one of the state blobs of
the \s-1TPM.\s0 The passed state blob is tested for whether it can be accepted and a \s-1TPM\s0
error code is returned in case it cannot be accepted. In case of acceptance, the
state blob will be passed to the \s-1TPM\s0 upon \fITPM_MainInit()\fR. Setting a state blob
hides a file that may contain the same type of blob and would be read otherwise.
It is required to call this function with a \s-1NULL\s0 pointer for the buffer parameter
to hide a state blob in a file.
.PP
It is only possible to set the state blobs after \fITPMLIB_ChooseTPMVersion()\fR has been
called. All state blobs are cleared when \fITPMLIB_Terminate()\fR is called.
.PP
The \fB\f(BITPMLIB_GetState()\fB\fR function allows to get the current state of the \s-1TPM.\s0
For as long as the \s-1TPM\s0 has not been started, this function either returns the state
blob previously set with \fB\f(BITPMLIB_GetState()\fB\fR or the state read from a file.
Once the \s-1TPM\s0 has been start the state of the running \s-1TPM\s0 is returned.
.PP
The \fB\s-1TPMLIB_STATE_SAVE_STATE\s0\fR (save state) type of \s-1TPM\s0 state can be set with this
function. The same state blob will be returned until TPM_Startup(\s-1ST_STATE\s0) has been
called, after which an empty blob will be returned. This blob can also only be
read after \fITPM_SaveState()\fR has been sent to the \s-1TPM.\s0
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fBTPMLIB_ChooseTPMVersion\fR(3), \fBTPMLIB_MainInit\fR(3), \fBTPMLIB_Terminate\fR(3)

View File

@ -0,0 +1,48 @@
=head1 NAME
TPMLIB_SetState - Set the TPM's volatile, permanent, or save state
TPMLIB_GetState - Get the TPM's volatile, permanent, or save state
=head1 LIBRARY
TPM library (libtpms, -ltpms)
=head1 SYNOPSIS
B<#include <libtpms/tpm_library.h>>
B<TPM_RESULT TPMLIB_SetState(enum TPMLIB_StateType st,
const unsigned char *buffer, uint32_t buflen);>
B<TPM_RESULT TPMLIB_GetState(enum TPMLIB_StateType st,
const unsigned char **buffer, uint32_t *buflen);>
=head1 DESCRIPTION
The B<TPMLIB_SetState()> function allows to set either one of the state blobs of
the TPM. The passed state blob is tested for whether it can be accepted and a TPM
error code is returned in case it cannot be accepted. In case of acceptance, the
state blob will be passed to the TPM upon TPM_MainInit(). Setting a state blob
hides a file that may contain the same type of blob and would be read otherwise.
It is required to call this function with a NULL pointer for the buffer parameter
to hide a state blob in a file.
It is only possible to set the state blobs after TPMLIB_ChooseTPMVersion() has been
called. All state blobs are cleared when TPMLIB_Terminate() is called.
The B<TPMLIB_GetState()> function allows to get the current state of the TPM.
For as long as the TPM has not been started, this function either returns the state
blob previously set with B<TPMLIB_GetState()> or the state read from a file.
Once the TPM has been start the state of the running TPM is returned.
The B<TPMLIB_STATE_SAVE_STATE> (save state) type of TPM state can be set with this
function. The same state blob will be returned until TPM_Startup(ST_STATE) has been
called, after which an empty blob will be returned. This blob can also only be
read after TPM_SaveState() has been sent to the TPM.
=head1 SEE ALSO
B<TPMLIB_ChooseTPMVersion>(3), B<TPMLIB_MainInit>(3), B<TPMLIB_Terminate>(3)
=cut

View File

@ -24,10 +24,12 @@ LIBTPMS_0.5.1 {
LIBTPMS_0.6.0 {
global:
TPMLIB_GetInfo;
TPMLIB_GetState;
TPMLIB_SetBufferSize;
TPMLIB_SetDebugFD;
TPMLIB_SetDebugLevel;
TPMLIB_SetDebugPrefix;
TPMLIB_SetState;
TPMLIB_ValidateState;
local:
*;

View File

@ -46,6 +46,7 @@
#include <stdarg.h>
#include <ctype.h>
#include <unistd.h>
#include <stdbool.h>
#ifdef USE_FREEBL_CRYPTO_LIBRARY
# include <plbase64.h>
@ -61,6 +62,7 @@
#include "tpm_library.h"
#include "tpm_library_intern.h"
#include "tpm_memory.h"
#include "tpm_nvfilename.h"
static const struct tags_and_indices {
const char *starttag;
@ -81,6 +83,8 @@ static int debug_fd = -1;
static unsigned debug_level = 0;
static char *debug_prefix = NULL;
static struct sized_buffer cached_blobs[TPMLIB_STATE_SAVE_STATE + 1];
uint32_t TPMLIB_GetVersion(void)
{
return TPM_LIBRARY_VERSION;
@ -466,3 +470,86 @@ void TPMLIB_LogPrintfA(unsigned int indent, const char *format, ...)
vdprintf(fd, format, args);
va_end(args);
}
void ClearCachedState(enum TPMLIB_StateType st)
{
free(cached_blobs[st].buffer);
cached_blobs[st].buffer = NULL;
cached_blobs[st].buflen = 0;
}
/*
* Set buffer for cached state; we allow setting an empty cached state
* by the caller passing a NULL pointer for the buffer.
*/
void SetCachedState(enum TPMLIB_StateType st,
unsigned char *buffer, uint32_t buflen)
{
free(cached_blobs[st].buffer);
cached_blobs[st].buffer = buffer;
cached_blobs[st].buflen = buffer ? buflen : BUFLEN_EMPTY_BUFFER;
}
void GetCachedState(enum TPMLIB_StateType st,
unsigned char **buffer, uint32_t *buflen,
bool *is_empty_buffer)
{
/* caller owns blob now */
*buffer = cached_blobs[st].buffer;
*buflen = cached_blobs[st].buflen;
*is_empty_buffer = (*buflen == BUFLEN_EMPTY_BUFFER);
cached_blobs[st].buffer = NULL;
cached_blobs[st].buflen = 0;
}
bool HasCachedState(enum TPMLIB_StateType st)
{
return (cached_blobs[st].buffer != NULL || cached_blobs[st].buflen != 0);
}
TPM_RESULT CopyCachedState(enum TPMLIB_StateType st,
unsigned char **buffer, uint32_t *buflen,
bool *is_empty_buffer)
{
TPM_RESULT ret = TPM_SUCCESS;
/* buflen may indicate an empty buffer */
*buflen = cached_blobs[st].buflen;
*is_empty_buffer = (*buflen == BUFLEN_EMPTY_BUFFER);
if (cached_blobs[st].buffer) {
ret = TPM_Malloc(buffer, *buflen);
if (ret == TPM_SUCCESS)
memcpy(*buffer, cached_blobs[st].buffer, *buflen);
} else {
*buffer = NULL;
}
return ret;
}
const char *TPMLIB_StateTypeToName(enum TPMLIB_StateType st)
{
switch (st) {
case TPMLIB_STATE_PERMANENT:
return TPM_PERMANENT_ALL_NAME;
case TPMLIB_STATE_VOLATILE:
return TPM_VOLATILESTATE_NAME;
case TPMLIB_STATE_SAVE_STATE:
return TPM_SAVESTATE_NAME;
}
return NULL;
}
enum TPMLIB_StateType TPMLIB_NameToStateType(const char *name)
{
if (!name)
return 0;
if (!strcmp(name, TPM_PERMANENT_ALL_NAME))
return TPMLIB_STATE_PERMANENT;
if (!strcmp(name, TPM_VOLATILESTATE_NAME))
return TPMLIB_STATE_VOLATILE;
if (!strcmp(name, TPM_SAVESTATE_NAME))
return TPMLIB_STATE_SAVE_STATE;
return 0;
}

View File

@ -39,6 +39,7 @@
#ifndef TPM_LIBRARY_INTERN_H
#define TPM_LIBRARY_INTERN_H
#include <stdbool.h>
#include "tpm_library.h"
#define ROUNDUP(VAL, SIZE) \
@ -68,6 +69,10 @@ struct tpm_interface {
TPM_RESULT (*HashEnd)(void);
TPM_RESULT (*ValidateState)(enum TPMLIB_StateType st,
unsigned int flags);
TPM_RESULT (*SetState)(enum TPMLIB_StateType st,
const unsigned char *buffer, uint32_t buflen);
TPM_RESULT (*GetState)(enum TPMLIB_StateType st,
unsigned char **buffer, uint32_t *buflen);
};
extern const struct tpm_interface TPM12Interface;
@ -88,4 +93,24 @@ void TPMLIB_LogPrintfA(unsigned int indent, const char *format, ...);
#define TPMLIB_LogTPM12Error(format, ...) \
TPMLIB_LogPrintfA(~0, "libtpms/tpm12: "format, __VA_ARGS__)
struct sized_buffer {
unsigned char *buffer;
uint32_t buflen;
#define BUFLEN_EMPTY_BUFFER 0xFFFFFFFF
};
void ClearCachedState(enum TPMLIB_StateType st);
void SetCachedState(enum TPMLIB_StateType st,
unsigned char *buffer, uint32_t buflen);
void GetCachedState(enum TPMLIB_StateType st,
unsigned char **buffer, uint32_t *buflen,
bool *is_empty_buffer);
bool HasCachedState(enum TPMLIB_StateType st);
TPM_RESULT CopyCachedState(enum TPMLIB_StateType st,
unsigned char **buffer, uint32_t *buflen,
bool *is_empty_buffer);
const char *TPMLIB_StateTypeToName(enum TPMLIB_StateType st);
enum TPMLIB_StateType TPMLIB_NameToStateType(const char *name);
#endif /* TPM_LIBRARY_INTERN_H */

View File

@ -53,6 +53,8 @@
#include "tpm12/tpm_startup.h"
#include "tpm12/tpm_global.h"
#include "tpm12/tpm_permanent.h"
#include "tpm12/tpm_nvfile.h"
#include "tpm_memory.h"
TPM_RESULT TPM12_MainInit(void)
{
@ -305,6 +307,146 @@ TPM_RESULT TPM12_ValidateState(enum TPMLIB_StateType st,
return ret;
}
static TPM_RESULT _TPM_PermanentAll_Store(TPM_STORE_BUFFER *sbuffer,
tpm_state_t *tpm_state)
{
const unsigned char *buffer = NULL;
uint32_t buflen;
return TPM_PermanentAll_Store(sbuffer, &buffer, &buflen, tpm_state);
}
/*
* Get the state blob of the given type. If we TPM is not running, we
* get the cached state blobs, if available, otherwise we try to read
* it from files. In case the TPM is running, we get it from the running
* TPM.
*/
TPM_RESULT TPM12_GetState(enum TPMLIB_StateType st,
unsigned char **buffer, uint32_t *buflen)
{
TPM_RESULT ret = TPM_FAIL;
TPM_STORE_BUFFER tsb;
uint32_t total;
/* TPM not running ? */
if (tpm_instances[0] == NULL) {
struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
bool is_empty_buffer;
/* try cached blob before file */
ret = CopyCachedState(st, buffer, buflen, &is_empty_buffer);
if (ret != TPM_SUCCESS || buffer != NULL || is_empty_buffer)
return ret;
if (cbs->tpm_nvram_init) {
ret = cbs->tpm_nvram_init();
if (ret != TPM_SUCCESS)
return ret;
ret = TPM_NVRAM_LoadData(buffer, buflen, 0,
TPMLIB_StateTypeToName(st));
} else {
ret = TPM_FAIL;
}
return ret;
}
TPM_Sbuffer_Init(&tsb);
switch (st) {
case TPMLIB_STATE_PERMANENT:
ret = _TPM_PermanentAll_Store(&tsb, tpm_instances[0]);
break;
case TPMLIB_STATE_VOLATILE:
ret = TPM_VolatileAll_Store(&tsb, tpm_instances[0]);
break;
case TPMLIB_STATE_SAVE_STATE:
ret = TPM_SaveState_Store(&tsb, tpm_instances[0]);
break;
}
if (ret == TPM_SUCCESS) {
/* caller now owns the buffer and needs to free it */
TPM_Sbuffer_GetAll(&tsb, buffer, buflen, &total);
} else {
TPM_Sbuffer_Delete(&tsb);
*buflen = 0;
*buffer = NULL;
}
return ret;
}
/*
* Set the state the TPM 1.2 will use upon next TPM_MainInit(). The TPM 1.2
* must not have been started, yet, or it must have been terminated for this
* function to set the state.
*
* @st: The TPMLIB_StateType describing the type of blob in the buffer
* @buffer: pointer to the buffer containing the state blob; NULL pointer clears
* previous state
* @buflen: length of the buffer
*/
TPM_RESULT TPM12_SetState(enum TPMLIB_StateType st,
const unsigned char *buffer, uint32_t buflen)
{
TPM_RESULT ret = TPM_SUCCESS;
unsigned char *stream = NULL, *orig_stream = NULL;
uint32_t stream_size = buflen;
tpm_state_t *tpm_state = NULL;
if (buffer == NULL) {
SetCachedState(st, NULL, 0);
return TPM_SUCCESS;
}
if (tpm_instances[0])
return TPM_INVALID_POSTINIT;
if (ret == TPM_SUCCESS) {
ret = TPM_Malloc((unsigned char **)&stream, buflen);
}
if (ret == TPM_SUCCESS) {
orig_stream = stream;
memcpy(stream, buffer, buflen);
ret = TPM_Malloc((unsigned char **)&tpm_state, sizeof(tpm_state_t));
}
if (ret == TPM_SUCCESS) {
ret = TPM_Global_Init(tpm_state);
}
/* test whether we can accept the blob */
if (ret == TPM_SUCCESS) {
switch (st) {
case TPMLIB_STATE_PERMANENT:
ret = TPM_PermanentAll_Load(tpm_state, &stream, &stream_size);
break;
case TPMLIB_STATE_VOLATILE:
ret = TPM_VolatileAll_Load(tpm_state, &stream, &stream_size);
break;
case TPMLIB_STATE_SAVE_STATE:
ret = TPM_SaveState_Load(tpm_state, &stream, &stream_size);
break;
}
}
/* cache the blob for the TPM_MainInit() to pick it up */
if (ret == TPM_SUCCESS) {
SetCachedState(st, orig_stream, buflen);
} else {
free(orig_stream);
}
TPM_Global_Delete(tpm_state);
free(tpm_state);
return ret;
}
const struct tpm_interface TPM12Interface = {
.MainInit = TPM12_MainInit,
.Terminate = TPM12_Terminate,
@ -318,4 +460,6 @@ const struct tpm_interface TPM12Interface = {
.HashEnd = TPM12_IO_Hash_End,
.SetBufferSize = TPM12_SetBufferSize,
.ValidateState = TPM12_ValidateState,
.SetState = TPM12_SetState,
.GetState = TPM12_GetState,
};