1 /********************************************************************************/
3 /* LibTPM interface functions */
4 /* Written by Stefan Berger */
5 /* IBM Thomas J. Watson Research Center */
6 /* $Id: tpm_library.c 4615 2011-08-30 15:35:24Z stefanb $ */
8 /* (c) Copyright IBM Corporation 2010. */
10 /* All rights reserved. */
12 /* Redistribution and use in source and binary forms, with or without */
13 /* modification, are permitted provided that the following conditions are */
16 /* Redistributions of source code must retain the above copyright notice, */
17 /* this list of conditions and the following disclaimer. */
19 /* Redistributions in binary form must reproduce the above copyright */
20 /* notice, this list of conditions and the following disclaimer in the */
21 /* documentation and/or other materials provided with the distribution. */
23 /* Neither the names of the IBM Corporation nor the names of its */
24 /* contributors may be used to endorse or promote products derived from */
25 /* this software without specific prior written permission. */
27 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
28 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
29 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
30 /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
31 /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
32 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
33 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
34 /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
35 /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
36 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
37 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
38 /********************************************************************************/
49 #ifdef USE_FREEBL_CRYPTO_LIBRARY
50 # include <plbase64.h>
53 #ifdef USE_OPENSSL_CRYPTO_LIBRARY
54 # include <openssl/bio.h>
55 # include <openssl/evp.h>
58 #include "tpm12/tpm_debug.h"
59 #include "tpm_error.h"
60 #include "tpm_library.h"
61 #include "tpm_library_intern.h"
62 #include "tpm_memory.h"
64 static const struct tags_and_indices
{
67 } tags_and_indices
[] = {
68 [TPMLIB_BLOB_TYPE_INITSTATE
] =
70 .starttag
= TPMLIB_INITSTATE_START_TAG
,
71 .endtag
= TPMLIB_INITSTATE_END_TAG
,
75 static const struct tpm_interface
*const tpm_iface
[] = {
79 static int debug_fd
= -1;
80 static unsigned debug_level
= 0;
81 static char *debug_prefix
= NULL
;
83 uint32_t TPMLIB_GetVersion(void)
85 return TPM_LIBRARY_VERSION
;
88 TPM_RESULT
TPMLIB_MainInit(void)
90 return tpm_iface
[0]->MainInit();
93 void TPMLIB_Terminate(void)
95 tpm_iface
[0]->Terminate();
99 * Send a command to the TPM. The command buffer must hold a well formatted
100 * TPM command and the command_size indicate the size of the command.
101 * The respbuffer parameter may be provided by the user and grow if
102 * the respbufsize size indicator is determined to be too small for the
103 * response. In that case a new buffer will be allocated and the size of that
104 * buffer returned in the respbufsize parameter. resp_size describes the
105 * size of the actual response within the respbuffer.
107 TPM_RESULT
TPMLIB_Process(unsigned char **respbuffer
, uint32_t *resp_size
,
108 uint32_t *respbufsize
,
109 unsigned char *command
, uint32_t command_size
)
111 return tpm_iface
[0]->Process(respbuffer
, resp_size
, respbufsize
,
112 command
, command_size
);
116 * Get the volatile state from the TPM. This function will return the
117 * buffer and the length of the buffer to the caller in case everything
120 TPM_RESULT
TPMLIB_VolatileAll_Store(unsigned char **buffer
,
123 return tpm_iface
[0]->VolatileAllStore(buffer
, buflen
);
127 * Get a property of the TPM. The functions currently only
128 * return compile-time #defines but this may change in future
129 * versions where we may return parameters with which the TPM
130 * was created (rather than compiled).
132 TPM_RESULT
TPMLIB_GetTPMProperty(enum TPMLIB_TPMProperty prop
,
136 case TPMPROP_TPM_BUFFER_MAX
:
137 *result
= TPM_BUFFER_MAX
;
141 return tpm_iface
[0]->GetTPMProperty(prop
, result
);
147 TPM_RESULT
TPM_IO_Hash_Start(void)
149 return tpm_iface
[0]->HashStart();
152 TPM_RESULT
TPM_IO_Hash_Data(const unsigned char *data
, uint32_t data_length
)
154 return tpm_iface
[0]->HashData(data
, data_length
);
157 TPM_RESULT
TPM_IO_Hash_End(void)
159 return tpm_iface
[0]->HashEnd();
162 TPM_RESULT
TPM_IO_TpmEstablished_Get(TPM_BOOL
*tpmEstablished
)
164 return tpm_iface
[0]->TpmEstablishedGet(tpmEstablished
);
167 uint32_t TPMLIB_SetBufferSize(uint32_t wanted_size
)
169 return tpm_iface
[0]->SetBufferSize(wanted_size
);
172 static struct libtpms_callbacks libtpms_cbs
;
174 struct libtpms_callbacks
*TPMLIB_GetCallbacks(void)
179 TPM_RESULT
TPMLIB_RegisterCallbacks(struct libtpms_callbacks
*callbacks
)
181 int max_size
= sizeof(struct libtpms_callbacks
);
183 /* restrict the size of the structure to what we know currently
184 future versions may know more callbacks */
185 if (callbacks
->sizeOfStruct
< max_size
)
186 max_size
= callbacks
->sizeOfStruct
;
188 /* clear the internal callback structure and copy the user provided
190 memset(&libtpms_cbs
, 0x0, sizeof(libtpms_cbs
));
191 memcpy(&libtpms_cbs
, callbacks
, max_size
);
196 static int is_base64ltr(char c
)
198 return ((c
>= 'A' && c
<= 'Z') ||
199 (c
>= 'a' && c
<= 'z') ||
200 (c
>= '0' && c
<= '9') ||
206 #ifdef USE_OPENSSL_CRYPTO_LIBRARY
207 static unsigned char *TPMLIB_OpenSSL_Base64Decode(char *input
,
208 unsigned int outputlen
)
211 unsigned char *res
= NULL
;
215 b64
= BIO_new(BIO_f_base64());
220 bmem
= BIO_new_mem_buf(input
, strlen(input
));
225 bmem
= BIO_push(b64
, bmem
);
226 BIO_set_flags(bmem
, BIO_FLAGS_BASE64_NO_NL
);
228 rc
= TPM_Malloc(&res
, outputlen
);
229 if (rc
!= TPM_SUCCESS
) {
233 n
= BIO_read(bmem
, res
, outputlen
);
248 * Base64 decode the string starting at 'start' and the last
249 * valid character may be a 'end'. The length of the decoded string
250 * is returned in *length.
252 static unsigned char *TPMLIB_Base64Decode(const char *start
, const char *end
,
255 unsigned char *ret
= NULL
;
256 char *input
= NULL
, *d
;
259 unsigned int numbase64chars
= 0;
264 while (end
> start
&& !is_base64ltr(*end
))
269 if (TPM_Malloc((unsigned char **)&input
, end
- start
+ 1) != TPM_SUCCESS
)
272 /* copy from source string skipping '\n' and '\r' and using
273 '=' to calculate the exact length */
279 if (is_base64ltr(c
)) {
292 *length
= (numbase64chars
/ 4) * 3;
293 switch (numbase64chars
% 4) {
296 *length
+= (numbase64chars
% 4) - 1;
301 fprintf(stderr
,"malformed base64\n");
306 #ifdef USE_FREEBL_CRYPTO_LIBRARY
307 ret
= (unsigned char *)PL_Base64Decode(input
, 0, NULL
);
310 #ifdef USE_OPENSSL_CRYPTO_LIBRARY
311 ret
= TPMLIB_OpenSSL_Base64Decode(input
, *length
);
320 static unsigned char *TPMLIB_GetPlaintext(const char *stream
,
321 const char *starttag
,
326 unsigned char *plaintext
= NULL
;
328 start
= strstr(stream
, starttag
);
330 start
+= strlen(starttag
);
331 while (isspace((int)*start
))
333 end
= strstr(start
, endtag
);
335 plaintext
= TPMLIB_Base64Decode(start
, --end
, length
);
341 TPM_RESULT
TPMLIB_DecodeBlob(const char *buffer
, enum TPMLIB_BlobType type
,
342 unsigned char **result
, size_t *result_len
)
344 TPM_RESULT res
= TPM_SUCCESS
;
346 *result
= TPMLIB_GetPlaintext(buffer
,
347 tags_and_indices
[type
].starttag
,
348 tags_and_indices
[type
].endtag
,
351 if (*result
== NULL
) {
358 void TPMLIB_SetDebugFD(int fd
)
363 void TPMLIB_SetDebugLevel(unsigned level
)
368 TPM_RESULT
TPMLIB_SetDebugPrefix(const char *prefix
)
373 debug_prefix
= strdup(prefix
);
383 int TPMLIB_LogPrintf(const char *format
, ...)
385 unsigned level
= debug_level
, i
;
390 if (!debug_fd
|| !debug_level
)
393 va_start(args
, format
);
394 n
= vsnprintf(buffer
, sizeof(buffer
), format
, args
);
397 if (n
< 0 || n
>= (int)sizeof(buffer
))
406 if (buffer
[i
] != ' ')
414 dprintf(debug_fd
, "%s", debug_prefix
);
415 dprintf(debug_fd
, "%s", buffer
);
421 * TPMLIB_LogPrintfA: Printf to the logfd without indentation check
423 void TPMLIB_LogPrintfA(unsigned int indent
, const char *format
, ...)
428 if (!debug_fd
|| !debug_level
)
432 if (indent
> sizeof(spaces
) - 1)
433 indent
= sizeof(spaces
) - 1;
434 memset(spaces
, ' ', indent
);
436 dprintf(debug_fd
, "%s", spaces
);
439 va_start(args
, format
);
440 vdprintf(debug_fd
, format
, args
);