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