Coverage Report

Created: 2025-07-12 06:29

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