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

stefanberger / libtpms / 2698

pending completion
2698

Pull #353

travis-ci-com

web-flow
Merge a8cae3f5d into d08b929de
Pull Request #353: Travis: Update from bionic to focal and from xenial to bionic

33875 of 43923 relevant lines covered (77.12%)

93992.6 hits per line

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

45.5
/src/tpm_tpm12_interface.c
1
/********************************************************************************/
2
/*                                                                                */
3
/*                        LibTPM TPM 1.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
#define _GNU_SOURCE
42
#include <assert.h>
43
#include <stdio.h>
44
#include <stdlib.h>
45
#include <string.h>
46
#include <stdbool.h>
47

48
#include "tpm_debug.h"
49
#include "tpm_error.h"
50
#include "tpm12/tpm_init.h"
51
#include "tpm_library_intern.h"
52
#include "tpm12/tpm_process.h"
53
#include "tpm12/tpm_startup.h"
54
#include "tpm12/tpm_global.h"
55
#include "tpm12/tpm_permanent.h"
56
#include "tpm_nvfile.h"
57

58
static TPM_RESULT TPM12_MainInit(void)
135✔
59
{
60
    return TPM_MainInit();
135✔
61
}
62

63
static void TPM12_Terminate(void)
337✔
64
{
65
    TPM_Global_Delete(tpm_instances[0]);
337✔
66
    free(tpm_instances[0]);
337✔
67
    tpm_instances[0] = NULL;
337✔
68
}
337✔
69

70
static TPM_RESULT TPM12_Process(unsigned char **respbuffer, uint32_t *resp_size,
12,131✔
71
                                uint32_t *respbufsize,
72
                                unsigned char *command, uint32_t command_size)
73
{
74
    *resp_size = 0;
12,131✔
75
    return TPM_ProcessA(respbuffer, resp_size, respbufsize,
12,131✔
76
                        command, command_size);
77
}
78

79
static TPM_RESULT TPM12_VolatileAllStore(unsigned char **buffer,
44✔
80
                                         uint32_t *buflen)
81
{
82
    TPM_RESULT rc;
44✔
83
    TPM_STORE_BUFFER tsb;
44✔
84
    TPM_Sbuffer_Init(&tsb);
44✔
85
    uint32_t total;
44✔
86

87
#ifdef TPM_DEBUG
88
    assert(tpm_instances[0] != NULL);
89
#endif
90

91
    rc = TPM_VolatileAll_Store(&tsb, tpm_instances[0]);
44✔
92

93
    if (rc == TPM_SUCCESS) {
44✔
94
        /* caller now owns the buffer and needs to free it */
95
        TPM_Sbuffer_GetAll(&tsb, buffer, buflen, &total);
44✔
96
    } else {
97
        TPM_Sbuffer_Delete(&tsb);
×
98
        *buflen = 0;
×
99
        *buffer = NULL;
×
100
    }
101

102
    return rc;
44✔
103
}
104

105
static TPM_RESULT TPM12_CancelCommand(void)
106
{
107
    return TPM_FAIL; /* not supported */
×
108
}
109

110

111
static TPM_RESULT TPM12_GetTPMProperty(enum TPMLIB_TPMProperty prop,
112
                                int *result)
113
{
114
    switch (prop) {
×
115
    case  TPMPROP_TPM_RSA_KEY_LENGTH_MAX:
×
116
        *result = TPM_RSA_KEY_LENGTH_MAX;
×
117
        break;
×
118

119
    case  TPMPROP_TPM_KEY_HANDLES:
×
120
        *result = TPM_KEY_HANDLES;
×
121
        break;
×
122

123
    case  TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES:
×
124
        *result = TPM_OWNER_EVICT_KEY_HANDLES;
×
125
        break;
×
126

127
    case  TPMPROP_TPM_MIN_AUTH_SESSIONS:
×
128
        *result = TPM_MIN_AUTH_SESSIONS;
×
129
        break;
×
130

131
    case  TPMPROP_TPM_MIN_TRANS_SESSIONS:
×
132
        *result = TPM_MIN_TRANS_SESSIONS;
×
133
        break;
×
134

135
    case  TPMPROP_TPM_MIN_DAA_SESSIONS:
×
136
        *result = TPM_MIN_DAA_SESSIONS;
×
137
        break;
×
138

139
    case  TPMPROP_TPM_MIN_SESSION_LIST:
×
140
        *result = TPM_MIN_SESSION_LIST;
×
141
        break;
×
142

143
    case  TPMPROP_TPM_MIN_COUNTERS:
×
144
        *result = TPM_MIN_COUNTERS;
×
145
        break;
×
146

147
    case  TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN:
×
148
        *result = TPM_NUM_FAMILY_TABLE_ENTRY_MIN;
×
149
        break;
×
150

151
    case  TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN:
×
152
        *result = TPM_NUM_DELEGATE_TABLE_ENTRY_MIN;
×
153
        break;
×
154

155
    case  TPMPROP_TPM_SPACE_SAFETY_MARGIN:
×
156
        *result = TPM_SPACE_SAFETY_MARGIN;
×
157
        break;
×
158

159
    case  TPMPROP_TPM_MAX_NV_SPACE:
×
160
        /* fill up 20 kb.; this provides some safety margin (currently
161
           >4Kb) for possible future expansion of this blob */
162
        *result = ROUNDUP(TPM_MAX_NV_SPACE, 20 * 1024);
×
163
        break;
×
164

165
    case  TPMPROP_TPM_MAX_SAVESTATE_SPACE:
×
166
        *result = TPM_MAX_SAVESTATE_SPACE;
×
167
        break;
×
168

169
    case  TPMPROP_TPM_MAX_VOLATILESTATE_SPACE:
×
170
        *result = TPM_MAX_VOLATILESTATE_SPACE;
×
171
        break;
×
172

173
    default:
174
        return TPM_FAIL;
175
    }
176

177
    return TPM_SUCCESS;
178
}
179

180
/*
181
 * TPM12_GetInfo:
182
 *
183
 * @flags: logical or of flags that query for information
184
 *
185
 * Return a JSON document with contents queried for by the user's passed flags
186
 */
187
static char *TPM12_GetInfo(enum TPMLIB_InfoFlags flags)
159✔
188
{
189
    const char *tpmspec =
159✔
190
    "\"TPMSpecification\":{"
191
        "\"family\":\"1.2\","
192
        "\"level\":2,"
193
        "\"revision\":116"
194
    "}";
195
    const char *tpmattrs =
159✔
196
    "\"TPMAttributes\":{"
197
        "\"manufacturer\":\"id:00001014\","
198
        "\"version\":\"id:00740001\"," /* 146.1 */
199
        "\"model\":\"swtpm\""
200
    "}";
201
    char *fmt = NULL, *buffer;
159✔
202
    bool printed = false;
159✔
203

204
    if (!(buffer = strdup("{%s%s%s}")))
159✔
205
        return NULL;
206

207
    if ((flags & TPMLIB_INFO_TPMSPECIFICATION)) {
159✔
208
        fmt = buffer;
8✔
209
        buffer = NULL;
8✔
210
        if (asprintf(&buffer, fmt, "", tpmspec, "%s%s%s") < 0)
8✔
211
            goto error;
×
212
        free(fmt);
8✔
213
        printed = true;
8✔
214
    }
215
    if ((flags & TPMLIB_INFO_TPMATTRIBUTES)) {
159✔
216
        fmt = buffer;
8✔
217
        buffer = NULL;
8✔
218
        if (asprintf(&buffer, fmt,  printed ? "," : "",
16✔
219
                     tpmattrs, "%s%s%s") < 0)
220
            goto error;
×
221
        free(fmt);
8✔
222
        printed = true;
8✔
223
    }
224

225
    /* nothing else to add */
226
    fmt = buffer;
159✔
227
    buffer = NULL;
159✔
228
    if (asprintf(&buffer, fmt, "", "", "") < 0)
159✔
229
        goto error;
×
230
    free(fmt);
159✔
231

232
    return buffer;
159✔
233

234
error:
×
235
    free(fmt);
×
236
    free(buffer);
×
237

238
    return NULL;
×
239
}
240

241
static uint32_t tpm12_buffersize = TPM_BUFFER_MAX;
242

243
static uint32_t TPM12_SetBufferSize(uint32_t wanted_size,
12,172✔
244
                                    uint32_t *min_size,
245
                                    uint32_t *max_size)
246
{
247
    if (min_size)
6✔
248
        *min_size = TPM_BUFFER_MIN;
6✔
249
    if (max_size)
6✔
250
        *max_size = TPM_BUFFER_MAX;
6✔
251

252
    if (wanted_size == 0)
6✔
253
        return tpm12_buffersize;
3✔
254

255
    if (wanted_size > TPM_BUFFER_MAX)
3✔
256
        wanted_size = TPM_BUFFER_MAX;
257
    else if (wanted_size < TPM_BUFFER_MIN)
258
        wanted_size = TPM_BUFFER_MIN;
259

260
    tpm12_buffersize = wanted_size;
3✔
261

262
    return tpm12_buffersize;
3✔
263
}
264

265
uint32_t TPM12_GetBufferSize(void)
12,166✔
266
{
267
    return TPM12_SetBufferSize(0, NULL, NULL);
12,166✔
268
}
269

270
static TPM_RESULT TPM12_ValidateState(enum TPMLIB_StateType st,
271
                                      unsigned int flags)
272
{
273
    TPM_RESULT ret = TPM_SUCCESS;
×
274
    tpm_state_t tpm_state;
×
275
    enum TPMLIB_StateType sts[] = {
×
276
        TPMLIB_STATE_PERMANENT,
277
        TPMLIB_STATE_VOLATILE,
278
        TPMLIB_STATE_SAVE_STATE,
279
        0,
280
    };
281
    enum TPMLIB_StateType c_st;
×
282
    unsigned i;
×
283

284
#ifdef TPM_LIBTPMS_CALLBACKS
285
    struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
×
286

287
    if (cbs->tpm_nvram_init) {
×
288
        ret = cbs->tpm_nvram_init();
×
289
        if (ret != TPM_SUCCESS)
×
290
            return ret;
291
    }
292
#endif
293

294
    ret = TPM_Global_Init(&tpm_state);
×
295
    tpm_state.tpm_number = 0;
×
296

297
    if (ret == TPM_SUCCESS) {
×
298
        /* permanent state needs to be there and loaded first */
299
        ret = TPM_PermanentAll_NVLoad(&tpm_state);
×
300
    }
301

302
    for (i = 0; sts[i] && ret == TPM_SUCCESS; i++) {
×
303
        c_st = st & sts[i];
×
304

305
        /* 'cached' state is known to 'work', so skip it */
306
        if (!c_st || HasCachedState(c_st))
×
307
            continue;
×
308

309
        switch (c_st) {
×
310
        case TPMLIB_STATE_PERMANENT:
311
            break;
312
        case TPMLIB_STATE_VOLATILE:
×
313
            ret = TPM_VolatileAll_NVLoad(&tpm_state);
×
314
            break;
×
315
        case TPMLIB_STATE_SAVE_STATE:
×
316
            ret = TPM_SaveState_NVLoad(&tpm_state);
×
317
            break;
×
318
        }
319
    }
320

321
    TPM_Global_Delete(&tpm_state);
×
322

323
    return ret;
×
324
}
325

326
static TPM_RESULT _TPM_PermanentAll_Store(TPM_STORE_BUFFER *sbuffer,
327
                                          tpm_state_t *tpm_state)
328
{
329
    const unsigned char *buffer = NULL;
×
330
    uint32_t buflen;
×
331

332
    return TPM_PermanentAll_Store(sbuffer, &buffer, &buflen, tpm_state);
×
333
}
334

335
/*
336
 * TPM_PermanentAll_NVLoad_Preserve
337
 *
338
 * @tpm_state: The tpm_state to load the permanent state into
339
 *
340
 * Call TPM_PermanentAll_NVLoad and preserve any cached data that a call
341
 * to TPM_PermanentAll_NVLoad (TPM_NVRAM_LoadData) may otherwise consume
342
 * and remove if it was available.
343
 */
344
static TPM_RESULT TPM_PermanentAll_NVLoad_Preserve(tpm_state_t *tpm_state)
19✔
345
{
346
    TPM_RESULT ret;
19✔
347
    unsigned char *buffer = NULL;
19✔
348
    uint32_t buffer_len;
19✔
349
    bool is_empty_buffer;
19✔
350

351
    ret = CopyCachedState(TPMLIB_STATE_PERMANENT,
19✔
352
                          &buffer, &buffer_len, &is_empty_buffer);
353
    if (ret == TPM_SUCCESS) {
19✔
354
        ret = TPM_PermanentAll_NVLoad(tpm_state);
19✔
355

356
        /* restore a previous empty buffer or any valid buffer */
357
        if (is_empty_buffer || buffer != NULL)
19✔
358
            SetCachedState(TPMLIB_STATE_PERMANENT, buffer, buffer_len);
11✔
359
    }
360

361
    return ret;
19✔
362
}
363

364
/*
365
 * Get the state blob of the given type. If we TPM is not running, we
366
 * get the cached state blobs, if available, otherwise we try to read
367
 * it from files. In case the TPM is running, we get it from the running
368
 * TPM.
369
 */
370
static TPM_RESULT TPM12_GetState(enum TPMLIB_StateType st,
371
                                 unsigned char **buffer, uint32_t *buflen)
372
{
373
    TPM_RESULT ret = TPM_FAIL;
×
374
    TPM_STORE_BUFFER tsb;
×
375
    uint32_t total;
×
376

377
    /* TPM not running ? */
378
    if (tpm_instances[0] == NULL) {
×
379
        struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
×
380
        bool is_empty_buffer;
×
381

382
        /* try cached blob before file */
383
        ret = CopyCachedState(st, buffer, buflen, &is_empty_buffer);
×
384
        if (ret != TPM_SUCCESS || *buffer != NULL || is_empty_buffer)
×
385
            return ret;
386

387
        if (cbs->tpm_nvram_init) {
×
388
            ret = cbs->tpm_nvram_init();
×
389
            if (ret != TPM_SUCCESS)
×
390
                return ret;
391

392
            ret = TPM_NVRAM_LoadData(buffer, buflen, 0,
×
393
                                     TPMLIB_StateTypeToName(st));
394
        } else {
395
            ret = TPM_FAIL;
396
        }
397
        return ret;
×
398
    }
399

400
    TPM_Sbuffer_Init(&tsb);
×
401

402
    switch (st) {
×
403
    case TPMLIB_STATE_PERMANENT:
×
404
        ret = _TPM_PermanentAll_Store(&tsb, tpm_instances[0]);
×
405
        break;
×
406
    case TPMLIB_STATE_VOLATILE:
×
407
        ret = TPM_VolatileAll_Store(&tsb, tpm_instances[0]);
×
408
        break;
×
409
    case TPMLIB_STATE_SAVE_STATE:
×
410
        ret = TPM_SaveState_Store(&tsb, tpm_instances[0]);
×
411
        break;
×
412
    }
413

414
    if (ret == TPM_SUCCESS) {
×
415
        /* caller now owns the buffer and needs to free it */
416
        TPM_Sbuffer_GetAll(&tsb, buffer, buflen, &total);
×
417
    } else {
418
        TPM_Sbuffer_Delete(&tsb);
×
419
        *buflen = 0;
×
420
        *buffer = NULL;
×
421
    }
422

423
    return ret;
424
}
425

426
/*
427
 * Set the state the TPM 1.2 will use upon next TPM_MainInit(). The TPM 1.2
428
 * must not have been started, yet, or it must have been terminated for this
429
 * function to set the state.
430
 *
431
 * @st: The TPMLIB_StateType describing the type of blob in the buffer
432
 * @buffer: pointer to the buffer containing the state blob; NULL pointer clears
433
 *          previous state
434
 * @buflen: length of the buffer
435
 */
436
static TPM_RESULT TPM12_SetState(enum TPMLIB_StateType st,
26✔
437
                                 const unsigned char *buffer, uint32_t buflen)
438
{
439
    TPM_RESULT ret = TPM_SUCCESS;
26✔
440
    unsigned char *stream = NULL, *orig_stream = NULL;
26✔
441
    uint32_t stream_size = buflen;
26✔
442
    tpm_state_t *tpm_state = NULL;
26✔
443

444
    if (buffer == NULL) {
26✔
445
        SetCachedState(st, NULL, 0);
×
446
        return TPM_SUCCESS;
×
447
    }
448

449
    if (tpm_instances[0])
26✔
450
        return TPM_INVALID_POSTINIT;
451

452
    if (ret == TPM_SUCCESS) {
26✔
453
        stream = malloc(buflen);
26✔
454
        if (!stream) {
26✔
455
            TPMLIB_LogError("Could not allocate %u bytes.\n", buflen);
×
456
            ret = TPM_SIZE;
×
457
        }
458
    }
459

460
    if (ret == TPM_SUCCESS) {
×
461
        orig_stream = stream;
26✔
462
        memcpy(stream, buffer, buflen);
26✔
463

464
        tpm_state = malloc(sizeof(tpm_state_t));
26✔
465
        if (!tpm_state) {
26✔
466
            TPMLIB_LogError("Could not allocated %zu bytes.\n",
×
467
                            sizeof(tpm_state_t));
468
            ret = TPM_SIZE;
×
469
        }
470
    }
471

472
    if (ret == TPM_SUCCESS) {
26✔
473
        ret = TPM_Global_Init(tpm_state);
26✔
474
    }
475

476
    /* test whether we can accept the blob */
477
    if (ret == TPM_SUCCESS) {
26✔
478
        tpm_state->tpm_number = 0;
26✔
479

480
        switch (st) {
26✔
481
        case TPMLIB_STATE_PERMANENT:
7✔
482
            ret = TPM_PermanentAll_Load(tpm_state, &stream, &stream_size);
7✔
483
            break;
7✔
484
        case TPMLIB_STATE_VOLATILE:
15✔
485
            /* permanent state needs to be there and loaded first */
486
            ret = TPM_PermanentAll_NVLoad_Preserve(tpm_state);
15✔
487
            if (ret == TPM_SUCCESS)
15✔
488
                ret = TPM_VolatileAll_Load(tpm_state, &stream, &stream_size);
15✔
489
            break;
490
        case TPMLIB_STATE_SAVE_STATE:
4✔
491
            ret = TPM_PermanentAll_NVLoad_Preserve(tpm_state);
4✔
492
            if (ret == TPM_SUCCESS)
4✔
493
                 ret = TPM_SaveState_Load(tpm_state, &stream, &stream_size);
4✔
494
            break;
495
        }
496
        if (ret)
26✔
497
            ClearAllCachedState();
×
498
    }
499

500
    /* cache the blob for the TPM_MainInit() to pick it up */
501
    if (ret == TPM_SUCCESS) {
26✔
502
        SetCachedState(st, orig_stream, buflen);
26✔
503
    } else {
504
        free(orig_stream);
×
505
    }
506

507
    TPM_Global_Delete(tpm_state);
26✔
508
    free(tpm_state);
26✔
509

510
    return ret;
26✔
511
}
512

513
const struct tpm_interface TPM12Interface = {
514
    .MainInit = TPM12_MainInit,
515
    .Terminate = TPM12_Terminate,
516
    .Process = TPM12_Process,
517
    .VolatileAllStore = TPM12_VolatileAllStore,
518
    .CancelCommand = TPM12_CancelCommand,
519
    .GetTPMProperty = TPM12_GetTPMProperty,
520
    .GetInfo = TPM12_GetInfo,
521
    .TpmEstablishedGet = TPM12_IO_TpmEstablished_Get,
522
    .TpmEstablishedReset = TPM12_IO_TpmEstablished_Reset,
523
    .HashStart = TPM12_IO_Hash_Start,
524
    .HashData = TPM12_IO_Hash_Data,
525
    .HashEnd = TPM12_IO_Hash_End,
526
    .SetBufferSize = TPM12_SetBufferSize,
527
    .ValidateState = TPM12_ValidateState,
528
    .SetState = TPM12_SetState,
529
    .GetState = TPM12_GetState,
530
};
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