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 <config.h>
|
---|
41 |
|
---|
42 | #include <assert.h>
|
---|
43 | #include <string.h>
|
---|
44 | #if defined __FreeBSD__
|
---|
45 | # define _WITH_DPRINTF
|
---|
46 | #endif
|
---|
47 | #include <stdio.h>
|
---|
48 | #include <stdlib.h>
|
---|
49 | #include <stdarg.h>
|
---|
50 | #include <ctype.h>
|
---|
51 | #ifndef VBOX
|
---|
52 | #include <unistd.h>
|
---|
53 | #endif
|
---|
54 | #include <stdbool.h>
|
---|
55 |
|
---|
56 | #ifdef USE_FREEBL_CRYPTO_LIBRARY
|
---|
57 | # include <plbase64.h>
|
---|
58 | #endif
|
---|
59 |
|
---|
60 | #ifdef USE_OPENSSL_CRYPTO_LIBRARY
|
---|
61 | # ifndef VBOX
|
---|
62 | # include <openssl/bio.h>
|
---|
63 | # include <openssl/evp.h>
|
---|
64 | # else
|
---|
65 | # include <iprt/errcore.h>
|
---|
66 | # include <iprt/base64.h>
|
---|
67 | # endif
|
---|
68 | #endif
|
---|
69 |
|
---|
70 | #include "tpm_debug.h"
|
---|
71 | #include "tpm_error.h"
|
---|
72 | #include "tpm_library.h"
|
---|
73 | #include "tpm_library_intern.h"
|
---|
74 | #include "tpm_nvfilename.h"
|
---|
75 | #include "tpm_tis.h"
|
---|
76 |
|
---|
77 | static const struct tags_and_indices {
|
---|
78 | const char *starttag;
|
---|
79 | const char *endtag;
|
---|
80 | } tags_and_indices[] = {
|
---|
81 | [TPMLIB_BLOB_TYPE_INITSTATE] =
|
---|
82 | {
|
---|
83 | .starttag = TPMLIB_INITSTATE_START_TAG,
|
---|
84 | .endtag = TPMLIB_INITSTATE_END_TAG,
|
---|
85 | },
|
---|
86 | };
|
---|
87 |
|
---|
88 | static const struct tpm_interface *const tpm_iface[] = {
|
---|
89 | #if WITH_TPM1
|
---|
90 | &TPM12Interface,
|
---|
91 | #else
|
---|
92 | &DisabledInterface,
|
---|
93 | #endif
|
---|
94 | #if WITH_TPM2
|
---|
95 | &TPM2Interface,
|
---|
96 | #else
|
---|
97 | &DisabledInterface,
|
---|
98 | #endif
|
---|
99 | NULL,
|
---|
100 | };
|
---|
101 |
|
---|
102 | static int debug_fd = -1;
|
---|
103 | static unsigned debug_level = 0;
|
---|
104 | static char *debug_prefix = NULL;
|
---|
105 |
|
---|
106 | static struct sized_buffer cached_blobs[TPMLIB_STATE_SAVE_STATE + 1];
|
---|
107 |
|
---|
108 | static int tpmvers_choice = 0; /* default is TPM1.2 */
|
---|
109 | static TPM_BOOL tpmvers_locked = FALSE;
|
---|
110 |
|
---|
111 | uint32_t TPMLIB_GetVersion(void)
|
---|
112 | {
|
---|
113 | return TPM_LIBRARY_VERSION;
|
---|
114 | }
|
---|
115 |
|
---|
116 | TPM_RESULT TPMLIB_ChooseTPMVersion(TPMLIB_TPMVersion ver)
|
---|
117 | {
|
---|
118 | /* TPMLIB_Terminate will reset previous choice */
|
---|
119 | if (tpmvers_locked)
|
---|
120 | return TPM_FAIL;
|
---|
121 |
|
---|
122 | switch (ver) {
|
---|
123 | #if WITH_TPM1
|
---|
124 | case TPMLIB_TPM_VERSION_1_2:
|
---|
125 | if (tpmvers_choice != 0)
|
---|
126 | ClearAllCachedState();
|
---|
127 |
|
---|
128 | tpmvers_choice = 0; // entry 0 in tpm_iface
|
---|
129 | return TPM_SUCCESS;
|
---|
130 | #endif
|
---|
131 | #if WITH_TPM2
|
---|
132 | case TPMLIB_TPM_VERSION_2:
|
---|
133 | if (tpmvers_choice != 1)
|
---|
134 | ClearAllCachedState();
|
---|
135 |
|
---|
136 | tpmvers_choice = 1; // entry 1 in tpm_iface
|
---|
137 | return TPM_SUCCESS;
|
---|
138 | #endif
|
---|
139 | default:
|
---|
140 | return TPM_FAIL;
|
---|
141 | }
|
---|
142 | }
|
---|
143 |
|
---|
144 | TPM_RESULT TPMLIB_MainInit(void)
|
---|
145 | {
|
---|
146 | if (!tpm_iface[tpmvers_choice]) {
|
---|
147 | return TPM_FAIL;
|
---|
148 | }
|
---|
149 |
|
---|
150 | tpmvers_locked = TRUE;
|
---|
151 |
|
---|
152 | return tpm_iface[tpmvers_choice]->MainInit();
|
---|
153 | }
|
---|
154 |
|
---|
155 | void TPMLIB_Terminate(void)
|
---|
156 | {
|
---|
157 | tpm_iface[tpmvers_choice]->Terminate();
|
---|
158 |
|
---|
159 | tpmvers_locked = FALSE;
|
---|
160 | }
|
---|
161 |
|
---|
162 | /*
|
---|
163 | * Send a command to the TPM. The command buffer must hold a well formatted
|
---|
164 | * TPM command and the command_size indicate the size of the command.
|
---|
165 | * The respbuffer parameter may be provided by the user and grow if
|
---|
166 | * the respbufsize size indicator is determined to be too small for the
|
---|
167 | * response. In that case a new buffer will be allocated and the size of that
|
---|
168 | * buffer returned in the respbufsize parameter. resp_size describes the
|
---|
169 | * size of the actual response within the respbuffer.
|
---|
170 | */
|
---|
171 | TPM_RESULT TPMLIB_Process(unsigned char **respbuffer, uint32_t *resp_size,
|
---|
172 | uint32_t *respbufsize,
|
---|
173 | unsigned char *command, uint32_t command_size)
|
---|
174 | {
|
---|
175 | return tpm_iface[tpmvers_choice]->Process(respbuffer,
|
---|
176 | resp_size, respbufsize,
|
---|
177 | command, command_size);
|
---|
178 | }
|
---|
179 |
|
---|
180 | /*
|
---|
181 | * Get the volatile state from the TPM. This function will return the
|
---|
182 | * buffer and the length of the buffer to the caller in case everything
|
---|
183 | * went alright.
|
---|
184 | */
|
---|
185 | TPM_RESULT TPMLIB_VolatileAll_Store(unsigned char **buffer,
|
---|
186 | uint32_t *buflen)
|
---|
187 | {
|
---|
188 | return tpm_iface[tpmvers_choice]->VolatileAllStore(buffer, buflen);
|
---|
189 | }
|
---|
190 |
|
---|
191 | /*
|
---|
192 | * Have the TPM cancel an ongoing command
|
---|
193 | */
|
---|
194 | TPM_RESULT TPMLIB_CancelCommand(void)
|
---|
195 | {
|
---|
196 | return tpm_iface[tpmvers_choice]->CancelCommand();
|
---|
197 | }
|
---|
198 |
|
---|
199 | /*
|
---|
200 | * Get a property of the TPM. The functions currently only
|
---|
201 | * return compile-time #defines but this may change in future
|
---|
202 | * versions where we may return parameters with which the TPM
|
---|
203 | * was created (rather than compiled).
|
---|
204 | */
|
---|
205 | TPM_RESULT TPMLIB_GetTPMProperty(enum TPMLIB_TPMProperty prop,
|
---|
206 | int *result)
|
---|
207 | {
|
---|
208 | switch (prop) {
|
---|
209 | case TPMPROP_TPM_BUFFER_MAX:
|
---|
210 | *result = TPM_BUFFER_MAX;
|
---|
211 | break;
|
---|
212 |
|
---|
213 | default:
|
---|
214 | return tpm_iface[tpmvers_choice]->GetTPMProperty(prop, result);
|
---|
215 | }
|
---|
216 |
|
---|
217 | return TPM_SUCCESS;
|
---|
218 | }
|
---|
219 |
|
---|
220 | char *TPMLIB_GetInfo(enum TPMLIB_InfoFlags flags)
|
---|
221 | {
|
---|
222 | return tpm_iface[tpmvers_choice]->GetInfo(flags);
|
---|
223 | }
|
---|
224 |
|
---|
225 | TPM_RESULT TPMLIB_SetState(enum TPMLIB_StateType st,
|
---|
226 | const unsigned char *buffer, uint32_t buflen)
|
---|
227 | {
|
---|
228 | return tpm_iface[tpmvers_choice]->SetState(st, buffer, buflen);
|
---|
229 | }
|
---|
230 |
|
---|
231 | TPM_RESULT TPMLIB_GetState(enum TPMLIB_StateType st,
|
---|
232 | unsigned char **buffer, uint32_t *buflen)
|
---|
233 | {
|
---|
234 | return tpm_iface[tpmvers_choice]->GetState(st, buffer, buflen);
|
---|
235 | }
|
---|
236 |
|
---|
237 | TPM_RESULT TPM_IO_Hash_Start(void)
|
---|
238 | {
|
---|
239 | return tpm_iface[tpmvers_choice]->HashStart();
|
---|
240 | }
|
---|
241 |
|
---|
242 | TPM_RESULT TPM_IO_Hash_Data(const unsigned char *data, uint32_t data_length)
|
---|
243 | {
|
---|
244 | return tpm_iface[tpmvers_choice]->HashData(data, data_length);
|
---|
245 | }
|
---|
246 |
|
---|
247 | TPM_RESULT TPM_IO_Hash_End(void)
|
---|
248 | {
|
---|
249 | return tpm_iface[tpmvers_choice]->HashEnd();
|
---|
250 | }
|
---|
251 |
|
---|
252 | TPM_RESULT TPM_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished)
|
---|
253 | {
|
---|
254 | return tpm_iface[tpmvers_choice]->TpmEstablishedGet(tpmEstablished);
|
---|
255 | }
|
---|
256 |
|
---|
257 | TPM_RESULT TPM_IO_TpmEstablished_Reset(void)
|
---|
258 | {
|
---|
259 | return tpm_iface[tpmvers_choice]->TpmEstablishedReset();
|
---|
260 | }
|
---|
261 |
|
---|
262 | uint32_t TPMLIB_SetBufferSize(uint32_t wanted_size,
|
---|
263 | uint32_t *min_size,
|
---|
264 | uint32_t *max_size)
|
---|
265 | {
|
---|
266 | return tpm_iface[tpmvers_choice]->SetBufferSize(wanted_size,
|
---|
267 | min_size,
|
---|
268 | max_size);
|
---|
269 | }
|
---|
270 |
|
---|
271 | TPM_RESULT TPMLIB_ValidateState(enum TPMLIB_StateType st,
|
---|
272 | unsigned int flags)
|
---|
273 | {
|
---|
274 | return tpm_iface[tpmvers_choice]->ValidateState(st, flags);
|
---|
275 | }
|
---|
276 |
|
---|
277 | static struct libtpms_callbacks libtpms_cbs;
|
---|
278 |
|
---|
279 | struct libtpms_callbacks *TPMLIB_GetCallbacks(void)
|
---|
280 | {
|
---|
281 | return &libtpms_cbs;
|
---|
282 | }
|
---|
283 |
|
---|
284 | TPM_RESULT TPMLIB_RegisterCallbacks(struct libtpms_callbacks *callbacks)
|
---|
285 | {
|
---|
286 | int max_size = sizeof(struct libtpms_callbacks);
|
---|
287 |
|
---|
288 | /* restrict the size of the structure to what we know currently
|
---|
289 | future versions may know more callbacks */
|
---|
290 | if (callbacks->sizeOfStruct < max_size)
|
---|
291 | max_size = callbacks->sizeOfStruct;
|
---|
292 |
|
---|
293 | /* clear the internal callback structure and copy the user provided
|
---|
294 | callbacks into it */
|
---|
295 | memset(&libtpms_cbs, 0x0, sizeof(libtpms_cbs));
|
---|
296 | memcpy(&libtpms_cbs, callbacks, max_size);
|
---|
297 |
|
---|
298 | return TPM_SUCCESS;
|
---|
299 | }
|
---|
300 |
|
---|
301 | static int is_base64ltr(char c)
|
---|
302 | {
|
---|
303 | return ((c >= 'A' && c <= 'Z') ||
|
---|
304 | (c >= 'a' && c <= 'z') ||
|
---|
305 | (c >= '0' && c <= '9') ||
|
---|
306 | c == '+' ||
|
---|
307 | c == '/' ||
|
---|
308 | c == '=');
|
---|
309 | }
|
---|
310 |
|
---|
311 | #ifdef USE_OPENSSL_CRYPTO_LIBRARY
|
---|
312 | static unsigned char *TPMLIB_OpenSSL_Base64Decode(char *input,
|
---|
313 | unsigned int outputlen)
|
---|
314 | {
|
---|
315 | #ifndef VBOX
|
---|
316 | BIO *b64, *bmem;
|
---|
317 | unsigned char *res = NULL;
|
---|
318 | int n;
|
---|
319 |
|
---|
320 | b64 = BIO_new(BIO_f_base64());
|
---|
321 | if (!b64) {
|
---|
322 | return NULL;
|
---|
323 | }
|
---|
324 |
|
---|
325 | bmem = BIO_new_mem_buf(input, strlen(input));
|
---|
326 | if (!bmem) {
|
---|
327 | BIO_free(b64);
|
---|
328 | goto cleanup;
|
---|
329 | }
|
---|
330 | bmem = BIO_push(b64, bmem);
|
---|
331 | BIO_set_flags(bmem, BIO_FLAGS_BASE64_NO_NL);
|
---|
332 |
|
---|
333 | res = malloc(outputlen);
|
---|
334 | if (!res) {
|
---|
335 | TPMLIB_LogError("Could not allocate %u bytes.\n", outputlen);
|
---|
336 | goto cleanup;
|
---|
337 | }
|
---|
338 |
|
---|
339 | n = BIO_read(bmem, res, outputlen);
|
---|
340 | if (n <= 0) {
|
---|
341 | free(res);
|
---|
342 | res = NULL;
|
---|
343 | goto cleanup;
|
---|
344 | }
|
---|
345 |
|
---|
346 | cleanup:
|
---|
347 | BIO_free_all(bmem);
|
---|
348 |
|
---|
349 | return res;
|
---|
350 | #else
|
---|
351 | ssize_t cbDec = RTBase64DecodedSize(input, NULL /*ppszEnd*/);
|
---|
352 | if (cbDec > 0)
|
---|
353 | {
|
---|
354 | void *pvData = malloc(cbDec);
|
---|
355 | if (pvData)
|
---|
356 | {
|
---|
357 | int rc = RTBase64Decode(input, pvData, cbDec, NULL /*pcbActual*/, NULL /*ppszEnd*/);
|
---|
358 | if (RT_SUCCESS(rc))
|
---|
359 | return (uint8_t *)pvData;
|
---|
360 |
|
---|
361 | free(pvData);
|
---|
362 | }
|
---|
363 | }
|
---|
364 |
|
---|
365 | return NULL;
|
---|
366 | #endif
|
---|
367 | }
|
---|
368 | #endif
|
---|
369 |
|
---|
370 | /*
|
---|
371 | * Base64 decode the string starting at 'start' and the last
|
---|
372 | * valid character may be a 'end'. The length of the decoded string
|
---|
373 | * is returned in *length.
|
---|
374 | */
|
---|
375 | static unsigned char *TPMLIB_Base64Decode(const char *start, const char *end,
|
---|
376 | size_t *length)
|
---|
377 | {
|
---|
378 | unsigned char *ret = NULL;
|
---|
379 | char *input = NULL, *d;
|
---|
380 | const char *s;
|
---|
381 | char c;
|
---|
382 | unsigned int numbase64chars = 0;
|
---|
383 |
|
---|
384 | if (end < start)
|
---|
385 | return NULL;
|
---|
386 |
|
---|
387 | while (end > start && !is_base64ltr(*end))
|
---|
388 | end--;
|
---|
389 |
|
---|
390 | end++;
|
---|
391 |
|
---|
392 | input = malloc(end - start + 1);
|
---|
393 | if (!input) {
|
---|
394 | TPMLIB_LogError("Could not allocate %u bytes.\n",
|
---|
395 | (unsigned int)(end - start + 1));
|
---|
396 | return NULL;
|
---|
397 | }
|
---|
398 |
|
---|
399 | /* copy from source string skipping '\n' and '\r' and using
|
---|
400 | '=' to calculate the exact length */
|
---|
401 | d = input;
|
---|
402 | s = start;
|
---|
403 |
|
---|
404 | while (s < end) {
|
---|
405 | c = *s;
|
---|
406 | if (is_base64ltr(c)) {
|
---|
407 | *d = c;
|
---|
408 | d++;
|
---|
409 | if (c != '=') {
|
---|
410 | numbase64chars++;
|
---|
411 | }
|
---|
412 | } else if (c == 0) {
|
---|
413 | break;
|
---|
414 | }
|
---|
415 | s++;
|
---|
416 | }
|
---|
417 | *d = 0;
|
---|
418 |
|
---|
419 | *length = (numbase64chars / 4) * 3;
|
---|
420 | switch (numbase64chars % 4) {
|
---|
421 | case 2:
|
---|
422 | case 3:
|
---|
423 | *length += (numbase64chars % 4) - 1;
|
---|
424 | break;
|
---|
425 | case 0:
|
---|
426 | break;
|
---|
427 | case 1:
|
---|
428 | fprintf(stderr,"malformed base64\n");
|
---|
429 | goto err_exit;
|
---|
430 | break;
|
---|
431 | }
|
---|
432 |
|
---|
433 | #ifdef USE_FREEBL_CRYPTO_LIBRARY
|
---|
434 | ret = (unsigned char *)PL_Base64Decode(input, 0, NULL);
|
---|
435 | #endif
|
---|
436 |
|
---|
437 | #ifdef USE_OPENSSL_CRYPTO_LIBRARY
|
---|
438 | ret = TPMLIB_OpenSSL_Base64Decode(input, *length);
|
---|
439 | #endif
|
---|
440 |
|
---|
441 | err_exit:
|
---|
442 | free(input);
|
---|
443 |
|
---|
444 | return ret;
|
---|
445 | }
|
---|
446 |
|
---|
447 | static unsigned char *TPMLIB_GetPlaintext(const char *stream,
|
---|
448 | const char *starttag,
|
---|
449 | const char *endtag,
|
---|
450 | size_t *length)
|
---|
451 | {
|
---|
452 | char *start, *end;
|
---|
453 | unsigned char *plaintext = NULL;
|
---|
454 |
|
---|
455 | start = strstr(stream, starttag);
|
---|
456 | if (start) {
|
---|
457 | start += strlen(starttag);
|
---|
458 | while (isspace((int)*start))
|
---|
459 | start++;
|
---|
460 | end = strstr(start, endtag);
|
---|
461 | if (end) {
|
---|
462 | plaintext = TPMLIB_Base64Decode(start, --end, length);
|
---|
463 | }
|
---|
464 | }
|
---|
465 | return plaintext;
|
---|
466 | }
|
---|
467 |
|
---|
468 | TPM_RESULT TPMLIB_DecodeBlob(const char *buffer, enum TPMLIB_BlobType type,
|
---|
469 | unsigned char **result, size_t *result_len)
|
---|
470 | {
|
---|
471 | TPM_RESULT res = TPM_SUCCESS;
|
---|
472 |
|
---|
473 | *result = TPMLIB_GetPlaintext(buffer,
|
---|
474 | tags_and_indices[type].starttag,
|
---|
475 | tags_and_indices[type].endtag,
|
---|
476 | result_len);
|
---|
477 |
|
---|
478 | if (*result == NULL) {
|
---|
479 | res = TPM_FAIL;
|
---|
480 | }
|
---|
481 |
|
---|
482 | return res;
|
---|
483 | }
|
---|
484 |
|
---|
485 | void TPMLIB_SetDebugFD(int fd)
|
---|
486 | {
|
---|
487 | debug_fd = fd;
|
---|
488 | }
|
---|
489 |
|
---|
490 | void TPMLIB_SetDebugLevel(unsigned level)
|
---|
491 | {
|
---|
492 | debug_level = level;
|
---|
493 | }
|
---|
494 |
|
---|
495 | TPM_RESULT TPMLIB_SetDebugPrefix(const char *prefix)
|
---|
496 | {
|
---|
497 | free(debug_prefix);
|
---|
498 |
|
---|
499 | if (prefix) {
|
---|
500 | debug_prefix = strdup(prefix);
|
---|
501 | if (!debug_prefix)
|
---|
502 | return TPM_FAIL;
|
---|
503 | } else {
|
---|
504 | debug_prefix = NULL;
|
---|
505 | }
|
---|
506 |
|
---|
507 | return TPM_SUCCESS;
|
---|
508 | }
|
---|
509 |
|
---|
510 | int TPMLIB_LogPrintf(const char *format, ...)
|
---|
511 | {
|
---|
512 | #ifndef VBOX
|
---|
513 | unsigned level = debug_level, i;
|
---|
514 | va_list args;
|
---|
515 | char buffer[256];
|
---|
516 | int n;
|
---|
517 |
|
---|
518 | if (!debug_fd || !debug_level)
|
---|
519 | return -1;
|
---|
520 |
|
---|
521 | va_start(args, format);
|
---|
522 | n = vsnprintf(buffer, sizeof(buffer), format, args);
|
---|
523 | va_end(args);
|
---|
524 |
|
---|
525 | if (n < 0 || n >= (int)sizeof(buffer))
|
---|
526 | return -1;
|
---|
527 |
|
---|
528 | level--;
|
---|
529 |
|
---|
530 | i = 0;
|
---|
531 | while (1) {
|
---|
532 | if (buffer[i] == 0)
|
---|
533 | return -1;
|
---|
534 | if (buffer[i] != ' ')
|
---|
535 | break;
|
---|
536 | if (i == level)
|
---|
537 | return -1;
|
---|
538 | i++;
|
---|
539 | }
|
---|
540 |
|
---|
541 | if (debug_prefix)
|
---|
542 | dprintf(debug_fd, "%s", debug_prefix);
|
---|
543 | dprintf(debug_fd, "%s", buffer);
|
---|
544 |
|
---|
545 | return i;
|
---|
546 | #else
|
---|
547 | return 0;
|
---|
548 | #endif
|
---|
549 | }
|
---|
550 |
|
---|
551 | /*
|
---|
552 | * TPMLIB_LogPrintfA: Printf to the logfd without indentation check
|
---|
553 | *
|
---|
554 | * @indent: how many spaces to indent; indent of ~0 forces logging
|
---|
555 | * with indent 0 even if not debug_level is set
|
---|
556 | * @format: format to use for formatting the following parameters
|
---|
557 | * @...: varargs
|
---|
558 | */
|
---|
559 | void TPMLIB_LogPrintfA(unsigned int indent, const char *format, ...)
|
---|
560 | {
|
---|
561 | #ifndef VBOX
|
---|
562 | va_list args;
|
---|
563 | char spaces[20];
|
---|
564 | int fd;
|
---|
565 |
|
---|
566 | if (indent != (unsigned int)~0) {
|
---|
567 | if (!debug_fd || !debug_level)
|
---|
568 | return;
|
---|
569 | fd = debug_fd;
|
---|
570 | } else {
|
---|
571 | indent = 0;
|
---|
572 | fd = (debug_fd >= 0) ? debug_fd : STDERR_FILENO;
|
---|
573 | }
|
---|
574 |
|
---|
575 | if (indent) {
|
---|
576 | if (indent > sizeof(spaces) - 1)
|
---|
577 | indent = sizeof(spaces) - 1;
|
---|
578 | memset(spaces, ' ', indent);
|
---|
579 | spaces[indent] = 0;
|
---|
580 | dprintf(fd, "%s", spaces);
|
---|
581 | }
|
---|
582 |
|
---|
583 | va_start(args, format);
|
---|
584 | vdprintf(fd, format, args);
|
---|
585 | va_end(args);
|
---|
586 | #endif
|
---|
587 | }
|
---|
588 |
|
---|
589 | /*
|
---|
590 | * TPMLIB_LogArray: Display an array of data
|
---|
591 | *
|
---|
592 | * @indent: how many spaces to indent; indent of ~0 forces logging
|
---|
593 | * with indent 0 even if not debug_level is set
|
---|
594 | * @data: the data to print
|
---|
595 | * @datalen: length of the data
|
---|
596 | */
|
---|
597 | void TPMLIB_LogArray(unsigned int indent, const unsigned char *data,
|
---|
598 | size_t datalen)
|
---|
599 | {
|
---|
600 | char line[80];
|
---|
601 | size_t i, o = 0;
|
---|
602 |
|
---|
603 | for (i = 0; i < datalen; i++) {
|
---|
604 | snprintf(&line[o], sizeof(line) - o, "%02x ", data[i]);
|
---|
605 | o += 3;
|
---|
606 | if (o >= 16 * 3) {
|
---|
607 | TPMLIB_LogPrintfA(indent, "%s\n", line);
|
---|
608 | o = 0;
|
---|
609 | }
|
---|
610 | }
|
---|
611 | if (o > 0) {
|
---|
612 | TPMLIB_LogPrintfA(indent, "%s\n", line);
|
---|
613 | }
|
---|
614 | }
|
---|
615 |
|
---|
616 | void ClearCachedState(enum TPMLIB_StateType st)
|
---|
617 | {
|
---|
618 | free(cached_blobs[st].buffer);
|
---|
619 | cached_blobs[st].buffer = NULL;
|
---|
620 | cached_blobs[st].buflen = 0;
|
---|
621 | }
|
---|
622 |
|
---|
623 | void ClearAllCachedState(void)
|
---|
624 | {
|
---|
625 | ClearCachedState(TPMLIB_STATE_VOLATILE);
|
---|
626 | ClearCachedState(TPMLIB_STATE_PERMANENT);
|
---|
627 | ClearCachedState(TPMLIB_STATE_SAVE_STATE);
|
---|
628 | }
|
---|
629 |
|
---|
630 | /*
|
---|
631 | * Set buffer for cached state; we allow setting an empty cached state
|
---|
632 | * by the caller passing a NULL pointer for the buffer.
|
---|
633 | */
|
---|
634 | void SetCachedState(enum TPMLIB_StateType st,
|
---|
635 | unsigned char *buffer, uint32_t buflen)
|
---|
636 | {
|
---|
637 | free(cached_blobs[st].buffer);
|
---|
638 | cached_blobs[st].buffer = buffer;
|
---|
639 | cached_blobs[st].buflen = buffer ? buflen : BUFLEN_EMPTY_BUFFER;
|
---|
640 | }
|
---|
641 |
|
---|
642 | void GetCachedState(enum TPMLIB_StateType st,
|
---|
643 | unsigned char **buffer, uint32_t *buflen,
|
---|
644 | bool *is_empty_buffer)
|
---|
645 | {
|
---|
646 | /* caller owns blob now */
|
---|
647 | *buffer = cached_blobs[st].buffer;
|
---|
648 | *buflen = cached_blobs[st].buflen;
|
---|
649 | *is_empty_buffer = (*buflen == BUFLEN_EMPTY_BUFFER);
|
---|
650 | cached_blobs[st].buffer = NULL;
|
---|
651 | cached_blobs[st].buflen = 0;
|
---|
652 | }
|
---|
653 |
|
---|
654 | bool HasCachedState(enum TPMLIB_StateType st)
|
---|
655 | {
|
---|
656 | return (cached_blobs[st].buffer != NULL || cached_blobs[st].buflen != 0);
|
---|
657 | }
|
---|
658 |
|
---|
659 | TPM_RESULT CopyCachedState(enum TPMLIB_StateType st,
|
---|
660 | unsigned char **buffer, uint32_t *buflen,
|
---|
661 | bool *is_empty_buffer)
|
---|
662 | {
|
---|
663 | TPM_RESULT ret = TPM_SUCCESS;
|
---|
664 |
|
---|
665 | /* buflen may indicate an empty buffer */
|
---|
666 | *buflen = cached_blobs[st].buflen;
|
---|
667 | *is_empty_buffer = (*buflen == BUFLEN_EMPTY_BUFFER);
|
---|
668 |
|
---|
669 | if (cached_blobs[st].buffer) {
|
---|
670 | *buffer = malloc(*buflen);
|
---|
671 | if (!*buffer) {
|
---|
672 | TPMLIB_LogError("Could not allocate %u bytes.\n", *buflen);
|
---|
673 | ret = TPM_SIZE;
|
---|
674 | } else {
|
---|
675 | memcpy(*buffer, cached_blobs[st].buffer, *buflen);
|
---|
676 | }
|
---|
677 | } else {
|
---|
678 | *buffer = NULL;
|
---|
679 | }
|
---|
680 |
|
---|
681 | return ret;
|
---|
682 | }
|
---|
683 |
|
---|
684 | const char *TPMLIB_StateTypeToName(enum TPMLIB_StateType st)
|
---|
685 | {
|
---|
686 | switch (st) {
|
---|
687 | case TPMLIB_STATE_PERMANENT:
|
---|
688 | return TPM_PERMANENT_ALL_NAME;
|
---|
689 | case TPMLIB_STATE_VOLATILE:
|
---|
690 | return TPM_VOLATILESTATE_NAME;
|
---|
691 | case TPMLIB_STATE_SAVE_STATE:
|
---|
692 | return TPM_SAVESTATE_NAME;
|
---|
693 | }
|
---|
694 | return NULL;
|
---|
695 | }
|
---|
696 |
|
---|
697 | enum TPMLIB_StateType TPMLIB_NameToStateType(const char *name)
|
---|
698 | {
|
---|
699 | if (!name)
|
---|
700 | return 0;
|
---|
701 | if (!strcmp(name, TPM_PERMANENT_ALL_NAME))
|
---|
702 | return TPMLIB_STATE_PERMANENT;
|
---|
703 | if (!strcmp(name, TPM_VOLATILESTATE_NAME))
|
---|
704 | return TPMLIB_STATE_VOLATILE;
|
---|
705 | if (!strcmp(name, TPM_SAVESTATE_NAME))
|
---|
706 | return TPMLIB_STATE_SAVE_STATE;
|
---|
707 | return 0;
|
---|
708 | }
|
---|