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