]> git.proxmox.com Git - libtpms.git/blob - src/tpm_library.c
Initial import of project
[libtpms.git] / src / tpm_library.c
1 /********************************************************************************/
2 /* */
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 $ */
7 /* */
8 /* (c) Copyright IBM Corporation 2010. */
9 /* */
10 /* All rights reserved. */
11 /* */
12 /* Redistribution and use in source and binary forms, with or without */
13 /* modification, are permitted provided that the following conditions are */
14 /* met: */
15 /* */
16 /* Redistributions of source code must retain the above copyright notice, */
17 /* this list of conditions and the following disclaimer. */
18 /* */
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. */
22 /* */
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. */
26 /* */
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 /********************************************************************************/
39
40 #include <assert.h>
41 #include <string.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <ctype.h>
45
46 #include <plbase64.h>
47
48 #include "tpm_debug.h"
49 #include "tpm_error.h"
50 #include "tpm_init.h"
51 #include "tpm_library.h"
52 #include "tpm_library_intern.h"
53 #include "tpm_key.h"
54 #include "tpm_memory.h"
55 #include "tpm_process.h"
56 #include "tpm_startup.h"
57
58 #define ROUNDUP(VAL, SIZE) \
59 ( ( (VAL) + (SIZE) - 1 ) / (SIZE) ) * (SIZE)
60
61
62
63 static const struct tags_and_indices {
64 const char *starttag;
65 const char *endtag;
66 } tags_and_indices[] = {
67 [TPMLIB_BLOB_TYPE_INITSTATE] =
68 {
69 .starttag = TPMLIB_INITSTATE_START_TAG,
70 .endtag = TPMLIB_INITSTATE_END_TAG,
71 },
72 };
73
74
75
76 uint32_t TPMLIB_GetVersion(void)
77 {
78 return TPM_LIBRARY_VERSION;
79 }
80
81 TPM_RESULT TPMLIB_MainInit(void)
82 {
83 return TPM_MainInit();
84 }
85
86
87 void TPMLIB_Terminate(void)
88 {
89 TPM_Global_Delete(tpm_instances[0]);
90 }
91
92
93 /*
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.
101 */
102 TPM_RESULT TPMLIB_Process(unsigned char **respbuffer, uint32_t *resp_size,
103 uint32_t *respbufsize,
104 unsigned char *command, uint32_t command_size)
105 {
106 *resp_size = 0;
107 return TPM_ProcessA(respbuffer, resp_size, respbufsize,
108 command, command_size);
109 }
110
111
112 /*
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
115 * went alright.
116 */
117 TPM_RESULT TPMLIB_VolatileAll_Store(unsigned char **buffer,
118 uint32_t *buflen)
119 {
120 TPM_RESULT rc;
121 TPM_STORE_BUFFER tsb;
122 TPM_Sbuffer_Init(&tsb);
123 uint32_t total;
124
125 #ifdef TPM_DEBUG
126 assert(tpm_instances[0] != NULL);
127 #endif
128
129 rc = TPM_VolatileAll_Store(&tsb, tpm_instances[0]);
130
131 if (rc == TPM_SUCCESS) {
132 /* caller now owns the buffer and needs to free it */
133 TPM_Sbuffer_GetAll(&tsb, buffer, buflen, &total);
134 } else {
135 TPM_Sbuffer_Delete(&tsb);
136 *buflen = 0;
137 *buffer = NULL;
138 }
139
140 return rc;
141 }
142
143
144 /*
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).
149 */
150 TPM_RESULT TPMLIB_GetTPMProperty(enum TPMLIB_TPMProperty prop,
151 int *result)
152 {
153 switch (prop) {
154 case TPMPROP_TPM_RSA_KEY_LENGTH_MAX:
155 *result = TPM_RSA_KEY_LENGTH_MAX;
156 break;
157
158 case TPMPROP_TPM_BUFFER_MAX:
159 *result = TPM_BUFFER_MAX;
160 break;
161
162 case TPMPROP_TPM_KEY_HANDLES:
163 *result = TPM_KEY_HANDLES;
164 break;
165
166 case TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES:
167 *result = TPM_OWNER_EVICT_KEY_HANDLES;
168 break;
169
170 case TPMPROP_TPM_MIN_AUTH_SESSIONS:
171 *result = TPM_MIN_AUTH_SESSIONS;
172 break;
173
174 case TPMPROP_TPM_MIN_TRANS_SESSIONS:
175 *result = TPM_MIN_TRANS_SESSIONS;
176 break;
177
178 case TPMPROP_TPM_MIN_DAA_SESSIONS:
179 *result = TPM_MIN_DAA_SESSIONS;
180 break;
181
182 case TPMPROP_TPM_MIN_SESSION_LIST:
183 *result = TPM_MIN_SESSION_LIST;
184 break;
185
186 case TPMPROP_TPM_MIN_COUNTERS:
187 *result = TPM_MIN_COUNTERS;
188 break;
189
190 case TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN:
191 *result = TPM_NUM_FAMILY_TABLE_ENTRY_MIN;
192 break;
193
194 case TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN:
195 *result = TPM_NUM_DELEGATE_TABLE_ENTRY_MIN;
196 break;
197
198 case TPMPROP_TPM_SPACE_SAFETY_MARGIN:
199 *result = TPM_SPACE_SAFETY_MARGIN;
200 break;
201
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);
206 break;
207
208 case TPMPROP_TPM_MAX_SAVESTATE_SPACE:
209 *result = TPM_MAX_SAVESTATE_SPACE;
210 break;
211
212 case TPMPROP_TPM_MAX_VOLATILESTATE_SPACE:
213 *result = TPM_MAX_VOLATILESTATE_SPACE;
214 break;
215
216 default:
217 return TPM_FAIL;
218 }
219
220 return TPM_SUCCESS;
221 }
222
223 static struct libtpms_callbacks libtpms_cbs;
224
225 struct libtpms_callbacks *TPMLIB_GetCallbacks(void)
226 {
227 return &libtpms_cbs;
228 }
229
230
231 TPM_RESULT TPMLIB_RegisterCallbacks(struct libtpms_callbacks *callbacks)
232 {
233 int max_size = sizeof(struct libtpms_callbacks);
234
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;
239
240 /* clear the internal callback structure and copy the user provided
241 callbacks into it */
242 memset(&libtpms_cbs, 0x0, sizeof(libtpms_cbs));
243 memcpy(&libtpms_cbs, callbacks, max_size);
244
245 return TPM_SUCCESS;
246 }
247
248
249 static int is_base64ltr(char c)
250 {
251 return ((c >= 'A' && c <= 'Z') ||
252 (c >= 'a' && c <= 'z') ||
253 (c >= '0' && c <= '9') ||
254 c == '+' ||
255 c == '/' ||
256 c == '=');
257 }
258
259
260 /*
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.
264 */
265 static unsigned char *TPMLIB_Base64Decode(const char *start, const char *end,
266 size_t *length)
267 {
268 unsigned char *ret = NULL;
269 char *input = NULL, *d;
270 const char *s;
271 char c;
272 unsigned int numbase64chars = 0;
273
274 if (end < start)
275 return NULL;
276
277 while (end > start && !is_base64ltr(*end))
278 end--;
279
280 end++;
281
282 if (TPM_Malloc((unsigned char **)&input, end - start + 1) != TPM_SUCCESS)
283 return NULL;
284
285 /* copy from source string skipping '\n' and '\r' and using
286 '=' to calculate the exact length */
287 d = input;
288 s = start;
289
290 while (s < end) {
291 c = *s;
292 if (c != '=' && is_base64ltr(c)) {
293 *d = c;
294 d++;
295 numbase64chars++;
296 } else if (c == 0) {
297 break;
298 }
299 s++;
300 }
301 *d = 0;
302
303 *length = (numbase64chars / 4) * 3;
304 switch (numbase64chars % 4) {
305 case 2:
306 case 3:
307 *length += (numbase64chars % 4) - 1;
308 break;
309 case 0:
310 break;
311 case 1:
312 fprintf(stderr,"malformed base64\n");
313 goto err_exit;
314 break;
315 }
316
317 ret = (unsigned char *)PL_Base64Decode(input, 0, NULL);
318
319 err_exit:
320 free(input);
321
322 return ret;
323 }
324
325
326 static unsigned char *TPMLIB_GetPlaintext(const char *stream,
327 const char *starttag,
328 const char *endtag,
329 size_t *length)
330 {
331 char *start, *end;
332 unsigned char *plaintext = NULL;
333
334 start = strstr(stream, starttag);
335 if (start) {
336 start += strlen(starttag);
337 while (isspace(*start))
338 start++;
339 end = strstr(start, endtag);
340 if (end) {
341 plaintext = TPMLIB_Base64Decode(start, --end, length);
342 }
343 }
344 return plaintext;
345 }
346
347
348 TPM_RESULT TPMLIB_DecodeBlob(const char *buffer, enum TPMLIB_BlobType type,
349 unsigned char **result, size_t *result_len)
350 {
351 TPM_RESULT res = TPM_SUCCESS;
352
353 *result = TPMLIB_GetPlaintext(buffer,
354 tags_and_indices[type].starttag,
355 tags_and_indices[type].endtag,
356 result_len);
357
358 if (*result == NULL) {
359 res = TPM_FAIL;
360 }
361
362 return res;
363 }
364