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 /********************************************************************************/
48 #include "tpm_debug.h"
49 #include "tpm_error.h"
51 #include "tpm_library.h"
52 #include "tpm_library_intern.h"
54 #include "tpm_memory.h"
55 #include "tpm_process.h"
56 #include "tpm_startup.h"
58 #define ROUNDUP(VAL, SIZE) \
59 ( ( (VAL) + (SIZE) - 1 ) / (SIZE) ) * (SIZE)
63 static const struct tags_and_indices
{
66 } tags_and_indices
[] = {
67 [TPMLIB_BLOB_TYPE_INITSTATE
] =
69 .starttag
= TPMLIB_INITSTATE_START_TAG
,
70 .endtag
= TPMLIB_INITSTATE_END_TAG
,
76 uint32_t TPMLIB_GetVersion(void)
78 return TPM_LIBRARY_VERSION
;
81 TPM_RESULT
TPMLIB_MainInit(void)
83 return TPM_MainInit();
87 void TPMLIB_Terminate(void)
89 TPM_Global_Delete(tpm_instances
[0]);
94 * Send a command to the TPM. The command buffer must hold a well formatted
95 * TPM command and the command_size indicate the size of the command.
96 * The respbuffer parameter may be provided by the user and grow if
97 * the respbufsize size indicator is determined to be too small for the
98 * response. In that case a new buffer will be allocated and the size of that
99 * buffer returned in the respbufsize parameter. resp_size describes the
100 * size of the actual response within the respbuffer.
102 TPM_RESULT
TPMLIB_Process(unsigned char **respbuffer
, uint32_t *resp_size
,
103 uint32_t *respbufsize
,
104 unsigned char *command
, uint32_t command_size
)
107 return TPM_ProcessA(respbuffer
, resp_size
, respbufsize
,
108 command
, command_size
);
113 * Get the volatile state from the TPM. This function will return the
114 * buffer and the length of the buffer to the caller in case everything
117 TPM_RESULT
TPMLIB_VolatileAll_Store(unsigned char **buffer
,
121 TPM_STORE_BUFFER tsb
;
122 TPM_Sbuffer_Init(&tsb
);
126 assert(tpm_instances
[0] != NULL
);
129 rc
= TPM_VolatileAll_Store(&tsb
, tpm_instances
[0]);
131 if (rc
== TPM_SUCCESS
) {
132 /* caller now owns the buffer and needs to free it */
133 TPM_Sbuffer_GetAll(&tsb
, buffer
, buflen
, &total
);
135 TPM_Sbuffer_Delete(&tsb
);
145 * Get a property of the TPM. The functions currently only
146 * return compile-time #defines but this may change in future
147 * versions where we may return parameters with which the TPM
148 * was created (rather than compiled).
150 TPM_RESULT
TPMLIB_GetTPMProperty(enum TPMLIB_TPMProperty prop
,
154 case TPMPROP_TPM_RSA_KEY_LENGTH_MAX
:
155 *result
= TPM_RSA_KEY_LENGTH_MAX
;
158 case TPMPROP_TPM_BUFFER_MAX
:
159 *result
= TPM_BUFFER_MAX
;
162 case TPMPROP_TPM_KEY_HANDLES
:
163 *result
= TPM_KEY_HANDLES
;
166 case TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES
:
167 *result
= TPM_OWNER_EVICT_KEY_HANDLES
;
170 case TPMPROP_TPM_MIN_AUTH_SESSIONS
:
171 *result
= TPM_MIN_AUTH_SESSIONS
;
174 case TPMPROP_TPM_MIN_TRANS_SESSIONS
:
175 *result
= TPM_MIN_TRANS_SESSIONS
;
178 case TPMPROP_TPM_MIN_DAA_SESSIONS
:
179 *result
= TPM_MIN_DAA_SESSIONS
;
182 case TPMPROP_TPM_MIN_SESSION_LIST
:
183 *result
= TPM_MIN_SESSION_LIST
;
186 case TPMPROP_TPM_MIN_COUNTERS
:
187 *result
= TPM_MIN_COUNTERS
;
190 case TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN
:
191 *result
= TPM_NUM_FAMILY_TABLE_ENTRY_MIN
;
194 case TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN
:
195 *result
= TPM_NUM_DELEGATE_TABLE_ENTRY_MIN
;
198 case TPMPROP_TPM_SPACE_SAFETY_MARGIN
:
199 *result
= TPM_SPACE_SAFETY_MARGIN
;
202 case TPMPROP_TPM_MAX_NV_SPACE
:
203 /* fill up 20 kb.; this provides some safety margin (currently
204 >4Kb) for possible future expansion of this blob */
205 *result
= ROUNDUP(TPM_MAX_NV_SPACE
, 20 * 1024);
208 case TPMPROP_TPM_MAX_SAVESTATE_SPACE
:
209 *result
= TPM_MAX_SAVESTATE_SPACE
;
212 case TPMPROP_TPM_MAX_VOLATILESTATE_SPACE
:
213 *result
= TPM_MAX_VOLATILESTATE_SPACE
;
223 static struct libtpms_callbacks libtpms_cbs
;
225 struct libtpms_callbacks
*TPMLIB_GetCallbacks(void)
231 TPM_RESULT
TPMLIB_RegisterCallbacks(struct libtpms_callbacks
*callbacks
)
233 int max_size
= sizeof(struct libtpms_callbacks
);
235 /* restrict the size of the structure to what we know currently
236 future versions may know more callbacks */
237 if (callbacks
->sizeOfStruct
< max_size
)
238 max_size
= callbacks
->sizeOfStruct
;
240 /* clear the internal callback structure and copy the user provided
242 memset(&libtpms_cbs
, 0x0, sizeof(libtpms_cbs
));
243 memcpy(&libtpms_cbs
, callbacks
, max_size
);
249 static int is_base64ltr(char c
)
251 return ((c
>= 'A' && c
<= 'Z') ||
252 (c
>= 'a' && c
<= 'z') ||
253 (c
>= '0' && c
<= '9') ||
261 * Base64 decode the string starting at 'start' and the last
262 * valid character may be a 'end'. The length of the decoded string
263 * is returned in *length.
265 static unsigned char *TPMLIB_Base64Decode(const char *start
, const char *end
,
268 unsigned char *ret
= NULL
;
269 char *input
= NULL
, *d
;
272 unsigned int numbase64chars
= 0;
277 while (end
> start
&& !is_base64ltr(*end
))
282 if (TPM_Malloc((unsigned char **)&input
, end
- start
+ 1) != TPM_SUCCESS
)
285 /* copy from source string skipping '\n' and '\r' and using
286 '=' to calculate the exact length */
292 if (c
!= '=' && is_base64ltr(c
)) {
303 *length
= (numbase64chars
/ 4) * 3;
304 switch (numbase64chars
% 4) {
307 *length
+= (numbase64chars
% 4) - 1;
312 fprintf(stderr
,"malformed base64\n");
317 ret
= (unsigned char *)PL_Base64Decode(input
, 0, NULL
);
326 static unsigned char *TPMLIB_GetPlaintext(const char *stream
,
327 const char *starttag
,
332 unsigned char *plaintext
= NULL
;
334 start
= strstr(stream
, starttag
);
336 start
+= strlen(starttag
);
337 while (isspace(*start
))
339 end
= strstr(start
, endtag
);
341 plaintext
= TPMLIB_Base64Decode(start
, --end
, length
);
348 TPM_RESULT
TPMLIB_DecodeBlob(const char *buffer
, enum TPMLIB_BlobType type
,
349 unsigned char **result
, size_t *result_len
)
351 TPM_RESULT res
= TPM_SUCCESS
;
353 *result
= TPMLIB_GetPlaintext(buffer
,
354 tags_and_indices
[type
].starttag
,
355 tags_and_indices
[type
].endtag
,
358 if (*result
== NULL
) {