mirror of
https://github.com/stefanberger/libtpms
synced 2025-08-26 04:33:40 +00:00

To avoid static analyzer warnings due to non-literal format strings being used, wrap asprintf in TPMLIB_asprintf and call vasprintf from there. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
703 lines
18 KiB
C
703 lines
18 KiB
C
/********************************************************************************/
|
|
/* */
|
|
/* LibTPM interface functions */
|
|
/* Written by Stefan Berger */
|
|
/* IBM Thomas J. Watson Research Center */
|
|
/* $Id: tpm_library.c 4615 2011-08-30 15:35:24Z stefanb $ */
|
|
/* */
|
|
/* (c) Copyright IBM Corporation 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. */
|
|
/********************************************************************************/
|
|
|
|
#include <config.h>
|
|
|
|
#define _GNU_SOURCE
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#if defined __FreeBSD__
|
|
# define _WITH_DPRINTF
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <ctype.h>
|
|
#include <unistd.h>
|
|
#include <stdbool.h>
|
|
|
|
#ifdef USE_FREEBL_CRYPTO_LIBRARY
|
|
# include <plbase64.h>
|
|
#endif
|
|
|
|
#ifdef USE_OPENSSL_CRYPTO_LIBRARY
|
|
# include <openssl/bio.h>
|
|
# include <openssl/evp.h>
|
|
#endif
|
|
|
|
#include "tpm_debug.h"
|
|
#include "tpm_error.h"
|
|
#include "tpm_library.h"
|
|
#include "tpm_library_intern.h"
|
|
#include "tpm_nvfilename.h"
|
|
#include "tpm_tis.h"
|
|
|
|
static const struct tags_and_indices {
|
|
const char *starttag;
|
|
const char *endtag;
|
|
} tags_and_indices[] = {
|
|
[TPMLIB_BLOB_TYPE_INITSTATE] =
|
|
{
|
|
.starttag = TPMLIB_INITSTATE_START_TAG,
|
|
.endtag = TPMLIB_INITSTATE_END_TAG,
|
|
},
|
|
};
|
|
|
|
static const struct tpm_interface *const tpm_iface[] = {
|
|
#if WITH_TPM1
|
|
&TPM12Interface,
|
|
#else
|
|
&DisabledInterface,
|
|
#endif
|
|
#if WITH_TPM2
|
|
&TPM2Interface,
|
|
#else
|
|
&DisabledInterface,
|
|
#endif
|
|
NULL,
|
|
};
|
|
|
|
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];
|
|
|
|
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)
|
|
{
|
|
/* TPMLIB_Terminate will reset previous choice */
|
|
if (tpmvers_locked)
|
|
return TPM_FAIL;
|
|
|
|
switch (ver) {
|
|
#if WITH_TPM1
|
|
case TPMLIB_TPM_VERSION_1_2:
|
|
if (tpmvers_choice != 0)
|
|
ClearAllCachedState();
|
|
|
|
tpmvers_choice = 0; // entry 0 in tpm_iface
|
|
return TPM_SUCCESS;
|
|
#endif
|
|
#if WITH_TPM2
|
|
case TPMLIB_TPM_VERSION_2:
|
|
if (tpmvers_choice != 1)
|
|
ClearAllCachedState();
|
|
|
|
tpmvers_choice = 1; // entry 1 in tpm_iface
|
|
return TPM_SUCCESS;
|
|
#endif
|
|
default:
|
|
return TPM_FAIL;
|
|
}
|
|
}
|
|
|
|
TPM_RESULT TPMLIB_MainInit(void)
|
|
{
|
|
if (!tpm_iface[tpmvers_choice]) {
|
|
return TPM_FAIL;
|
|
}
|
|
|
|
tpmvers_locked = TRUE;
|
|
|
|
return tpm_iface[tpmvers_choice]->MainInit();
|
|
}
|
|
|
|
void TPMLIB_Terminate(void)
|
|
{
|
|
tpm_iface[tpmvers_choice]->Terminate();
|
|
|
|
tpmvers_locked = FALSE;
|
|
}
|
|
|
|
/*
|
|
* Send a command to the TPM. The command buffer must hold a well formatted
|
|
* TPM command and the command_size indicate the size of the command.
|
|
* The respbuffer parameter may be provided by the user and grow if
|
|
* the respbufsize size indicator is determined to be too small for the
|
|
* response. In that case a new buffer will be allocated and the size of that
|
|
* buffer returned in the respbufsize parameter. resp_size describes the
|
|
* size of the actual response within the respbuffer.
|
|
*/
|
|
TPM_RESULT TPMLIB_Process(unsigned char **respbuffer, uint32_t *resp_size,
|
|
uint32_t *respbufsize,
|
|
unsigned char *command, uint32_t command_size)
|
|
{
|
|
return tpm_iface[tpmvers_choice]->Process(respbuffer,
|
|
resp_size, respbufsize,
|
|
command, command_size);
|
|
}
|
|
|
|
/*
|
|
* Get the volatile state from the TPM. This function will return the
|
|
* buffer and the length of the buffer to the caller in case everything
|
|
* went alright.
|
|
*/
|
|
TPM_RESULT TPMLIB_VolatileAll_Store(unsigned char **buffer,
|
|
uint32_t *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();
|
|
}
|
|
|
|
/*
|
|
* Get a property of the TPM. The functions currently only
|
|
* return compile-time #defines but this may change in future
|
|
* versions where we may return parameters with which the TPM
|
|
* was created (rather than compiled).
|
|
*/
|
|
TPM_RESULT TPMLIB_GetTPMProperty(enum TPMLIB_TPMProperty prop,
|
|
int *result)
|
|
{
|
|
switch (prop) {
|
|
case TPMPROP_TPM_BUFFER_MAX:
|
|
*result = TPM_BUFFER_MAX;
|
|
break;
|
|
|
|
default:
|
|
return tpm_iface[tpmvers_choice]->GetTPMProperty(prop, result);
|
|
}
|
|
|
|
return TPM_SUCCESS;
|
|
}
|
|
|
|
char *TPMLIB_GetInfo(enum TPMLIB_InfoFlags flags)
|
|
{
|
|
return tpm_iface[tpmvers_choice]->GetInfo(flags);
|
|
}
|
|
|
|
TPM_RESULT TPMLIB_SetState(enum TPMLIB_StateType st,
|
|
const unsigned char *buffer, uint32_t buflen)
|
|
{
|
|
return tpm_iface[tpmvers_choice]->SetState(st, buffer, buflen);
|
|
}
|
|
|
|
TPM_RESULT TPMLIB_GetState(enum TPMLIB_StateType st,
|
|
unsigned char **buffer, uint32_t *buflen)
|
|
{
|
|
return tpm_iface[tpmvers_choice]->GetState(st, buffer, buflen);
|
|
}
|
|
|
|
TPM_RESULT TPM_IO_Hash_Start(void)
|
|
{
|
|
return tpm_iface[tpmvers_choice]->HashStart();
|
|
}
|
|
|
|
TPM_RESULT TPM_IO_Hash_Data(const unsigned char *data, uint32_t data_length)
|
|
{
|
|
return tpm_iface[tpmvers_choice]->HashData(data, data_length);
|
|
}
|
|
|
|
TPM_RESULT TPM_IO_Hash_End(void)
|
|
{
|
|
return tpm_iface[tpmvers_choice]->HashEnd();
|
|
}
|
|
|
|
TPM_RESULT TPM_IO_TpmEstablished_Get(TPM_BOOL *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[tpmvers_choice]->SetBufferSize(wanted_size,
|
|
min_size,
|
|
max_size);
|
|
}
|
|
|
|
TPM_RESULT TPMLIB_ValidateState(enum TPMLIB_StateType st,
|
|
unsigned int flags)
|
|
{
|
|
return tpm_iface[tpmvers_choice]->ValidateState(st, flags);
|
|
}
|
|
|
|
TPM_RESULT TPMLIB_SetProfile(const char *profile)
|
|
{
|
|
return tpm_iface[tpmvers_choice]->SetProfile(profile);
|
|
}
|
|
|
|
TPM_BOOL TPMLIB_WasManufactured(void)
|
|
{
|
|
return tpm_iface[tpmvers_choice]->WasManufactured();
|
|
}
|
|
|
|
static struct libtpms_callbacks libtpms_cbs;
|
|
|
|
struct libtpms_callbacks *TPMLIB_GetCallbacks(void)
|
|
{
|
|
return &libtpms_cbs;
|
|
}
|
|
|
|
TPM_RESULT TPMLIB_RegisterCallbacks(struct libtpms_callbacks *callbacks)
|
|
{
|
|
int max_size = sizeof(struct libtpms_callbacks);
|
|
|
|
/* restrict the size of the structure to what we know currently
|
|
future versions may know more callbacks */
|
|
if (callbacks->sizeOfStruct < max_size)
|
|
max_size = callbacks->sizeOfStruct;
|
|
|
|
/* clear the internal callback structure and copy the user provided
|
|
callbacks into it */
|
|
memset(&libtpms_cbs, 0x0, sizeof(libtpms_cbs));
|
|
memcpy(&libtpms_cbs, callbacks, max_size);
|
|
|
|
return TPM_SUCCESS;
|
|
}
|
|
|
|
static int is_base64ltr(char c)
|
|
{
|
|
return ((c >= 'A' && c <= 'Z') ||
|
|
(c >= 'a' && c <= 'z') ||
|
|
(c >= '0' && c <= '9') ||
|
|
c == '+' ||
|
|
c == '/' ||
|
|
c == '=');
|
|
}
|
|
|
|
#ifdef USE_OPENSSL_CRYPTO_LIBRARY
|
|
static unsigned char *TPMLIB_OpenSSL_Base64Decode(char *input,
|
|
unsigned int outputlen)
|
|
{
|
|
BIO *b64, *bmem;
|
|
unsigned char *res = NULL;
|
|
int n;
|
|
|
|
b64 = BIO_new(BIO_f_base64());
|
|
if (!b64) {
|
|
return NULL;
|
|
}
|
|
|
|
bmem = BIO_new_mem_buf(input, strlen(input));
|
|
if (!bmem) {
|
|
BIO_free(b64);
|
|
goto cleanup;
|
|
}
|
|
bmem = BIO_push(b64, bmem);
|
|
BIO_set_flags(bmem, BIO_FLAGS_BASE64_NO_NL);
|
|
|
|
res = malloc(outputlen);
|
|
if (!res) {
|
|
TPMLIB_LogError("Could not allocate %u bytes.\n", outputlen);
|
|
goto cleanup;
|
|
}
|
|
|
|
n = BIO_read(bmem, res, outputlen);
|
|
if (n <= 0) {
|
|
free(res);
|
|
res = NULL;
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
BIO_free_all(bmem);
|
|
|
|
return res;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Base64 decode the string starting at 'start' and the last
|
|
* valid character may be a 'end'. The length of the decoded string
|
|
* is returned in *length.
|
|
*/
|
|
static unsigned char *TPMLIB_Base64Decode(const char *start, const char *end,
|
|
size_t *length)
|
|
{
|
|
unsigned char *ret = NULL;
|
|
char *input = NULL, *d;
|
|
const char *s;
|
|
char c;
|
|
unsigned int numbase64chars = 0;
|
|
|
|
if (end < start)
|
|
return NULL;
|
|
|
|
while (end > start && !is_base64ltr(*end))
|
|
end--;
|
|
|
|
end++;
|
|
|
|
input = malloc(end - start + 1);
|
|
if (!input) {
|
|
TPMLIB_LogError("Could not allocate %u bytes.\n",
|
|
(unsigned int)(end - start + 1));
|
|
return NULL;
|
|
}
|
|
|
|
/* copy from source string skipping '\n' and '\r' and using
|
|
'=' to calculate the exact length */
|
|
d = input;
|
|
s = start;
|
|
|
|
while (s < end) {
|
|
c = *s;
|
|
if (is_base64ltr(c)) {
|
|
*d = c;
|
|
d++;
|
|
if (c != '=') {
|
|
numbase64chars++;
|
|
}
|
|
} else if (c == 0) {
|
|
break;
|
|
}
|
|
s++;
|
|
}
|
|
*d = 0;
|
|
|
|
*length = (numbase64chars / 4) * 3;
|
|
switch (numbase64chars % 4) {
|
|
case 2:
|
|
case 3:
|
|
*length += (numbase64chars % 4) - 1;
|
|
break;
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
fprintf(stderr,"malformed base64\n");
|
|
goto err_exit;
|
|
break;
|
|
}
|
|
|
|
#ifdef USE_FREEBL_CRYPTO_LIBRARY
|
|
ret = (unsigned char *)PL_Base64Decode(input, 0, NULL);
|
|
#endif
|
|
|
|
#ifdef USE_OPENSSL_CRYPTO_LIBRARY
|
|
ret = TPMLIB_OpenSSL_Base64Decode(input, *length);
|
|
#endif
|
|
|
|
err_exit:
|
|
free(input);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static unsigned char *TPMLIB_GetPlaintext(const char *stream,
|
|
const char *starttag,
|
|
const char *endtag,
|
|
size_t *length)
|
|
{
|
|
char *start, *end;
|
|
unsigned char *plaintext = NULL;
|
|
|
|
start = strstr(stream, starttag);
|
|
if (start) {
|
|
start += strlen(starttag);
|
|
while (isspace((int)*start))
|
|
start++;
|
|
end = strstr(start, endtag);
|
|
if (end) {
|
|
plaintext = TPMLIB_Base64Decode(start, --end, length);
|
|
}
|
|
}
|
|
return plaintext;
|
|
}
|
|
|
|
TPM_RESULT TPMLIB_DecodeBlob(const char *buffer, enum TPMLIB_BlobType type,
|
|
unsigned char **result, size_t *result_len)
|
|
{
|
|
TPM_RESULT res = TPM_SUCCESS;
|
|
|
|
*result = TPMLIB_GetPlaintext(buffer,
|
|
tags_and_indices[type].starttag,
|
|
tags_and_indices[type].endtag,
|
|
result_len);
|
|
|
|
if (*result == NULL) {
|
|
res = TPM_FAIL;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
void TPMLIB_SetDebugFD(int fd)
|
|
{
|
|
debug_fd = fd;
|
|
}
|
|
|
|
void TPMLIB_SetDebugLevel(unsigned level)
|
|
{
|
|
debug_level = level;
|
|
}
|
|
|
|
TPM_RESULT TPMLIB_SetDebugPrefix(const char *prefix)
|
|
{
|
|
free(debug_prefix);
|
|
|
|
if (prefix) {
|
|
debug_prefix = strdup(prefix);
|
|
if (!debug_prefix)
|
|
return TPM_FAIL;
|
|
} else {
|
|
debug_prefix = NULL;
|
|
}
|
|
|
|
return TPM_SUCCESS;
|
|
}
|
|
|
|
int TPMLIB_LogPrintf(const char *format, ...)
|
|
{
|
|
unsigned level = debug_level, i;
|
|
va_list args;
|
|
char buffer[256];
|
|
int n;
|
|
|
|
if (!debug_fd || !debug_level)
|
|
return -1;
|
|
|
|
va_start(args, format);
|
|
n = vsnprintf(buffer, sizeof(buffer), format, args);
|
|
va_end(args);
|
|
|
|
if (n < 0 || n >= (int)sizeof(buffer))
|
|
return -1;
|
|
|
|
level--;
|
|
|
|
i = 0;
|
|
while (1) {
|
|
if (buffer[i] == 0)
|
|
return -1;
|
|
if (buffer[i] != ' ')
|
|
break;
|
|
if (i == level)
|
|
return -1;
|
|
i++;
|
|
}
|
|
|
|
if (debug_prefix)
|
|
dprintf(debug_fd, "%s", debug_prefix);
|
|
dprintf(debug_fd, "%s", buffer);
|
|
|
|
return i;
|
|
}
|
|
|
|
/*
|
|
* TPMLIB_LogPrintfA: Printf to the logfd without indentation check
|
|
*
|
|
* @indent: how many spaces to indent; indent of ~0 forces logging
|
|
* with indent 0 even if not debug_level is set
|
|
* @format: format to use for formatting the following parameters
|
|
* @...: varargs
|
|
*/
|
|
void TPMLIB_LogPrintfA(unsigned int indent, const char *format, ...)
|
|
{
|
|
va_list args;
|
|
char spaces[20];
|
|
int fd;
|
|
|
|
if (indent != (unsigned int)~0) {
|
|
if (!debug_fd || !debug_level)
|
|
return;
|
|
fd = debug_fd;
|
|
} else {
|
|
indent = 0;
|
|
fd = (debug_fd >= 0) ? debug_fd : STDERR_FILENO;
|
|
}
|
|
|
|
if (indent) {
|
|
if (indent > sizeof(spaces) - 1)
|
|
indent = sizeof(spaces) - 1;
|
|
memset(spaces, ' ', indent);
|
|
spaces[indent] = 0;
|
|
dprintf(fd, "%s", spaces);
|
|
}
|
|
|
|
va_start(args, format);
|
|
vdprintf(fd, format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
/*
|
|
* TPMLIB_LogArray: Display an array of data
|
|
*
|
|
* @indent: how many spaces to indent; indent of ~0 forces logging
|
|
* with indent 0 even if not debug_level is set
|
|
* @data: the data to print
|
|
* @datalen: length of the data
|
|
*/
|
|
void TPMLIB_LogArray(unsigned int indent, const unsigned char *data,
|
|
size_t datalen)
|
|
{
|
|
char line[80];
|
|
size_t i, o = 0;
|
|
|
|
for (i = 0; i < datalen; i++) {
|
|
snprintf(&line[o], sizeof(line) - o, "%02x ", data[i]);
|
|
o += 3;
|
|
if (o >= 16 * 3) {
|
|
TPMLIB_LogPrintfA(indent, "%s\n", line);
|
|
o = 0;
|
|
}
|
|
}
|
|
if (o > 0) {
|
|
TPMLIB_LogPrintfA(indent, "%s\n", line);
|
|
}
|
|
}
|
|
|
|
int TPMLIB_asprintf(char **strp, const char *fmt, ...)
|
|
{
|
|
int ret;
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
ret = vasprintf(strp, fmt, ap);
|
|
va_end(ap);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ClearCachedState(enum TPMLIB_StateType st)
|
|
{
|
|
free(cached_blobs[st].buffer);
|
|
cached_blobs[st].buffer = NULL;
|
|
cached_blobs[st].buflen = 0;
|
|
}
|
|
|
|
void ClearAllCachedState(void)
|
|
{
|
|
ClearCachedState(TPMLIB_STATE_VOLATILE);
|
|
ClearCachedState(TPMLIB_STATE_PERMANENT);
|
|
ClearCachedState(TPMLIB_STATE_SAVE_STATE);
|
|
}
|
|
|
|
/*
|
|
* 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) {
|
|
assert(*buflen != BUFLEN_EMPTY_BUFFER);
|
|
|
|
*buffer = malloc(*buflen);
|
|
if (!*buffer) {
|
|
TPMLIB_LogError("Could not allocate %u bytes.\n", *buflen);
|
|
ret = TPM_SIZE;
|
|
} else {
|
|
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;
|
|
}
|