• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stefanberger / libtpms / #2056

20 Jan 2026 10:12PM UTC coverage: 77.177% (-0.006%) from 77.183%
#2056

push

travis-ci

web-flow
Merge 26872a5bf into c2a8109f8

1063 of 1263 new or added lines in 88 files covered. (84.16%)

1810 existing lines in 64 files now uncovered.

36345 of 47093 relevant lines covered (77.18%)

125599.29 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.75
/src/tpm_tpm2_interface.c
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

48
#include "Tpm.h"
49
#include <TpmTcpProtocol.h>
50
#include <Simulator_fp.h>
51
#include "PlatformData.h"
52
#include "PlatformInternal.h"
53
#include "StateMarshal.h"
54
#include "Volatile.h"
55
#include "ExpDCache_fp.h"
56

57
#define TPM_HAVE_TPM2_DECLARATIONS
58
#include "tpm_nvfile.h" // TPM_NVRAM_Loaddata()
59
#include "tpm_error.h"
60
#include "tpm_library_intern.h"
61
#include "tpm_nvfilename.h"
62

63
static BOOL      reportedFailureCommand;
64
static char     *g_profile;
65
static TPM_BOOL  g_wasManufactured;
66

67
/*
68
 * Check whether the main NVRAM file exists. Return TRUE if it doesn, FALSE otherwise
69
 */
70
static TPM_BOOL _TPM2_CheckNVRAMFileExists(bool *has_nvram_loaddata_callback)
8,357✔
71
{
72
#ifdef TPM_LIBTPMS_CALLBACKS
73
    struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
8,357✔
74
    const char *name = TPM_PERMANENT_ALL_NAME;
8,357✔
75
    unsigned char *data = NULL;
8,357✔
76
    uint32_t length = 0;
8,357✔
77
    uint32_t tpm_number = 0;
8,357✔
78
    TPM_RESULT ret;
8,357✔
79

80
    *has_nvram_loaddata_callback = cbs->tpm_nvram_loaddata != NULL;
8,357✔
81
    if (cbs->tpm_nvram_loaddata) {
8,357✔
82
        ret = cbs->tpm_nvram_loaddata(&data, &length, tpm_number, name);
8,339✔
83
        free(data);
8,339✔
84
        /* a file exists once NOT TPM_RETRY is returned */
85
        if (ret != TPM_RETRY)
8,339✔
86
            return TRUE;
4,195✔
87
    }
88
#else
89
    *has_nvram_loaddata_callback = FALSE;
90
#endif /* TPM_LIBTPMS_CALLBACKS */
91

92
    return FALSE;
93
}
94

95
static TPM_RESULT TPM2_MainInit(void)
8,357✔
96
{
97
    TPM_RESULT ret = TPM_SUCCESS;
8,357✔
98
    bool has_cached_state;
8,357✔
99
    bool has_nvram_file;
8,357✔
100
    bool has_nvram_loaddata_callback;
8,357✔
101

102
    _plat_internal_resetFailureData();
8,357✔
103
    reportedFailureCommand = FALSE;
8,357✔
104
    g_wasManufactured = FALSE;
8,357✔
105

106
#ifdef TPM_LIBTPMS_CALLBACKS
107
    struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
8,357✔
108

109
    if (cbs->tpm_io_init) {
8,357✔
110
        ret = cbs->tpm_io_init();
8,338✔
111
        if (ret != TPM_SUCCESS)
8,338✔
112
            return ret;
113
    }
114

115
    if (cbs->tpm_nvram_init) {
8,357✔
116
        ret = cbs->tpm_nvram_init();
411✔
117
        if (ret != TPM_SUCCESS)
411✔
118
            return ret;
119
    }
120
#endif /* TPM_LIBTPMS_CALLBACKS */
121

122
    _rpc__Signal_PowerOff();
8,357✔
123

124
    has_cached_state = HasCachedState(TPMLIB_STATE_PERMANENT);
8,357✔
125
    has_nvram_file = _TPM2_CheckNVRAMFileExists(&has_nvram_loaddata_callback);
8,357✔
126

127
    if (!has_cached_state) {
8,357✔
128
        if (!has_nvram_file) {
4,379✔
129
            ret = _plat__NVEnable(NULL, 0);
4,157✔
130
            if (ret)
4,157✔
UNCOV
131
                TPMLIB_LogTPM2Error(
×
132
                    "%s: _plat__NVEnable(NULL) failed: %d\n",
133
                    __func__, ret);
134
            if (TPM_Manufacture(TRUE, g_profile) < 0 || _plat__InFailureMode()) {
4,157✔
135
                TPMLIB_LogTPM2Error("%s: TPM_Manufacture(TRUE) failed or TPM in "
1✔
136
                                    "failure mode\n", __func__);
137
                reportedFailureCommand = TRUE;
1✔
138
            } else {
139
                g_wasManufactured = TRUE;
4,156✔
140
            }
141
        }
142
    } else if (!has_nvram_loaddata_callback) {
3,978✔
143
        ret = _plat__NVEnable_NVChipFile(NULL);
2✔
144
        if (ret)
2✔
UNCOV
145
            TPMLIB_LogTPM2Error("%s: _plat__NVEnable_File(NULL) failed: %d\n",
×
146
                                __func__, ret);
147
    }
148

149
    _rpc__Signal_PowerOn(FALSE);
8,357✔
150

151
    _rpc__Signal_NvOn();
8,357✔
152

153
    if (ret == TPM_SUCCESS) {
8,357✔
154
        if (_plat__InFailureMode())
8,357✔
155
            ret = TPM_RC_FAILURE;
16✔
156
    }
157

158
    if (ret == TPM_SUCCESS && has_cached_state) {
8,357✔
159
        NvCommit();
3,978✔
160
    }
161

162
    return ret;
163
}
164

165
static void TPM2_Terminate(void)
8,793✔
166
{
167
    TPM_TearDown();
8,793✔
168

169
    _rpc__Signal_PowerOff();
8,793✔
170
    ExpDCacheFree();
8,793✔
171

172
    free(g_profile);
8,793✔
173
    g_profile = NULL;
8,793✔
174
}
8,793✔
175

176
static TPM_RESULT TPM2_Process(unsigned char **respbuffer, uint32_t *resp_size,
17,800✔
177
                               uint32_t *respbufsize,
178
                               unsigned char *command, uint32_t command_size)
179
{
180
    uint8_t locality = 0;
17,800✔
181
    _IN_BUFFER req;
17,800✔
182
    _OUT_BUFFER resp;
17,800✔
183
    unsigned char *tmp;
17,800✔
184

185
#ifdef TPM_LIBTPMS_CALLBACKS
186
    struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
17,800✔
187

188
    if (cbs->tpm_io_getlocality) {
17,800✔
189
        TPM_MODIFIER_INDICATOR locty;
17,774✔
190

191
        /* called function is trusted and must return valid value */
192
        cbs->tpm_io_getlocality(&locty, 0);
17,774✔
193

194
        locality = locty;
17,774✔
195
    }
196
#endif /* TPM_LIBTPMS_CALLBACKS */
197

198
    req.BufferSize = command_size;
17,800✔
199
    req.Buffer = command;
17,800✔
200

201
    /* have the TPM 2 write directly into the response buffer */
202
    if (*respbufsize < TPM_BUFFER_MAX || !*respbuffer) {
17,800✔
203
        tmp = realloc(*respbuffer, TPM_BUFFER_MAX);
4,477✔
204
        if (!tmp) {
4,477✔
UNCOV
205
            TPMLIB_LogTPM2Error("Could not allocated %u bytes.\n",
×
206
                                TPM_BUFFER_MAX);
UNCOV
207
            return TPM_SIZE;
×
208
        }
209
        *respbuffer = tmp;
4,477✔
210
        *respbufsize = TPM_BUFFER_MAX;
4,477✔
211
    }
212
    resp.BufferSize = *respbufsize;
17,800✔
213
    resp.Buffer = *respbuffer;
17,800✔
214

215
    /*
216
     * signals for cancellation have to come after we start processing
217
     */
218
    _rpc__Signal_CancelOff();
17,800✔
219

220
    _rpc__Send_Command(locality, req, &resp);
17,800✔
221

222
    /* it may come back with a different buffer, especially in failure mode */
223
    if (resp.Buffer != *respbuffer) {
17,800✔
UNCOV
224
        if (resp.BufferSize > *respbufsize)
×
UNCOV
225
            resp.BufferSize = *respbufsize;
×
UNCOV
226
        memcpy(*respbuffer, resp.Buffer, resp.BufferSize);
×
227
    }
228

229
    *resp_size = resp.BufferSize;
17,800✔
230

231
    if (_plat__InFailureMode() && !reportedFailureCommand) {
17,800✔
UNCOV
232
        reportedFailureCommand = TRUE;
×
UNCOV
233
        TPMLIB_LogTPM2Error("%s: Entered failure mode through command:\n",
×
234
                            __func__);
UNCOV
235
        TPMLIB_LogArray(~0, command, command_size);
×
236
    }
237

238
    return TPM_SUCCESS;
239
}
240

241
TPM_RESULT TPM2_PersistentAllStore(unsigned char **buf,
18,870✔
242
                                   uint32_t *buflen)
243
{
244
    BYTE *buffer;
18,870✔
245
    INT32 size;
18,870✔
246
    unsigned char *nbuffer;
18,870✔
247
    TPM_RESULT ret = TPM_SUCCESS;
18,870✔
248
    UINT32 written = 0;
18,870✔
249

250
    *buflen = NV_MEMORY_SIZE + 32 * 1024;
18,870✔
251
    *buf = NULL;
18,870✔
252

253
    /* the marshal functions do not indicate insufficient
254
       buffer; to make sure we didn't run out of buffer,
255
       we check that enough room for the biggest type of
256
       chunk (64k) is available and try again. */
257
    do {
18,870✔
258
        *buflen += 66 * 1024;
18,870✔
259

260
        nbuffer = realloc(*buf, *buflen);
18,870✔
261
        if (nbuffer == NULL) {
18,870✔
UNCOV
262
            free(*buf);
×
UNCOV
263
            *buf = NULL;
×
UNCOV
264
            ret = TPM_SIZE;
×
UNCOV
265
            written = 0;
×
UNCOV
266
            break;
×
267
        }
268

269
        *buf = buffer = nbuffer;
18,870✔
270
        size = *buflen;
18,870✔
271
        written = PERSISTENT_ALL_Marshal(&buffer, &size);
18,870✔
272
    } while (size < 66 * 1024);
18,870✔
273

274
    *buflen = written;
18,870✔
275

276
    return ret;
18,870✔
277
}
278

279
static TPM_RESULT TPM2_VolatileAllStore(unsigned char **buffer,
4,018✔
280
                                        uint32_t *buflen)
281
{
282
    TPM_RESULT rc = 0;
4,018✔
283
    INT32 size = NV_MEMORY_SIZE;
4,018✔
284
    UINT16 written;
4,018✔
285
    unsigned char *statebuffer = NULL;
4,018✔
286

287
    *buffer = NULL;
4,018✔
288
    statebuffer = malloc(size);
4,018✔
289
    if (!statebuffer) {
4,018✔
UNCOV
290
        TPMLIB_LogTPM2Error("Could not allocate %u bytes.\n", size);
×
UNCOV
291
        return TPM_SIZE;
×
292
    }
293

294
    /* statebuffer will change */
295
    *buffer = statebuffer;
4,018✔
296

297
    written = VolatileSave(&statebuffer, &size);
4,018✔
298
    if (written >= size) {
4,018✔
UNCOV
299
        free(*buffer);
×
UNCOV
300
        *buffer = NULL;
×
UNCOV
301
        rc = TPM_FAIL;
×
302
    } else {
303
        *buflen = written;
4,018✔
304
    }
305

306
    return rc;
307
}
308

309
static TPM_RESULT TPM2_CancelCommand(void)
310
{
UNCOV
311
    _rpc__Signal_CancelOn();
×
312

UNCOV
313
    return TPM_SUCCESS;
×
314
}
315

316
static TPM_RESULT TPM2_GetTPMProperty(enum TPMLIB_TPMProperty prop,
317
                                      int *result)
318
{
319
    switch (prop) {
×
320
    case  TPMPROP_TPM_RSA_KEY_LENGTH_MAX:
×
321
        *result = MAX_RSA_KEY_BITS;
×
UNCOV
322
        break;
×
323

UNCOV
324
    case  TPMPROP_TPM_KEY_HANDLES:
×
UNCOV
325
        *result = MAX_HANDLE_NUM;
×
UNCOV
326
        break;
×
327

328
    /* not supported for TPM 2 */
329
    case  TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES:
330
    case  TPMPROP_TPM_MIN_AUTH_SESSIONS:
331
    case  TPMPROP_TPM_MIN_TRANS_SESSIONS:
332
    case  TPMPROP_TPM_MIN_DAA_SESSIONS:
333
    case  TPMPROP_TPM_MIN_SESSION_LIST:
334
    case  TPMPROP_TPM_MIN_COUNTERS:
335
    case  TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN:
336
    case  TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN:
337
    case  TPMPROP_TPM_SPACE_SAFETY_MARGIN:
338
    case  TPMPROP_TPM_MAX_NV_SPACE:
339
    case  TPMPROP_TPM_MAX_SAVESTATE_SPACE:
340
    case  TPMPROP_TPM_MAX_VOLATILESTATE_SPACE:
341

342
    default:
343
        return TPM_FAIL;
344
    }
345

346
    return TPM_SUCCESS;
347
}
348

349
/*
350
 * TPM2_GetInfo:
351
 *
352
 * @flags: logical or of flags that query for information
353
 *
354
 * Return a JSON document with contents queried for by the user's passed flags
355
 */
356
static char *TPM2_GetInfo(enum TPMLIB_InfoFlags flags)
1,920✔
357
{
358
    const char *tpmspec_temp =
1,920✔
359
    "\"TPMSpecification\":{"
360
        "\"family\":\"2.0\","
361
        "\"level\": %u,"
362
        "\"revision\": %u"
363
    "}";
364
    const char *tpmattrs_temp =
1,920✔
365
    "\"TPMAttributes\":{"
366
        "\"manufacturer\":\"id:00001014\","
367
        "\"version\":\"id:%08X\","
368
        "\"model\":\"swtpm\""
369
    "}";
370
    const char *tpmfeatures_temp =
1,920✔
371
    "\"TPMFeatures\":{"
372
        "\"RSAKeySizes\":[%s],"
373
        "\"CamelliaKeySizes\":[%s]"
374
#if ALG_SM4
375
        ", \"SM4KeySizes\":[128]"
376
#endif
377
    "}";
378
    const char *runtimeAlgorithms_temp =
1,920✔
379
    "\"RuntimeAlgorithms\":{"
380
        "\"Implemented\":%s,"
381
        "\"CanBeDisabled\":%s,"
382
        "\"Enabled\":%s,"
383
        "\"Disabled\":%s"
384
    "}";
385
    const char *runtimeCommands_temp =
1,920✔
386
    "\"RuntimeCommands\":{"
387
        "\"Implemented\":%s,"
388
        "\"CanBeDisabled\":%s,"
389
        "\"Enabled\":%s,"
390
        "\"Disabled\":%s"
391
    "}";
392
    const char *runtimeAttributes_temp =
1,920✔
393
    "\"RuntimeAttributes\":{"
394
        "\"Implemented\":%s,"
395
        "\"CanBeDisabled\":%s,"
396
        "\"Enabled\":%s,"
397
        "\"Disabled\":%s"
398
    "}";
399
    const char *tpmProfile_temp = "\"ActiveProfile\":%s";
1,920✔
400
    const char *availableProfiles_temp =
1,920✔
401
    "\"AvailableProfiles\":["
402
        "%s%s%s"
403
    "]";
404
    char *fmt = NULL, *buffer;
1,920✔
405
    bool printed = false;
1,920✔
406
    char *tpmspec = NULL;
1,920✔
407
    char *tpmattrs = NULL;
1,920✔
408
    char *tpmfeatures = NULL;
1,920✔
409
    char rsakeys[32];
1,920✔
410
    char camelliakeys[16];
1,920✔
411
    SPEC_CAPABILITY_VALUE spec_capability_value = {0};
1,920✔
412
    char *runtimeAlgos[RUNTIME_ALGO_NUM] = { NULL, };
1,920✔
413
    char *runtimeCmds[RUNTIME_CMD_NUM] = { NULL, };
1,920✔
414
    char *runtimeAttrs[RUNTIME_ATTR_NUM] = { NULL, };
1,920✔
415
    enum RuntimeAlgorithmType rat;
1,920✔
416
    enum RuntimeCommandType rct;
1,920✔
417
    enum RuntimeAttributeType rabt;
1,920✔
418
    char *runtimeAlgorithms = NULL;
1,920✔
419
    char *runtimeCommands = NULL;
1,920✔
420
    char *runtimeAttributes = NULL;
1,920✔
421
    char *profile = NULL;
1,920✔
422
    const char *profileJSON;
1,920✔
423
    char *availableProfiles = NULL;
1,920✔
424
    char *tmp = NULL;
1,920✔
425
    size_t n;
1,920✔
426

427
    if (!(buffer = strdup("{%s%s%s}")))
1,920✔
428
        return NULL;
429

430
    if ((flags & TPMLIB_INFO_TPMSPECIFICATION)) {
1,920✔
431
        _plat_GetSpecCapabilityValue(&spec_capability_value);
82✔
432

433
        fmt = buffer;
82✔
434
        buffer = NULL;
82✔
435
        if (TPMLIB_asprintf(&tpmspec, tpmspec_temp,
82✔
436
                            spec_capability_value.tpmSpecLevel,
437
                            spec_capability_value.tpmSpecVersion) < 0)
NEW
438
            goto error;
×
439
        if (TPMLIB_asprintf(&buffer, fmt, "", tpmspec, "%s%s%s") < 0)
82✔
UNCOV
440
            goto error;
×
441
        free(fmt);
82✔
442
        printed = true;
82✔
443
    }
444

445
    if ((flags & TPMLIB_INFO_TPMATTRIBUTES)) {
1,920✔
446
        uint32_t firmware_v1 = _plat__GetTpmFirmwareVersionHigh();
78✔
447

448
        fmt = buffer;
78✔
449
        buffer = NULL;
78✔
450
        if (TPMLIB_asprintf(&tpmattrs, tpmattrs_temp, firmware_v1) < 0)
78✔
UNCOV
451
            goto error;
×
452
        if (TPMLIB_asprintf(&buffer, fmt,  printed ? "," : "",
78✔
453
                             tpmattrs, "%s%s%s") < 0)
454
            goto error;
×
455
        free(fmt);
78✔
456
        printed = true;
78✔
457
    }
458

459
    if ((flags & TPMLIB_INFO_TPMFEATURES)) {
1,920✔
460
        fmt = buffer;
229✔
461
        buffer = NULL;
229✔
462
        n = snprintf(rsakeys, sizeof(rsakeys), "%s2048%s%s",
229✔
463
                     RSA_1024 ? "1024," : "",
464
                     RSA_3072 ? ",3072" : "",
465
                     RSA_4096 ? ",4096" : "");
466
        if (n >= sizeof(rsakeys))
229✔
UNCOV
467
            goto error;
×
468
        n = snprintf(camelliakeys, sizeof(camelliakeys), "%s%s%s",
229✔
469
                     CAMELLIA_128 ? "128" : "",
470
                     CAMELLIA_192 ? ",192" : "",
471
                     CAMELLIA_256 ? ",256" : "");
472
        if (n >= sizeof(camelliakeys))
229✔
UNCOV
473
            goto error;
×
474
        if (TPMLIB_asprintf(&tpmfeatures, tpmfeatures_temp,
229✔
475
                            rsakeys, camelliakeys) < 0)
476
            goto error;
×
477
        if (TPMLIB_asprintf(&buffer, fmt,  printed ? "," : "",
458✔
478
                            tpmfeatures, "%s%s%s") < 0)
479
            goto error;
×
480
        free(fmt);
229✔
481
        printed = true;
229✔
482
    }
483

484
    if ((flags & TPMLIB_INFO_RUNTIME_ALGORITHMS)) {
1,920✔
485
        fmt = buffer;
1,026✔
486
        buffer = NULL;
1,026✔
487
        for (rat = RUNTIME_ALGO_IMPLEMENTED; rat < RUNTIME_ALGO_NUM; rat++) {
5,130✔
488
            runtimeAlgos[rat] = RuntimeAlgorithmPrint(&g_RuntimeProfile.RuntimeAlgorithm, rat);
4,104✔
489
            if (!runtimeAlgos[rat])
4,104✔
UNCOV
490
                goto error;
×
491
        }
492
        if (TPMLIB_asprintf(&runtimeAlgorithms, runtimeAlgorithms_temp,
1,026✔
493
                            runtimeAlgos[RUNTIME_ALGO_IMPLEMENTED],
494
                            runtimeAlgos[RUNTIME_ALGO_CAN_BE_DISABLED],
495
                            runtimeAlgos[RUNTIME_ALGO_ENABLED],
496
                            runtimeAlgos[RUNTIME_ALGO_DISABLED]) < 0)
UNCOV
497
            goto error;
×
498
        if (TPMLIB_asprintf(&buffer, fmt,  printed ? "," : "",
2,052✔
499
                            runtimeAlgorithms, "%s%s%s") < 0)
500
            goto error;
×
501
        free(fmt);
1,026✔
502
        printed = true;
1,026✔
503
    }
504

505
    if ((flags & TPMLIB_INFO_RUNTIME_COMMANDS)) {
1,920✔
506
        fmt = buffer;
229✔
507
        buffer = NULL;
229✔
508
        for (rct = RUNTIME_CMD_IMPLEMENTED; rct < RUNTIME_CMD_NUM; rct++) {
1,145✔
509
            runtimeCmds[rct] = RuntimeCommandsPrint(&g_RuntimeProfile.RuntimeCommands, rct);
916✔
510
            if (!runtimeCmds[rct])
916✔
UNCOV
511
                goto error;
×
512
        }
513
        if (TPMLIB_asprintf(&runtimeCommands, runtimeCommands_temp,
229✔
514
                            runtimeCmds[RUNTIME_CMD_IMPLEMENTED],
515
                            runtimeCmds[RUNTIME_CMD_CAN_BE_DISABLED],
516
                            runtimeCmds[RUNTIME_CMD_ENABLED],
517
                            runtimeCmds[RUNTIME_CMD_DISABLED]) < 0)
UNCOV
518
            goto error;
×
519
        if (TPMLIB_asprintf(&buffer, fmt,  printed ? "," : "",
229✔
520
                            runtimeCommands, "%s%s%s") < 0)
521
            goto error;
×
522
        free(fmt);
229✔
523
        printed = true;
229✔
524
    }
525

526
    if ((flags & TPMLIB_INFO_RUNTIME_ATTRIBUTES)) {
1,920✔
527
        fmt = buffer;
390✔
528
        buffer = NULL;
390✔
529
        for (rabt = RUNTIME_ATTR_IMPLEMENTED; rabt < RUNTIME_ATTR_NUM; rabt++) {
1,950✔
530
            runtimeAttrs[rabt] = RuntimeAttributesGet(&g_RuntimeProfile.RuntimeAttributes, rabt);
1,560✔
531
            if (!runtimeAttrs[rabt])
1,560✔
UNCOV
532
                goto error;
×
533
        }
534
        if (TPMLIB_asprintf(&runtimeAttributes, runtimeAttributes_temp,
390✔
535
                            runtimeAttrs[RUNTIME_ATTR_IMPLEMENTED],
536
                            runtimeAttrs[RUNTIME_ATTR_CAN_BE_DISABLED],
537
                            runtimeAttrs[RUNTIME_ATTR_ENABLED],
538
                            runtimeAttrs[RUNTIME_ATTR_DISABLED]) < 0)
UNCOV
539
            goto error;
×
540
        if (TPMLIB_asprintf(&buffer, fmt,  printed ? "," : "",
780✔
541
                            runtimeAttributes, "%s%s%s") < 0)
542
            goto error;
×
543
        free(fmt);
390✔
544
        printed = true;
390✔
545
    }
546

547
    if ((flags & TPMLIB_INFO_ACTIVE_PROFILE) &&
1,920✔
548
        (profileJSON = RuntimeProfileGetJSON(&g_RuntimeProfile))) {
186✔
549
        fmt = buffer;
186✔
550
        buffer = NULL;
186✔
551
        if (TPMLIB_asprintf(&profile, tpmProfile_temp, profileJSON) < 0)
186✔
UNCOV
552
            goto error;
×
553
        if (TPMLIB_asprintf(&buffer, fmt, printed ? "," : "",
372✔
554
                            profile, "%s%s%s") < 0)
555
            goto error;
×
556
        free(fmt);
186✔
557
        printed = true;
186✔
558
    }
559

560
    if ((flags & TPMLIB_INFO_AVAILABLE_PROFILES)) {
1,920✔
561
        size_t idx = 0;
236✔
562
        char *json = NULL;
236✔
563

564
        fmt = buffer; // keep here in case of 'goto error'
236✔
565
        buffer = NULL;
236✔
566

567
        tmp = NULL;
236✔
568

569
        while (RuntimeProfileGetByIndex(idx, &json) == TPM_RC_SUCCESS) {
1,180✔
570
            if (TPMLIB_asprintf(&availableProfiles,
1,416✔
571
                                idx > 0 ? tmp : availableProfiles_temp,
572
                                idx > 0 ? "," : "",
573
                                json,
574
                                "%s%s%s") < 0) {
UNCOV
575
                free(json);
×
UNCOV
576
                goto error;
×
577
            }
578

579
            free(json);
944✔
580
            free(tmp);
944✔
581
            tmp = availableProfiles;
944✔
582
            idx++;
944✔
583
        }
584
        availableProfiles = NULL;
236✔
585
        if (TPMLIB_asprintf(&availableProfiles, tmp, "", "", "") < 0)
236✔
UNCOV
586
            goto error;
×
587

588
        if (TPMLIB_asprintf(&buffer, fmt, printed ? "," : "",
243✔
589
                            availableProfiles, "%s%s%s") < 0)
UNCOV
590
            goto error;
×
591
        free(fmt);
236✔
592
        printed = true;
236✔
593
    }
594

595
    /* nothing else to add */
596
    fmt = buffer;
1,920✔
597
    buffer = NULL;
1,920✔
598
    if (TPMLIB_asprintf(&buffer, fmt, "", "", "") < 0)
1,920✔
UNCOV
599
        goto error;
×
600

601
exit:
1,920✔
602
    free(fmt);
1,920✔
603
    free(tpmspec);
1,920✔
604
    free(tpmattrs);
1,920✔
605
    free(tpmfeatures);
1,920✔
606
    free(profile);
1,920✔
607
    for (rat = RUNTIME_ALGO_IMPLEMENTED; rat < RUNTIME_ALGO_NUM; rat++)
9,600✔
608
        free(runtimeAlgos[rat]);
7,680✔
609
    for (rct = RUNTIME_CMD_IMPLEMENTED; rct < RUNTIME_CMD_NUM; rct++)
9,600✔
610
        free(runtimeCmds[rct]);
7,680✔
611
    for (rabt = RUNTIME_ATTR_IMPLEMENTED; rabt < RUNTIME_ATTR_NUM; rabt++)
9,600✔
612
        free(runtimeAttrs[rabt]);
7,680✔
613
    free(runtimeAlgorithms);
1,920✔
614
    free(runtimeCommands);
1,920✔
615
    free(runtimeAttributes);
1,920✔
616
    free(availableProfiles);
1,920✔
617
    free(tmp);
1,920✔
618

619
    return buffer;
1,920✔
620

UNCOV
621
error:
×
UNCOV
622
    free(buffer);
×
UNCOV
623
    buffer = NULL;
×
UNCOV
624
    goto exit;
×
625
}
626

627
static uint32_t tpm2_buffersize = TPM_BUFFER_MAX;
628

629
static uint32_t TPM2_SetBufferSize(uint32_t wanted_size,
17,978✔
630
                                   uint32_t *min_size,
631
                                   uint32_t *max_size)
632
{
633
    const uint32_t min = MAX_CONTEXT_SIZE + 128;
17,978✔
634
    const uint32_t max = TPM_BUFFER_MAX;
17,978✔
635

636
    if (min_size)
7✔
637
        *min_size = min;
6✔
638
    if (max_size)
7✔
639
        *max_size = max;
6✔
640

641
    if (wanted_size == 0)
7✔
642
        return tpm2_buffersize;
4✔
643

644
    if (wanted_size > max)
3✔
645
        wanted_size = max;
646
    else if (wanted_size < min)
647
        wanted_size = min;
648

649
    tpm2_buffersize = wanted_size;
3✔
650

651
    return tpm2_buffersize;
3✔
652
}
653

654
uint32_t TPM2_GetBufferSize(void)
17,971✔
655
{
656
    return TPM2_SetBufferSize(0, NULL, NULL);
17,971✔
657
}
658

659
/*
660
 * Validate the state blobs to check whether they can be
661
 * successfully used by a TPM_INIT.
662
*/
663
static TPM_RESULT TPM2_ValidateState(enum TPMLIB_StateType st,
664
                                     unsigned int flags LIBTPMS_ATTR_UNUSED)
665
{
UNCOV
666
    TPM_RESULT ret = TPM_SUCCESS;
×
UNCOV
667
    TPM_RC rc = TPM_RC_SUCCESS;
×
UNCOV
668
    unsigned char *data = NULL;
×
UNCOV
669
    uint32_t length;
×
670
    unsigned char bak_NV[NV_MEMORY_SIZE];
×
671
    INT32 size;
×
672
    BYTE *buffer;
×
673
    BOOL restored;
×
674

675
    /* make backup of current NvChip memory */
676
    memcpy(bak_NV, s_NV, sizeof(bak_NV));
×
677

678
#ifdef TPM_LIBTPMS_CALLBACKS
UNCOV
679
    struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
×
680

UNCOV
681
    if (cbs->tpm_nvram_init) {
×
UNCOV
682
        ret = cbs->tpm_nvram_init();
×
683
        if (ret != TPM_SUCCESS)
×
684
            return ret;
685
    }
686

687
#endif
688

UNCOV
689
    if ((rc == TPM_RC_SUCCESS) &&
×
UNCOV
690
        (st & (TPMLIB_STATE_PERMANENT | TPMLIB_STATE_SAVE_STATE))) {
×
691

692
#ifdef TPM_LIBTPMS_CALLBACKS
693
        if (cbs->tpm_nvram_loaddata) {
×
694
            ret = cbs->tpm_nvram_loaddata(&data, &length, 0,
×
695
                                          TPM_PERMANENT_ALL_NAME);
UNCOV
696
            if (ret != TPM_SUCCESS)
×
697
                return ret;
698
        }
699
#endif
700

UNCOV
701
        if (!data)
×
702
            return TPM_FAIL;
703

UNCOV
704
        buffer = data;
×
705
        size = length;
×
UNCOV
706
        rc = PERSISTENT_ALL_Unmarshal(&buffer, &size);
×
UNCOV
707
        free(data);
×
708
    }
709

710
    if ((rc == TPM_RC_SUCCESS) &&
×
711
        (st & TPMLIB_STATE_VOLATILE)) {
×
UNCOV
712
        rc = VolatileLoad(&restored);
×
713
    }
714

715
    ret = rc;
×
716

717
    return ret;
718
}
719

720
/*
721
 * Get the state blob of the given type. If the TPM is not running, we
722
 * get the cached state blobs, if available, otherwise we try to read
723
 * it from files. In case the TPM is running, we get it from the running
724
 * TPM.
725
 */
726
static TPM_RESULT TPM2_GetState(enum TPMLIB_StateType st,
11,917✔
727
                                unsigned char **buffer, uint32_t *buflen)
728
{
729
    TPM_RESULT ret = TPM_FAIL;
11,917✔
730

731
    if (!_rpc__Signal_IsPowerOn()) {
11,917✔
732
        struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
3,985✔
733
        bool is_empty_buffer;
3,985✔
734

735
        ret = CopyCachedState(st, buffer, buflen, &is_empty_buffer);
3,985✔
736
        if (ret != TPM_SUCCESS || *buffer != NULL || is_empty_buffer)
3,985✔
737
            return ret;
738

739
        if (cbs->tpm_nvram_init) {
7✔
740
            ret = cbs->tpm_nvram_init();
7✔
741
            if (ret != TPM_SUCCESS)
7✔
742
                return ret;
743

744
            /* we can call the TPM 1.2 function here ... */
745
            ret = TPM_NVRAM_LoadData(buffer, buflen, 0,
7✔
746
                                     TPMLIB_StateTypeToName(st));
747
        } else {
748
            ret = TPM_FAIL;
749
        }
750
        return ret;
7✔
751
    }
752

753
    /* from the running TPM */
754
    switch (st) {
7,932✔
755
    case TPMLIB_STATE_PERMANENT:
3,966✔
756
        ret = TPM2_PersistentAllStore(buffer, buflen);
3,966✔
757
        break;
3,966✔
758
    case TPMLIB_STATE_VOLATILE:
3,966✔
759
        ret = TPM2_VolatileAllStore(buffer, buflen);
3,966✔
760
        break;
3,966✔
UNCOV
761
    case TPMLIB_STATE_SAVE_STATE:
×
UNCOV
762
        *buffer = NULL;
×
UNCOV
763
        *buflen = 0;
×
UNCOV
764
        ret = 0;
×
765
        break;
×
766
    }
767

768
    return ret;
769
}
770

771
/*
772
 * Set the state the TPM 2 will use upon next TPM_MainInit(). The TPM 2
773
 * must not have been started, yet, or it must have been terminated for this
774
 * function to set the state.
775
 *
776
 * @st: The TPMLIB_StateType describing the type of blob in the buffer
777
 * @buffer: pointer to the buffer containing the state blob; NULL pointer clears
778
 *          previous state
779
 * @buflen: length of the buffer
780
 */
781
static TPM_RESULT TPM2_SetState(enum TPMLIB_StateType st,
7,963✔
782
                                const unsigned char *buffer, uint32_t buflen)
783
{
784
    TPM_RESULT ret = TPM_SUCCESS;
7,963✔
785
    TPM_RC rc = TPM_RC_SUCCESS;
7,963✔
786
    BYTE *stream = NULL, *orig_stream = NULL;
7,963✔
787
    INT32 stream_size = buflen;
7,963✔
788
    unsigned char *permanent = NULL, *ptr;
7,963✔
789
    INT32 permanent_len;
7,963✔
790

791
    if (buffer == NULL) {
7,963✔
UNCOV
792
        SetCachedState(st, NULL, 0);
×
UNCOV
793
        return TPM_SUCCESS;
×
794
    }
795

796
    if (_rpc__Signal_IsPowerOn())
7,963✔
797
        return TPM_INVALID_POSTINIT;
798

799
    if (ret == TPM_SUCCESS) {
7,963✔
800
        stream = malloc(buflen);
7,963✔
801
        if (!stream)
7,963✔
802
            ret = TPM_SIZE;
803
    }
804

805
    if (ret == TPM_SUCCESS) {
7,963✔
806
        orig_stream = stream;
7,963✔
807
        memcpy(stream, buffer, buflen);
7,963✔
808
    }
809

810
    /* test whether we can accept the blob */
811
    if (ret == TPM_SUCCESS) {
7,963✔
812
        switch (st) {
7,963✔
813
        case TPMLIB_STATE_PERMANENT:
3,978✔
814
            rc = PERSISTENT_ALL_Unmarshal(&stream, &stream_size);
3,978✔
815
            break;
3,978✔
816
        case TPMLIB_STATE_VOLATILE:
3,985✔
817
            /* load permanent state first */
818
            rc = TPM2_GetState(TPMLIB_STATE_PERMANENT,
3,985✔
819
                               &permanent, (uint32_t *)&permanent_len);
820
            if (rc == TPM_RC_SUCCESS) {
3,985✔
821
                ptr = permanent;
3,985✔
822
                rc = PERSISTENT_ALL_Unmarshal(&ptr, &permanent_len);
3,985✔
823
                if (rc == TPM_RC_SUCCESS)
3,985✔
824
                    rc = VolatileState_Load(&stream, &stream_size);
3,985✔
825
            }
826
            break;
827
        case TPMLIB_STATE_SAVE_STATE:
828
            if (buffer != NULL)
829
                rc = TPM_BAD_TYPE;
830
            break;
831
        }
832
        ret = rc;
7,963✔
833
        if (ret != TPM_SUCCESS)
7,963✔
UNCOV
834
            ClearAllCachedState();
×
835
    }
836

837
    /* cache the blob for the TPM_MainInit() to pick it up */
838
    if (ret == TPM_SUCCESS) {
7,963✔
839
        SetCachedState(st, orig_stream, buflen);
7,963✔
840
    } else {
UNCOV
841
        free(orig_stream);
×
842
    }
843
    free(permanent);
7,963✔
844

845
    return ret;
7,963✔
846
}
847

848
static TPM_RESULT TPM2_SetProfile(const char *profile)
105✔
849
{
850
    char *copyProfile = NULL;
105✔
851
    TPM_RC rc;
105✔
852

853
    if (_rpc__Signal_IsPowerOn())
105✔
854
        return TPM_INVALID_POSTINIT;
855

856
    if (profile) {
105✔
857
        /* test the profile */
858
        rc = RuntimeProfileTest(&g_RuntimeProfile, profile, true);
104✔
859
        if (rc != TPM_RC_SUCCESS)
104✔
860
            return TPM_FAIL;
861

862
        copyProfile = strdup(profile);
94✔
863
        if (!copyProfile)
94✔
864
            return TPM_SIZE;
865
    }
866

867
    free(g_profile);
95✔
868
    g_profile = copyProfile;
95✔
869

870
    return TPM_SUCCESS;
95✔
871
}
872

873
static TPM_BOOL TPM2_WasManufactured(void)
84✔
874
{
875
    return g_wasManufactured;
84✔
876
}
877

878
const struct tpm_interface TPM2Interface = {
879
    .MainInit = TPM2_MainInit,
880
    .Terminate = TPM2_Terminate,
881
    .Process = TPM2_Process,
882
    .VolatileAllStore = TPM2_VolatileAllStore,
883
    .CancelCommand = TPM2_CancelCommand,
884
    .GetTPMProperty = TPM2_GetTPMProperty,
885
    .GetInfo = TPM2_GetInfo,
886
    .TpmEstablishedGet = TPM2_IO_TpmEstablished_Get,
887
    .TpmEstablishedReset = TPM2_IO_TpmEstablished_Reset,
888
    .HashStart = TPM2_IO_Hash_Start,
889
    .HashData = TPM2_IO_Hash_Data,
890
    .HashEnd = TPM2_IO_Hash_End,
891
    .SetBufferSize = TPM2_SetBufferSize,
892
    .ValidateState = TPM2_ValidateState,
893
    .SetState = TPM2_SetState,
894
    .GetState = TPM2_GetState,
895
    .SetProfile = TPM2_SetProfile,
896
    .WasManufactured = TPM2_WasManufactured,
897
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc