Coverage Report

Created: 2025-05-08 06:39

/src/libtpms/src/tpm_tpm2_interface.c
Line
Count
Source (jump to first uncovered line)
1
/********************************************************************************/
2
/*                    */
3
/*      LibTPM TPM 2 call interface functions       */
4
/*           Written by Stefan Berger       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*                    */
7
/* (c) Copyright IBM Corporation 2015.            */
8
/*                    */
9
/* All rights reserved.               */
10
/*                    */
11
/* Redistribution and use in source and binary forms, with or without   */
12
/* modification, are permitted provided that the following conditions are */
13
/* met:                   */
14
/*                    */
15
/* Redistributions of source code must retain the above copyright notice, */
16
/* this list of conditions and the following disclaimer.      */
17
/*                    */
18
/* Redistributions in binary form must reproduce the above copyright    */
19
/* notice, this list of conditions and the following disclaimer in the    */
20
/* documentation and/or other materials provided with the distribution.   */
21
/*                    */
22
/* Neither the names of the IBM Corporation nor the names of its    */
23
/* contributors may be used to endorse or promote products derived from   */
24
/* this software without specific prior written permission.     */
25
/*                    */
26
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS    */
27
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    */
28
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  */
29
/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT   */
30
/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
31
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT   */
32
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  */
33
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  */
34
/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT    */
35
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  */
36
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   */
37
/********************************************************************************/
38
39
#include <config.h>
40
41
#include <string.h>
42
#include <stdbool.h>
43
44
#ifndef LIB_EXPORT
45
#define LIB_EXPORT
46
#endif
47
#include "tpm2/Tpm.h"
48
#include "tpm2/Manufacture_fp.h"
49
#include "tpm2/Platform_fp.h"
50
#include "tpm2/ExecCommand_fp.h"
51
#include "tpm2/TpmTcpProtocol.h"
52
#include "tpm2/Simulator_fp.h"
53
#include "tpm2/_TPM_Hash_Data_fp.h"
54
#include "tpm2/_TPM_Init_fp.h"
55
#include "tpm2/StateMarshal.h"
56
#include "tpm2/PlatformACT.h"
57
#include "tpm2/PlatformData.h"
58
#include "tpm2/Volatile.h"
59
#include "tpm2/crypto/openssl/ExpDCache_fp.h"
60
61
#define TPM_HAVE_TPM2_DECLARATIONS
62
#include "tpm_nvfile.h" // TPM_NVRAM_Loaddata()
63
#include "tpm_error.h"
64
#include "tpm_library_intern.h"
65
#include "tpm_nvfilename.h"
66
67
extern BOOL      g_inFailureMode;
68
static BOOL      reportedFailureCommand;
69
static char     *g_profile;
70
static TPM_BOOL  g_wasManufactured;
71
72
/*
73
 * Check whether the main NVRAM file exists. Return TRUE if it doesn, FALSE otherwise
74
 */
75
static TPM_BOOL _TPM2_CheckNVRAMFileExists(bool *has_nvram_loaddata_callback)
76
14.2k
{
77
14.2k
#ifdef TPM_LIBTPMS_CALLBACKS
78
14.2k
    struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
79
14.2k
    const char *name = TPM_PERMANENT_ALL_NAME;
80
14.2k
    unsigned char *data = NULL;
81
14.2k
    uint32_t length = 0;
82
14.2k
    uint32_t tpm_number = 0;
83
14.2k
    TPM_RESULT ret;
84
85
14.2k
    *has_nvram_loaddata_callback = cbs->tpm_nvram_loaddata != NULL;
86
14.2k
    if (cbs->tpm_nvram_loaddata) {
87
14.2k
        ret = cbs->tpm_nvram_loaddata(&data, &length, tpm_number, name);
88
14.2k
        free(data);
89
        /* a file exists once NOT TPM_RETRY is returned */
90
14.2k
        if (ret != TPM_RETRY)
91
7.10k
            return TRUE;
92
14.2k
    }
93
#else
94
    *has_nvram_loaddata_callback = FALSE;
95
#endif /* TPM_LIBTPMS_CALLBACKS */
96
97
7.10k
    return FALSE;
98
14.2k
}
99
100
static TPM_RESULT TPM2_MainInit(void)
101
14.2k
{
102
14.2k
    TPM_RESULT ret = TPM_SUCCESS;
103
14.2k
    bool has_cached_state;
104
14.2k
    bool has_nvram_file;
105
14.2k
    bool has_nvram_loaddata_callback;
106
107
14.2k
    g_inFailureMode = FALSE;
108
14.2k
    reportedFailureCommand = FALSE;
109
14.2k
    g_wasManufactured = FALSE;
110
111
14.2k
#ifdef TPM_LIBTPMS_CALLBACKS
112
14.2k
    struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
113
114
14.2k
    if (cbs->tpm_io_init) {
115
14.2k
        ret = cbs->tpm_io_init();
116
14.2k
        if (ret != TPM_SUCCESS)
117
0
            return ret;
118
14.2k
    }
119
120
14.2k
    if (cbs->tpm_nvram_init) {
121
0
        ret = cbs->tpm_nvram_init();
122
0
        if (ret != TPM_SUCCESS)
123
0
            return ret;
124
0
    }
125
14.2k
#endif /* TPM_LIBTPMS_CALLBACKS */
126
127
14.2k
    _rpc__Signal_PowerOff();
128
129
14.2k
    has_cached_state = HasCachedState(TPMLIB_STATE_PERMANENT);
130
14.2k
    has_nvram_file = _TPM2_CheckNVRAMFileExists(&has_nvram_loaddata_callback);
131
132
14.2k
    if (!has_cached_state) {
133
7.10k
        if (!has_nvram_file) {
134
7.10k
            ret = _plat__NVEnable(NULL, 0);
135
7.10k
            if (ret)
136
0
                TPMLIB_LogTPM2Error(
137
7.10k
                    "%s: _plat__NVEnable(NULL) failed: %d\n",
138
7.10k
                    __func__, ret);
139
7.10k
            if (TPM_Manufacture(TRUE, g_profile) < 0 || g_inFailureMode) {
140
0
                TPMLIB_LogTPM2Error("%s: TPM_Manufacture(TRUE) failed or TPM in "
141
0
                                    "failure mode\n", __func__);
142
0
                reportedFailureCommand = TRUE;
143
7.10k
            } else {
144
7.10k
                g_wasManufactured = TRUE;
145
7.10k
            }
146
7.10k
        }
147
7.10k
    } else if (!has_nvram_loaddata_callback) {
148
0
        ret = _plat__NVEnable_NVChipFile(NULL);
149
0
        if (ret)
150
0
            TPMLIB_LogTPM2Error("%s: _plat__NVEnable_File(NULL) failed: %d\n",
151
0
                                __func__, ret);
152
0
    }
153
154
14.2k
    _rpc__Signal_PowerOn(FALSE);
155
156
14.2k
    _rpc__Signal_NvOn();
157
158
14.2k
    if (ret == TPM_SUCCESS) {
159
14.2k
        if (g_inFailureMode)
160
0
            ret = TPM_RC_FAILURE;
161
14.2k
    }
162
163
14.2k
    if (ret == TPM_SUCCESS && has_cached_state) {
164
7.10k
        NvCommit();
165
7.10k
    }
166
167
14.2k
    return ret;
168
14.2k
}
169
170
static void TPM2_Terminate(void)
171
14.2k
{
172
14.2k
    TPM_TearDown();
173
174
14.2k
    _rpc__Signal_PowerOff();
175
14.2k
    ExpDCacheFree();
176
177
14.2k
    free(g_profile);
178
14.2k
    g_profile = NULL;
179
14.2k
}
180
181
static TPM_RESULT TPM2_Process(unsigned char **respbuffer, uint32_t *resp_size,
182
                               uint32_t *respbufsize,
183
                               unsigned char *command, uint32_t command_size)
184
14.2k
{
185
14.2k
    uint8_t locality = 0;
186
14.2k
    _IN_BUFFER req;
187
14.2k
    _OUT_BUFFER resp;
188
14.2k
    unsigned char *tmp;
189
190
14.2k
#ifdef TPM_LIBTPMS_CALLBACKS
191
14.2k
    struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
192
193
14.2k
    if (cbs->tpm_io_getlocality) {
194
14.2k
        TPM_MODIFIER_INDICATOR locty;
195
196
        /* called function is trusted and must return valid value */
197
14.2k
        cbs->tpm_io_getlocality(&locty, 0);
198
199
14.2k
        locality = locty;
200
14.2k
    }
201
14.2k
#endif /* TPM_LIBTPMS_CALLBACKS */
202
203
14.2k
    req.BufferSize = command_size;
204
14.2k
    req.Buffer = command;
205
206
    /* have the TPM 2 write directly into the response buffer */
207
14.2k
    if (*respbufsize < TPM_BUFFER_MAX || !*respbuffer) {
208
7.10k
        tmp = realloc(*respbuffer, TPM_BUFFER_MAX);
209
7.10k
        if (!tmp) {
210
0
            TPMLIB_LogTPM2Error("Could not allocated %u bytes.\n",
211
0
                                TPM_BUFFER_MAX);
212
0
            return TPM_SIZE;
213
0
        }
214
7.10k
        *respbuffer = tmp;
215
7.10k
        *respbufsize = TPM_BUFFER_MAX;
216
7.10k
    }
217
14.2k
    resp.BufferSize = *respbufsize;
218
14.2k
    resp.Buffer = *respbuffer;
219
220
    /*
221
     * signals for cancellation have to come after we start processing
222
     */
223
14.2k
    _rpc__Signal_CancelOff();
224
225
14.2k
    _rpc__Send_Command(locality, req, &resp);
226
227
    /* it may come back with a different buffer, especially in failure mode */
228
14.2k
    if (resp.Buffer != *respbuffer) {
229
0
        if (resp.BufferSize > *respbufsize)
230
0
            resp.BufferSize = *respbufsize;
231
0
        memcpy(*respbuffer, resp.Buffer, resp.BufferSize);
232
0
    }
233
234
14.2k
    *resp_size = resp.BufferSize;
235
236
14.2k
    if (g_inFailureMode && !reportedFailureCommand) {
237
0
        reportedFailureCommand = TRUE;
238
0
        TPMLIB_LogTPM2Error("%s: Entered failure mode through command:\n",
239
0
                            __func__);
240
0
        TPMLIB_LogArray(~0, command, command_size);
241
0
    }
242
243
14.2k
    return TPM_SUCCESS;
244
14.2k
}
245
246
TPM_RESULT TPM2_PersistentAllStore(unsigned char **buf,
247
                                   uint32_t *buflen)
248
28.6k
{
249
28.6k
    BYTE *buffer;
250
28.6k
    INT32 size;
251
28.6k
    unsigned char *nbuffer;
252
28.6k
    TPM_RESULT ret = TPM_SUCCESS;
253
28.6k
    UINT32 written = 0;
254
255
28.6k
    *buflen = NV_MEMORY_SIZE + 32 * 1024;
256
28.6k
    *buf = NULL;
257
258
    /* the marshal functions do not indicate insufficient
259
       buffer; to make sure we didn't run out of buffer,
260
       we check that enough room for the biggest type of
261
       chunk (64k) is available and try again. */
262
28.6k
    do {
263
28.6k
        *buflen += 66 * 1024;
264
265
28.6k
        nbuffer = realloc(*buf, *buflen);
266
28.6k
        if (nbuffer == NULL) {
267
0
            free(*buf);
268
0
            *buf = NULL;
269
0
            ret = TPM_SIZE;
270
0
            written = 0;
271
0
            break;
272
0
        }
273
274
28.6k
        *buf = buffer = nbuffer;
275
28.6k
        size = *buflen;
276
28.6k
        written = PERSISTENT_ALL_Marshal(&buffer, &size);
277
28.6k
    } while (size < 66 * 1024);
278
279
0
    *buflen = written;
280
281
28.6k
    return ret;
282
28.6k
}
283
284
static TPM_RESULT TPM2_VolatileAllStore(unsigned char **buffer,
285
                                        uint32_t *buflen)
286
7.10k
{
287
7.10k
    TPM_RESULT rc = 0;
288
7.10k
    INT32 size = NV_MEMORY_SIZE;
289
7.10k
    UINT16 written;
290
7.10k
    unsigned char *statebuffer = NULL;
291
292
7.10k
    *buffer = NULL;
293
7.10k
    statebuffer = malloc(size);
294
7.10k
    if (!statebuffer) {
295
0
        TPMLIB_LogTPM2Error("Could not allocate %u bytes.\n", size);
296
0
        return TPM_SIZE;
297
0
    }
298
299
    /* statebuffer will change */
300
7.10k
    *buffer = statebuffer;
301
302
7.10k
    written = VolatileSave(&statebuffer, &size);
303
7.10k
    if (written >= size) {
304
0
        free(*buffer);
305
0
        *buffer = NULL;
306
0
        rc = TPM_FAIL;
307
7.10k
    } else {
308
7.10k
        *buflen = written;
309
7.10k
    }
310
311
7.10k
    return rc;
312
7.10k
}
313
314
static TPM_RESULT TPM2_CancelCommand(void)
315
0
{
316
0
    _rpc__Signal_CancelOn();
317
318
0
    return TPM_SUCCESS;
319
0
}
320
321
static TPM_RESULT TPM2_GetTPMProperty(enum TPMLIB_TPMProperty prop,
322
                                      int *result)
323
0
{
324
0
    switch (prop) {
325
0
    case  TPMPROP_TPM_RSA_KEY_LENGTH_MAX:
326
0
        *result = MAX_RSA_KEY_BITS;
327
0
        break;
328
329
0
    case  TPMPROP_TPM_KEY_HANDLES:
330
0
        *result = MAX_HANDLE_NUM;
331
0
        break;
332
333
    /* not supported for TPM 2 */
334
0
    case  TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES:
335
0
    case  TPMPROP_TPM_MIN_AUTH_SESSIONS:
336
0
    case  TPMPROP_TPM_MIN_TRANS_SESSIONS:
337
0
    case  TPMPROP_TPM_MIN_DAA_SESSIONS:
338
0
    case  TPMPROP_TPM_MIN_SESSION_LIST:
339
0
    case  TPMPROP_TPM_MIN_COUNTERS:
340
0
    case  TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN:
341
0
    case  TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN:
342
0
    case  TPMPROP_TPM_SPACE_SAFETY_MARGIN:
343
0
    case  TPMPROP_TPM_MAX_NV_SPACE:
344
0
    case  TPMPROP_TPM_MAX_SAVESTATE_SPACE:
345
0
    case  TPMPROP_TPM_MAX_VOLATILESTATE_SPACE:
346
347
0
    default:
348
0
        return TPM_FAIL;
349
0
    }
350
351
0
    return TPM_SUCCESS;
352
0
}
353
354
/*
355
 * TPM2_GetInfo:
356
 *
357
 * @flags: logical or of flags that query for information
358
 *
359
 * Return a JSON document with contents queried for by the user's passed flags
360
 */
361
static char *TPM2_GetInfo(enum TPMLIB_InfoFlags flags)
362
0
{
363
0
    const char *tpmspec =
364
0
    "\"TPMSpecification\":{"
365
0
        "\"family\":\"2.0\","
366
0
        "\"level\":" STRINGIFY(TPM_SPEC_LEVEL_NUM) ","
367
0
        "\"revision\":" STRINGIFY(TPM_SPEC_VERSION)
368
0
    "}";
369
0
    const char *tpmattrs_temp =
370
0
    "\"TPMAttributes\":{"
371
0
        "\"manufacturer\":\"id:00001014\","
372
0
        "\"version\":\"id:%08X\","
373
0
        "\"model\":\"swtpm\""
374
0
    "}";
375
0
    const char *tpmfeatures_temp =
376
0
    "\"TPMFeatures\":{"
377
0
        "\"RSAKeySizes\":[%s],"
378
0
        "\"CamelliaKeySizes\":[%s]"
379
#if ALG_SM4
380
        ", \"SM4KeySizes\":[128]"
381
#endif
382
0
    "}";
383
0
    const char *runtimeAlgorithms_temp =
384
0
    "\"RuntimeAlgorithms\":{"
385
0
        "\"Implemented\":%s,"
386
0
        "\"CanBeDisabled\":%s,"
387
0
        "\"Enabled\":%s,"
388
0
        "\"Disabled\":%s"
389
0
    "}";
390
0
    const char *runtimeCommands_temp =
391
0
    "\"RuntimeCommands\":{"
392
0
        "\"Implemented\":%s,"
393
0
        "\"CanBeDisabled\":%s,"
394
0
        "\"Enabled\":%s,"
395
0
        "\"Disabled\":%s"
396
0
    "}";
397
0
    const char *runtimeAttributes_temp =
398
0
    "\"RuntimeAttributes\":{"
399
0
        "\"Implemented\":%s,"
400
0
        "\"CanBeDisabled\":%s,"
401
0
        "\"Enabled\":%s,"
402
0
        "\"Disabled\":%s"
403
0
    "}";
404
0
    const char *tpmProfile_temp = "\"ActiveProfile\":%s";
405
0
    const char *availableProfiles_temp =
406
0
    "\"AvailableProfiles\":["
407
0
        "%s%s%s"
408
0
    "]";
409
0
    char *fmt = NULL, *buffer;
410
0
    bool printed = false;
411
0
    char *tpmattrs = NULL;
412
0
    char *tpmfeatures = NULL;
413
0
    char rsakeys[32];
414
0
    char camelliakeys[16];
415
0
    char *runtimeAlgos[RUNTIME_ALGO_NUM] = { NULL, };
416
0
    char *runtimeCmds[RUNTIME_CMD_NUM] = { NULL, };
417
0
    char *runtimeAttrs[RUNTIME_ATTR_NUM] = { NULL, };
418
0
    enum RuntimeAlgorithmType rat;
419
0
    enum RuntimeCommandType rct;
420
0
    enum RuntimeAttributeType rabt;
421
0
    char *runtimeAlgorithms = NULL;
422
0
    char *runtimeCommands = NULL;
423
0
    char *runtimeAttributes = NULL;
424
0
    char *profile = NULL;
425
0
    const char *profileJSON;
426
0
    char *availableProfiles = NULL;
427
0
    char *tmp = NULL;
428
0
    size_t n;
429
430
0
    if (!(buffer = strdup("{%s%s%s}")))
431
0
        return NULL;
432
433
0
    if ((flags & TPMLIB_INFO_TPMSPECIFICATION)) {
434
0
        fmt = buffer;
435
0
        buffer = NULL;
436
0
        if (TPMLIB_asprintf(&buffer, fmt, "", tpmspec, "%s%s%s") < 0)
437
0
            goto error;
438
0
        free(fmt);
439
0
        printed = true;
440
0
    }
441
442
0
    if ((flags & TPMLIB_INFO_TPMATTRIBUTES)) {
443
0
        uint32_t firmware_v1 = _plat__GetTpmFirmwareVersionHigh();
444
445
0
        fmt = buffer;
446
0
        buffer = NULL;
447
0
        if (TPMLIB_asprintf(&tpmattrs, tpmattrs_temp, firmware_v1) < 0)
448
0
            goto error;
449
0
        if (TPMLIB_asprintf(&buffer, fmt,  printed ? "," : "",
450
0
                             tpmattrs, "%s%s%s") < 0)
451
0
            goto error;
452
0
        free(fmt);
453
0
        printed = true;
454
0
    }
455
456
0
    if ((flags & TPMLIB_INFO_TPMFEATURES)) {
457
0
        fmt = buffer;
458
0
        buffer = NULL;
459
0
        n = snprintf(rsakeys, sizeof(rsakeys), "%s2048%s%s",
460
0
                     RSA_1024 ? "1024," : "",
461
0
                     RSA_3072 ? ",3072" : "",
462
0
                     RSA_4096 ? ",4096" : "");
463
0
        if (n >= sizeof(rsakeys))
464
0
            goto error;
465
0
        n = snprintf(camelliakeys, sizeof(camelliakeys), "%s%s%s",
466
0
                     CAMELLIA_128 ? "128" : "",
467
0
                     CAMELLIA_192 ? ",192" : "",
468
0
                     CAMELLIA_256 ? ",256" : "");
469
0
        if (n >= sizeof(camelliakeys))
470
0
            goto error;
471
0
        if (TPMLIB_asprintf(&tpmfeatures, tpmfeatures_temp,
472
0
                            rsakeys, camelliakeys) < 0)
473
0
            goto error;
474
0
        if (TPMLIB_asprintf(&buffer, fmt,  printed ? "," : "",
475
0
                            tpmfeatures, "%s%s%s") < 0)
476
0
            goto error;
477
0
        free(fmt);
478
0
        printed = true;
479
0
    }
480
481
0
    if ((flags & TPMLIB_INFO_RUNTIME_ALGORITHMS)) {
482
0
        fmt = buffer;
483
0
        buffer = NULL;
484
0
        for (rat = RUNTIME_ALGO_IMPLEMENTED; rat < RUNTIME_ALGO_NUM; rat++) {
485
0
            runtimeAlgos[rat] = RuntimeAlgorithmPrint(&g_RuntimeProfile.RuntimeAlgorithm, rat);
486
0
            if (!runtimeAlgos[rat])
487
0
                goto error;
488
0
        }
489
0
        if (TPMLIB_asprintf(&runtimeAlgorithms, runtimeAlgorithms_temp,
490
0
                            runtimeAlgos[RUNTIME_ALGO_IMPLEMENTED],
491
0
                            runtimeAlgos[RUNTIME_ALGO_CAN_BE_DISABLED],
492
0
                            runtimeAlgos[RUNTIME_ALGO_ENABLED],
493
0
                            runtimeAlgos[RUNTIME_ALGO_DISABLED]) < 0)
494
0
            goto error;
495
0
        if (TPMLIB_asprintf(&buffer, fmt,  printed ? "," : "",
496
0
                            runtimeAlgorithms, "%s%s%s") < 0)
497
0
            goto error;
498
0
        free(fmt);
499
0
        printed = true;
500
0
    }
501
502
0
    if ((flags & TPMLIB_INFO_RUNTIME_COMMANDS)) {
503
0
        fmt = buffer;
504
0
        buffer = NULL;
505
0
        for (rct = RUNTIME_CMD_IMPLEMENTED; rct < RUNTIME_CMD_NUM; rct++) {
506
0
            runtimeCmds[rct] = RuntimeCommandsPrint(&g_RuntimeProfile.RuntimeCommands, rct);
507
0
            if (!runtimeCmds[rct])
508
0
                goto error;
509
0
        }
510
0
        if (TPMLIB_asprintf(&runtimeCommands, runtimeCommands_temp,
511
0
                            runtimeCmds[RUNTIME_CMD_IMPLEMENTED],
512
0
                            runtimeCmds[RUNTIME_CMD_CAN_BE_DISABLED],
513
0
                            runtimeCmds[RUNTIME_CMD_ENABLED],
514
0
                            runtimeCmds[RUNTIME_CMD_DISABLED]) < 0)
515
0
            goto error;
516
0
        if (TPMLIB_asprintf(&buffer, fmt,  printed ? "," : "",
517
0
                            runtimeCommands, "%s%s%s") < 0)
518
0
            goto error;
519
0
        free(fmt);
520
0
        printed = true;
521
0
    }
522
523
0
    if ((flags & TPMLIB_INFO_RUNTIME_ATTRIBUTES)) {
524
0
        fmt = buffer;
525
0
        buffer = NULL;
526
0
        for (rabt = RUNTIME_ATTR_IMPLEMENTED; rabt < RUNTIME_ATTR_NUM; rabt++) {
527
0
            runtimeAttrs[rabt] = RuntimeAttributesGet(&g_RuntimeProfile.RuntimeAttributes, rabt);
528
0
            if (!runtimeAttrs[rabt])
529
0
                goto error;
530
0
        }
531
0
        if (TPMLIB_asprintf(&runtimeAttributes, runtimeAttributes_temp,
532
0
                            runtimeAttrs[RUNTIME_ATTR_IMPLEMENTED],
533
0
                            runtimeAttrs[RUNTIME_ATTR_CAN_BE_DISABLED],
534
0
                            runtimeAttrs[RUNTIME_ATTR_ENABLED],
535
0
                            runtimeAttrs[RUNTIME_ATTR_DISABLED]) < 0)
536
0
            goto error;
537
0
        if (TPMLIB_asprintf(&buffer, fmt,  printed ? "," : "",
538
0
                            runtimeAttributes, "%s%s%s") < 0)
539
0
            goto error;
540
0
        free(fmt);
541
0
        printed = true;
542
0
    }
543
544
0
    if ((flags & TPMLIB_INFO_ACTIVE_PROFILE) &&
545
0
        (profileJSON = RuntimeProfileGetJSON(&g_RuntimeProfile))) {
546
0
        fmt = buffer;
547
0
        buffer = NULL;
548
0
        if (TPMLIB_asprintf(&profile, tpmProfile_temp, profileJSON) < 0)
549
0
            goto error;
550
0
        if (TPMLIB_asprintf(&buffer, fmt, printed ? "," : "",
551
0
                            profile, "%s%s%s") < 0)
552
0
            goto error;
553
0
        free(fmt);
554
0
        printed = true;
555
0
    }
556
557
0
    if ((flags & TPMLIB_INFO_AVAILABLE_PROFILES)) {
558
0
        size_t idx = 0;
559
0
        char *json = NULL;
560
561
0
        fmt = buffer; // keep here in case of 'goto error'
562
0
        buffer = NULL;
563
564
0
        tmp = NULL;
565
566
0
        while (RuntimeProfileGetByIndex(idx, &json) == TPM_RC_SUCCESS) {
567
0
            if (TPMLIB_asprintf(&availableProfiles,
568
0
                                idx > 0 ? tmp : availableProfiles_temp,
569
0
                                idx > 0 ? "," : "",
570
0
                                json,
571
0
                                "%s%s%s") < 0) {
572
0
                free(json);
573
0
                goto error;
574
0
            }
575
576
0
            free(json);
577
0
            free(tmp);
578
0
            tmp = availableProfiles;
579
0
            idx++;
580
0
        }
581
0
        availableProfiles = NULL;
582
0
        if (TPMLIB_asprintf(&availableProfiles, tmp, "", "", "") < 0)
583
0
            goto error;
584
585
0
        if (TPMLIB_asprintf(&buffer, fmt, printed ? "," : "",
586
0
                            availableProfiles, "%s%s%s") < 0)
587
0
            goto error;
588
0
        free(fmt);
589
0
        printed = true;
590
0
    }
591
592
    /* nothing else to add */
593
0
    fmt = buffer;
594
0
    buffer = NULL;
595
0
    if (TPMLIB_asprintf(&buffer, fmt, "", "", "") < 0)
596
0
        goto error;
597
598
0
exit:
599
0
    free(fmt);
600
0
    free(tpmattrs);
601
0
    free(tpmfeatures);
602
0
    free(profile);
603
0
    for (rat = RUNTIME_ALGO_IMPLEMENTED; rat < RUNTIME_ALGO_NUM; rat++)
604
0
        free(runtimeAlgos[rat]);
605
0
    for (rct = RUNTIME_CMD_IMPLEMENTED; rct < RUNTIME_CMD_NUM; rct++)
606
0
        free(runtimeCmds[rct]);
607
0
    for (rabt = RUNTIME_ATTR_IMPLEMENTED; rabt < RUNTIME_ATTR_NUM; rabt++)
608
0
        free(runtimeAttrs[rabt]);
609
0
    free(runtimeAlgorithms);
610
0
    free(runtimeCommands);
611
0
    free(runtimeAttributes);
612
0
    free(availableProfiles);
613
0
    free(tmp);
614
615
0
    return buffer;
616
617
0
error:
618
0
    free(buffer);
619
0
    buffer = NULL;
620
0
    goto exit;
621
0
}
622
623
static uint32_t tpm2_buffersize = TPM_BUFFER_MAX;
624
625
static uint32_t TPM2_SetBufferSize(uint32_t wanted_size,
626
                                   uint32_t *min_size,
627
                                   uint32_t *max_size)
628
14.0k
{
629
14.0k
    const uint32_t min = MAX_CONTEXT_SIZE + 128;
630
14.0k
    const uint32_t max = TPM_BUFFER_MAX;
631
632
14.0k
    if (min_size)
633
0
        *min_size = min;
634
14.0k
    if (max_size)
635
0
        *max_size = max;
636
637
14.0k
    if (wanted_size == 0)
638
14.0k
        return tpm2_buffersize;
639
640
0
    if (wanted_size > max)
641
0
        wanted_size = max;
642
0
    else if (wanted_size < min)
643
0
        wanted_size = min;
644
645
0
    tpm2_buffersize = wanted_size;
646
647
0
    return tpm2_buffersize;
648
14.0k
}
649
650
uint32_t TPM2_GetBufferSize(void)
651
14.0k
{
652
14.0k
    return TPM2_SetBufferSize(0, NULL, NULL);
653
14.0k
}
654
655
/*
656
 * Validate the state blobs to check whether they can be
657
 * successfully used by a TPM_INIT.
658
*/
659
static TPM_RESULT TPM2_ValidateState(enum TPMLIB_StateType st,
660
                                     unsigned int flags LIBTPMS_ATTR_UNUSED)
661
0
{
662
0
    TPM_RESULT ret = TPM_SUCCESS;
663
0
    TPM_RC rc = TPM_RC_SUCCESS;
664
0
    unsigned char *data = NULL;
665
0
    uint32_t length;
666
0
    unsigned char bak_NV[NV_MEMORY_SIZE];
667
0
    INT32 size;
668
0
    BYTE *buffer;
669
0
    BOOL restored;
670
671
    /* make backup of current NvChip memory */
672
0
    memcpy(bak_NV, s_NV, sizeof(bak_NV));
673
674
0
#ifdef TPM_LIBTPMS_CALLBACKS
675
0
    struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
676
677
0
    if (cbs->tpm_nvram_init) {
678
0
        ret = cbs->tpm_nvram_init();
679
0
        if (ret != TPM_SUCCESS)
680
0
            return ret;
681
0
    }
682
683
0
#endif
684
685
0
    if ((rc == TPM_RC_SUCCESS) &&
686
0
        (st & (TPMLIB_STATE_PERMANENT | TPMLIB_STATE_SAVE_STATE))) {
687
688
0
#ifdef TPM_LIBTPMS_CALLBACKS
689
0
        if (cbs->tpm_nvram_loaddata) {
690
0
            ret = cbs->tpm_nvram_loaddata(&data, &length, 0,
691
0
                                          TPM_PERMANENT_ALL_NAME);
692
0
            if (ret != TPM_SUCCESS)
693
0
                return ret;
694
0
        }
695
0
#endif
696
697
0
        if (!data)
698
0
            return TPM_FAIL;
699
700
0
        buffer = data;
701
0
        size = length;
702
0
        rc = PERSISTENT_ALL_Unmarshal(&buffer, &size);
703
0
        free(data);
704
0
    }
705
706
0
    if ((rc == TPM_RC_SUCCESS) &&
707
0
        (st & TPMLIB_STATE_VOLATILE)) {
708
0
        rc = VolatileLoad(&restored);
709
0
    }
710
711
0
    ret = rc;
712
713
0
    return ret;
714
0
}
715
716
/*
717
 * Get the state blob of the given type. If the TPM is not running, we
718
 * get the cached state blobs, if available, otherwise we try to read
719
 * it from files. In case the TPM is running, we get it from the running
720
 * TPM.
721
 */
722
static TPM_RESULT TPM2_GetState(enum TPMLIB_StateType st,
723
                                unsigned char **buffer, uint32_t *buflen)
724
21.3k
{
725
21.3k
    TPM_RESULT ret = TPM_FAIL;
726
727
21.3k
    if (!_rpc__Signal_IsPowerOn()) {
728
7.10k
        struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
729
7.10k
        bool is_empty_buffer;
730
731
7.10k
        ret = CopyCachedState(st, buffer, buflen, &is_empty_buffer);
732
7.10k
        if (ret != TPM_SUCCESS || *buffer != NULL || is_empty_buffer)
733
7.10k
            return ret;
734
735
0
        if (cbs->tpm_nvram_init) {
736
0
            ret = cbs->tpm_nvram_init();
737
0
            if (ret != TPM_SUCCESS)
738
0
                return ret;
739
740
            /* we can call the TPM 1.2 function here ... */
741
0
            ret = TPM_NVRAM_LoadData(buffer, buflen, 0,
742
0
                                     TPMLIB_StateTypeToName(st));
743
0
        } else {
744
0
            ret = TPM_FAIL;
745
0
        }
746
0
        return ret;
747
0
    }
748
749
    /* from the running TPM */
750
14.2k
    switch (st) {
751
7.10k
    case TPMLIB_STATE_PERMANENT:
752
7.10k
        ret = TPM2_PersistentAllStore(buffer, buflen);
753
7.10k
        break;
754
7.10k
    case TPMLIB_STATE_VOLATILE:
755
7.10k
        ret = TPM2_VolatileAllStore(buffer, buflen);
756
7.10k
        break;
757
0
    case TPMLIB_STATE_SAVE_STATE:
758
0
        *buffer = NULL;
759
0
        *buflen = 0;
760
0
        ret = 0;
761
0
        break;
762
14.2k
    }
763
764
14.2k
    return ret;
765
14.2k
}
766
767
/*
768
 * Set the state the TPM 2 will use upon next TPM_MainInit(). The TPM 2
769
 * must not have been started, yet, or it must have been terminated for this
770
 * function to set the state.
771
 *
772
 * @st: The TPMLIB_StateType describing the type of blob in the buffer
773
 * @buffer: pointer to the buffer containing the state blob; NULL pointer clears
774
 *          previous state
775
 * @buflen: length of the buffer
776
 */
777
static TPM_RESULT TPM2_SetState(enum TPMLIB_StateType st,
778
                                const unsigned char *buffer, uint32_t buflen)
779
14.2k
{
780
14.2k
    TPM_RESULT ret = TPM_SUCCESS;
781
14.2k
    TPM_RC rc = TPM_RC_SUCCESS;
782
14.2k
    BYTE *stream = NULL, *orig_stream = NULL;
783
14.2k
    INT32 stream_size = buflen;
784
14.2k
    unsigned char *permanent = NULL, *ptr;
785
14.2k
    INT32 permanent_len;
786
787
14.2k
    if (buffer == NULL) {
788
0
        SetCachedState(st, NULL, 0);
789
0
        return TPM_SUCCESS;
790
0
    }
791
792
14.2k
    if (_rpc__Signal_IsPowerOn())
793
0
        return TPM_INVALID_POSTINIT;
794
795
14.2k
    if (ret == TPM_SUCCESS) {
796
14.2k
        stream = malloc(buflen);
797
14.2k
        if (!stream)
798
0
            ret = TPM_SIZE;
799
14.2k
    }
800
801
14.2k
    if (ret == TPM_SUCCESS) {
802
14.2k
        orig_stream = stream;
803
14.2k
        memcpy(stream, buffer, buflen);
804
14.2k
    }
805
806
    /* test whether we can accept the blob */
807
14.2k
    if (ret == TPM_SUCCESS) {
808
14.2k
        switch (st) {
809
7.10k
        case TPMLIB_STATE_PERMANENT:
810
7.10k
            rc = PERSISTENT_ALL_Unmarshal(&stream, &stream_size);
811
7.10k
            break;
812
7.10k
        case TPMLIB_STATE_VOLATILE:
813
            /* load permanent state first */
814
7.10k
            rc = TPM2_GetState(TPMLIB_STATE_PERMANENT,
815
7.10k
                               &permanent, (uint32_t *)&permanent_len);
816
7.10k
            if (rc == TPM_RC_SUCCESS) {
817
7.10k
                ptr = permanent;
818
7.10k
                rc = PERSISTENT_ALL_Unmarshal(&ptr, &permanent_len);
819
7.10k
                if (rc == TPM_RC_SUCCESS)
820
7.10k
                    rc = VolatileState_Load(&stream, &stream_size);
821
7.10k
            }
822
7.10k
            break;
823
0
        case TPMLIB_STATE_SAVE_STATE:
824
0
            if (buffer != NULL)
825
0
                rc = TPM_BAD_TYPE;
826
0
            break;
827
14.2k
        }
828
14.2k
        ret = rc;
829
14.2k
        if (ret != TPM_SUCCESS)
830
0
            ClearAllCachedState();
831
14.2k
    }
832
833
    /* cache the blob for the TPM_MainInit() to pick it up */
834
14.2k
    if (ret == TPM_SUCCESS) {
835
14.2k
        SetCachedState(st, orig_stream, buflen);
836
14.2k
    } else {
837
0
        free(orig_stream);
838
0
    }
839
14.2k
    free(permanent);
840
841
14.2k
    return ret;
842
14.2k
}
843
844
static TPM_RESULT TPM2_SetProfile(const char *profile)
845
0
{
846
0
    char *copyProfile = NULL;
847
0
    TPM_RC rc;
848
849
0
    if (_rpc__Signal_IsPowerOn())
850
0
        return TPM_INVALID_POSTINIT;
851
852
0
    if (profile) {
853
        /* test the profile */
854
0
        rc = RuntimeProfileTest(&g_RuntimeProfile, profile, true);
855
0
        if (rc != TPM_RC_SUCCESS)
856
0
            return TPM_FAIL;
857
858
0
        copyProfile = strdup(profile);
859
0
        if (!copyProfile)
860
0
            return TPM_SIZE;
861
0
    }
862
863
0
    free(g_profile);
864
0
    g_profile = copyProfile;
865
866
0
    return TPM_SUCCESS;
867
0
}
868
869
static TPM_BOOL TPM2_WasManufactured(void)
870
0
{
871
0
    return g_wasManufactured;
872
0
}
873
874
const struct tpm_interface TPM2Interface = {
875
    .MainInit = TPM2_MainInit,
876
    .Terminate = TPM2_Terminate,
877
    .Process = TPM2_Process,
878
    .VolatileAllStore = TPM2_VolatileAllStore,
879
    .CancelCommand = TPM2_CancelCommand,
880
    .GetTPMProperty = TPM2_GetTPMProperty,
881
    .GetInfo = TPM2_GetInfo,
882
    .TpmEstablishedGet = TPM2_IO_TpmEstablished_Get,
883
    .TpmEstablishedReset = TPM2_IO_TpmEstablished_Reset,
884
    .HashStart = TPM2_IO_Hash_Start,
885
    .HashData = TPM2_IO_Hash_Data,
886
    .HashEnd = TPM2_IO_Hash_End,
887
    .SetBufferSize = TPM2_SetBufferSize,
888
    .ValidateState = TPM2_ValidateState,
889
    .SetState = TPM2_SetState,
890
    .GetState = TPM2_GetState,
891
    .SetProfile = TPM2_SetProfile,
892
    .WasManufactured = TPM2_WasManufactured,
893
};