]> git.proxmox.com Git - libtpms.git/blame - src/tpm_library.c
Move common debug, memory & nvfile units to src/
[libtpms.git] / src / tpm_library.c
CommitLineData
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
70static 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
81static 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
89static int debug_fd = -1;
90static unsigned debug_level = 0;
91static char *debug_prefix = NULL;
92
c76f52ef
SB
93static struct sized_buffer cached_blobs[TPMLIB_STATE_SAVE_STATE + 1];
94
3cf528aa
SB
95static int tpmvers_choice = 0; /* default is TPM1.2 */
96static TPM_BOOL tpmvers_locked = FALSE;
97
a0098eda
CB
98uint32_t TPMLIB_GetVersion(void)
99{
100 return TPM_LIBRARY_VERSION;
101}
102
3cf528aa
SB
103TPM_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
133TPM_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
140void 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 */
156TPM_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 */
170TPM_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 */
179TPM_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 */
190TPM_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
205char *TPMLIB_GetInfo(enum TPMLIB_InfoFlags flags)
206{
3cf528aa 207 return tpm_iface[tpmvers_choice]->GetInfo(flags);
70547a75
SB
208}
209
ec672b4e
SB
210TPM_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
216TPM_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
222TPM_RESULT TPM_IO_Hash_Start(void)
223{
3cf528aa 224 return tpm_iface[tpmvers_choice]->HashStart();
39c9604a 225}
a0098eda 226
39c9604a
SB
227TPM_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
232TPM_RESULT TPM_IO_Hash_End(void)
233{
3cf528aa 234 return tpm_iface[tpmvers_choice]->HashEnd();
39c9604a 235}
a0098eda 236
39c9604a
SB
237TPM_RESULT TPM_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished)
238{
3cf528aa
SB
239 return tpm_iface[tpmvers_choice]->TpmEstablishedGet(tpmEstablished);
240}
241
242TPM_RESULT TPM_IO_TpmEstablished_Reset(void)
243{
244 return tpm_iface[tpmvers_choice]->TpmEstablishedReset();
a0098eda
CB
245}
246
ae3f105a
SB
247uint32_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
256TPM_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
262static struct libtpms_callbacks libtpms_cbs;
263
264struct libtpms_callbacks *TPMLIB_GetCallbacks(void)
265{
266 return &libtpms_cbs;
267}
268
a0098eda
CB
269TPM_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
286static 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
297static 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
330cleanup:
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 */
342static 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
408err_exit:
409 free(input);
410
411 return ret;
412}
413
a0098eda
CB
414static 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
435TPM_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
452void TPMLIB_SetDebugFD(int fd)
453{
454 debug_fd = fd;
455}
456
457void TPMLIB_SetDebugLevel(unsigned level)
458{
459 debug_level = level;
460}
461
462TPM_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
477int 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 */
522void 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 */
558void 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
577void 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
584void 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 */
595void 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
603void 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
615bool HasCachedState(enum TPMLIB_StateType st)
616{
617 return (cached_blobs[st].buffer != NULL || cached_blobs[st].buflen != 0);
618}
619
620TPM_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
645const 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
658enum 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}