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

stefanberger / swtpm / #2825

13 May 2025 12:34PM UTC coverage: 73.203% (+0.2%) from 72.964%
#2825

push

travis-ci

web-flow
Merge b1b10a575 into 29d533fbf

7149 of 9766 relevant lines covered (73.2%)

14118.19 hits per line

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

81.27
/src/swtpm_setup/swtpm.c
1
/* SPDX-License-Identifier: BSD-3-Clause */
2
/*
3
 * swtpm.c: Programming of a swtpm using communication via fd-passing
4
 *
5
 * Author: Stefan Berger, stefanb@linux.ibm.com
6
 *
7
 * Copyright (c) IBM Corporation, 2021
8
 */
9

10
#include "config.h"
11

12
#include <errno.h>
13
#include <poll.h>
14
#include <stdbool.h>
15
#include <stdio.h>
16
#include <stdint.h>
17
#include <string.h>
18
#include <sys/types.h>
19
#include <sys/socket.h>
20
#include <sys/stat.h>
21
#include <sys/wait.h>
22
#include <unistd.h>
23
#include <fcntl.h>
24

25
#include <glib.h>
26

27
#include <openssl/bn.h>
28
#include <openssl/evp.h>
29
#include <openssl/hmac.h>
30
#include <openssl/rsa.h>
31
#include <openssl/sha.h>
32
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
33
# include <openssl/core_names.h>
34
# include <openssl/param_build.h>
35
#else
36
# include <openssl/rsa.h>
37
#endif
38

39
#include "swtpm.h"
40
#include "swtpm_utils.h"
41
#include "tpm_ioctl.h"
42
#include "sys_dependencies.h"
43

44
#define AS2BE(VAL) (((VAL) >> 8) & 0xff), ((VAL) & 0xff)
45
#define AS4BE(VAL) AS2BE((VAL) >> 16), AS2BE(VAL)
46
#define AS8BE(VAL) AS4BE((VAL) >> 32), AS4BE(VAL)
47

48
#define CMD_DURATION_SHORT  2000 /* ms */
49

50
struct tpm_req_header {
51
    uint16_t tag;
52
    uint32_t size;
53
    uint32_t ordinal;
54
} __attribute__((packed));
55

56
struct tpm_resp_header {
57
    uint16_t tag;
58
    uint32_t size;
59
    uint32_t errcode;
60
} __attribute__((packed));
61

62
/* Close the ctrl and data file descriptors that were passed to the swtpm process.
63
 * If 'all' is true then also close the ones not passed to the process.
64
 */
65
static void swtpm_close_comm(struct swtpm *self, bool all)
146✔
66
{
67
    if (all)
146✔
68
        SWTPM_CLOSE(self->data_fds[0]);
73✔
69
    SWTPM_CLOSE(self->data_fds[1]);
146✔
70

71
    if (all)
146✔
72
        SWTPM_CLOSE(self->ctrl_fds[0]);
73✔
73
    SWTPM_CLOSE(self->ctrl_fds[1]);
146✔
74
}
146✔
75

76
static int swtpm_start(struct swtpm *self)
73✔
77
{
78
    g_autofree gchar *tpmstate = g_strdup_printf("backend-uri=%s", self->state_path);
73✔
79
    g_autofree gchar *pidfile_arg = NULL;
73✔
80
    g_autofree gchar *server_fd = NULL;
73✔
81
    g_autofree gchar *ctrl_fd = NULL;
73✔
82
    g_autofree gchar *keyopts = NULL;
73✔
83
    g_autofree gchar *logop = NULL;
73✔
84
    g_autofree gchar **argv = NULL;
73✔
85
    struct stat statbuf;
73✔
86
    gboolean success;
73✔
87
    GError *error = NULL;
73✔
88
    GSpawnFlags flags;
73✔
89
    unsigned ctr;
73✔
90
    int pidfile_fd;
73✔
91
    int ret = 1;
73✔
92
    char pidfile[] = "/tmp/.swtpm_setup.pidfile.XXXXXX";
73✔
93

94
    pidfile_fd = g_mkstemp_full(pidfile, O_EXCL|O_CREAT, 0600);
73✔
95
    if (pidfile_fd < 0) {
73✔
96
        logerr(self->logfile, "Could not create pidfile: %s\n", strerror(errno));
×
97
        goto error_no_pidfile;
×
98
    }
99
    // pass filename rather than fd (Cygwin)
100
    pidfile_arg = g_strdup_printf("file=%s", pidfile);
73✔
101

102
    argv = concat_arrays(self->swtpm_exec_l,
146✔
103
                         (gchar*[]){
73✔
104
                              "--flags", "not-need-init,startup-clear",
105
                              "--tpmstate", tpmstate,
106
                              "--pid", pidfile_arg,
107
#if 0
108
                              "--log", "file=/tmp/log,level=20",
109
#endif
110
                              NULL
111
                         }, FALSE);
112

113
    if (self->is_tpm2)
73✔
114
        argv = concat_arrays(argv, (gchar*[]){"--tpm2", NULL}, TRUE);
47✔
115

116
    if (self->keyopts != NULL) {
73✔
117
        keyopts = g_strdup(self->keyopts);
30✔
118
        argv = concat_arrays(argv, (gchar*[]){"--key", keyopts, NULL}, TRUE);
30✔
119
    }
120

121
    if (gl_LOGFILE != NULL) {
73✔
122
        logop = g_strdup_printf("file=%s", gl_LOGFILE);
15✔
123
        argv = concat_arrays(argv, (gchar*[]){"--log", logop, NULL}, TRUE);
15✔
124
    }
125

126
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, self->ctrl_fds) != 0) {
73✔
127
        logerr(self->logfile, "Could not create socketpair: %s\n", strerror(errno));
×
128
        goto error;
×
129
    }
130
    ctrl_fd = g_strdup_printf("type=unixio,clientfd=%d", self->ctrl_fds[1]);
73✔
131

132
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, self->data_fds) != 0) {
73✔
133
        logerr(self->logfile, "Could not create socketpair: %s\n", strerror(errno));
×
134
        goto error;
×
135
    }
136
    server_fd = g_strdup_printf("type=tcp,fd=%d", self->data_fds[1]);
73✔
137

138
    argv = concat_arrays(argv, (gchar*[]){
73✔
139
                             "--server", server_fd,
140
                             "--ctrl", ctrl_fd,
141
                             NULL
142
                         }, TRUE);
143

144
#if 0
145
    {
146
        g_autofree gchar *join = g_strjoinv(" ", argv);
147
        logit(self->logfile, "Starting swtpm: %s\n", join);
148
    }
149
#endif
150

151
    flags = G_SPAWN_LEAVE_DESCRIPTORS_OPEN;
73✔
152
    if (gl_LOGFILE) {
73✔
153
        flags |= G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
15✔
154
    } else {
155
#if GLIB_CHECK_VERSION(2, 74, 0)
156
        flags |= G_SPAWN_CHILD_INHERITS_STDOUT | G_SPAWN_CHILD_INHERITS_STDERR;
157
#endif
158
    }
73✔
159

160
    success = g_spawn_async(NULL, argv, NULL, flags,
73✔
161
                            NULL, NULL, &self->pid, &error);
162
    if (!success) {
73✔
163
        logerr(self->logfile, "Could not start swtpm: %s\n", error->message);
×
164
        g_error_free(error);
×
165
        goto error;
×
166
    }
167

168
    /* wait until the pidfile is written to or swtpm terminates */
169
    for (ctr = 0; ctr < 1000; ctr++) {
409✔
170
        if (kill(self->pid, 0) < 0) {
409✔
171
            /* swtpm terminated */
172
            self->pid = 0;
×
173
            logerr(self->logfile, "swtpm process terminated unexpectedly.\n");
×
174
            self->cops->stop(self);
×
175
            goto error;
×
176
        }
177
        if (fstat(pidfile_fd, &statbuf) == 0 && statbuf.st_size > 0) {
409✔
178
            printf("TPM is listening on Unix socket.\n");
73✔
179
            ret = 0;
73✔
180
            break;
73✔
181
        }
182
        usleep(5000);
336✔
183
    }
184

185
error:
×
186
    swtpm_close_comm(self, ret != 0);
73✔
187

188
    close(pidfile_fd);
73✔
189
    unlink(pidfile);
73✔
190

191
error_no_pidfile:
73✔
192
    return ret;
73✔
193
}
194

195
/* Stop a running swtpm instance and close all the file descriptors connecting to it */
196
static void swtpm_stop(struct swtpm *self)
73✔
197
{
198
    unsigned c;
73✔
199
    gboolean ended = FALSE;
73✔
200

201
    if (self->pid > 0) {
73✔
202
        self->cops->ctrl_shutdown(self);
73✔
203
        for (c = 0; c < 500; c++) {
288✔
204
            if (kill(self->pid, 0) < 0) {
215✔
205
                ended = TRUE;
206
                break;
207
            }
208
            usleep(1000);
142✔
209
        }
210
        if (!ended)
73✔
211
            kill(self->pid, SIGKILL);
×
212
        waitpid(self->pid, NULL, 0);
73✔
213

214
        self->pid = 0;
73✔
215
    }
216

217
    swtpm_close_comm(self, true);
73✔
218
}
73✔
219

220
/* Destroy a running swtpm instance */
221
static void swtpm_destroy(struct swtpm *self)
73✔
222
{
223
    self->cops->stop(self);
73✔
224
}
73✔
225

226
/* Send a command to swtpm and receive the response either via control or data channel */
227
static int transfer(struct swtpm *self, void *buffer, size_t buffer_len,
933✔
228
                    const char *cmdname, gboolean use_ctrl,
229
                    void *respbuffer, size_t *respbuffer_len, int timeout_ms)
230
{
231
    size_t offset;
933✔
232
    int sockfd;
933✔
233
    ssize_t n;
933✔
234
    unsigned char resp[4096];
933✔
235
    ssize_t resplen;
933✔
236
    uint32_t returncode;
933✔
237
    struct pollfd fds = {
933✔
238
        .events = POLLIN | POLLERR | POLLHUP,
239
    };
240

241
    if (use_ctrl) {
933✔
242
        sockfd = self->ctrl_fds[0];
147✔
243
        offset = 0;
147✔
244
    } else {
245
        sockfd = self->data_fds[0];
786✔
246
        offset = 6;
786✔
247
    }
248

249
    n = write(sockfd, buffer, buffer_len);
933✔
250
    if (n < 0) {
933✔
251
        logerr(self->logfile, "Could not send %s buffer to swtpm: %s\n",
×
252
               cmdname, strerror(errno));
×
253
        return 1;
×
254
    }
255
    if ((size_t)n != buffer_len) {
933✔
256
        logerr(self->logfile, "Could not send all bytes to swtpm: %zu < %zu\n",
×
257
               (size_t)n, buffer_len);
258
        return 1;
×
259
    }
260

261
    fds.fd = sockfd;
933✔
262
    n = poll(&fds, 1, timeout_ms);
933✔
263
    if (n != 1 || (fds.revents & POLLIN) == 0) {
933✔
264
        logerr(self->logfile, "Could not receive response to %s from swtpm: %s\n",
×
265
               cmdname, strerror(errno));
×
266
        return 1;
×
267
    }
268

269
    resplen = read(sockfd, resp, sizeof(resp));
933✔
270
    if (resplen < 0) {
933✔
271
        logerr(self->logfile, "Could not receive response to %s from swtpm: %s\n",
×
272
               cmdname, strerror(errno));
×
273
        return 1;
×
274
    }
275

276
    if (!use_ctrl) {
933✔
277
        if ((size_t)resplen < sizeof(struct tpm_resp_header)) {
786✔
278
            logerr(self->logfile,
×
279
                   "Response for %s has only %d bytes.\n", cmdname, resplen);
280
            return 1;
×
281
        }
282
    } else if ((size_t)resplen < 4) {
147✔
283
        logerr(self->logfile,
×
284
               "Response for %s has only %d bytes.\n", cmdname, resplen);
285
        return 1;
×
286
    }
287

288
    memcpy(&returncode, &resp[offset], sizeof(returncode));
933✔
289
    returncode = be32toh(returncode);
933✔
290
    if (returncode != 0) {
933✔
291
        logerr(self->logfile,
×
292
               "%s failed: 0x%x\n", cmdname, returncode);
293
        return 1;
×
294
    }
295

296
    if (respbuffer) {
933✔
297
        *respbuffer_len = min((size_t)resplen, *respbuffer_len);
230✔
298
        memcpy(respbuffer, resp, *respbuffer_len);
230✔
299
    }
300

301
    return 0;
302
}
303

304
/* Send a CMD_SHUTDOWN over the control channel */
305
static int swtpm_ctrl_shutdown(struct swtpm *self)
73✔
306
{
307
    uint32_t cmd = htobe32(CMD_SHUTDOWN);
73✔
308

309
    return transfer(self, &cmd, sizeof(cmd), "CMD_SHUTDOWN", TRUE,
73✔
310
                    NULL, NULL, CMD_DURATION_SHORT);
311
}
312

313
/* Get the TPM specification parameters over the control channel */
314
static int swtpm_ctrl_get_tpm_specs_and_attrs(struct swtpm *self, gchar **result)
74✔
315
{
316
    unsigned char req[] = {AS4BE(CMD_GET_INFO),
74✔
317
                           AS8BE(SWTPM_INFO_TPMSPECIFICATION | SWTPM_INFO_TPMATTRIBUTES),
318
                           AS4BE(0), AS4BE(0)};
319
    unsigned char tpmresp[1024];
74✔
320
    size_t tpmresp_len = sizeof(tpmresp);
74✔
321
    int ret;
74✔
322
    uint32_t length;
74✔
323

324
    ret = transfer(self, req, sizeof(req), "CMD_GET_INFO", TRUE,
74✔
325
                   tpmresp, &tpmresp_len, CMD_DURATION_SHORT);
326
    if (ret != 0)
74✔
327
        return 1;
328

329
    if (tpmresp_len < 8 + sizeof(length))
74✔
330
        goto err_too_short;
×
331
    memcpy(&length, &tpmresp[8], sizeof(length));
74✔
332
    length = htobe32(length);
74✔
333

334
    if (tpmresp_len < 12 + length)
74✔
335
        goto err_too_short;
×
336
    *result = g_strndup((gchar *)&tpmresp[12], length);
74✔
337

338
    return 0;
74✔
339

340
err_too_short:
×
341
    logerr(self->logfile, "Response from CMD_GET_INFO is too short!\n");
×
342

343
    return 1;
×
344
}
345

346
static const struct swtpm_cops swtpm_cops = {
347
    .start = swtpm_start,
348
    .stop = swtpm_stop,
349
    .destroy = swtpm_destroy,
350
    .ctrl_shutdown = swtpm_ctrl_shutdown,
351
    .ctrl_get_tpm_specs_and_attrs = swtpm_ctrl_get_tpm_specs_and_attrs,
352
};
353

354
/*
355
 * TPM 2 support
356
 */
357

358
#define TPM2_ST_NO_SESSIONS  0x8001
359
#define TPM2_ST_SESSIONS     0x8002
360

361
#define TPM2_CC_EVICTCONTROL   0x00000120
362
#define TPM2_CC_NV_DEFINESPACE 0x0000012a
363
#define TPM2_CC_PCR_ALLOCATE   0x0000012b
364
#define TPM2_CC_CREATEPRIMARY  0x00000131
365
#define TPM2_CC_NV_WRITE       0x00000137
366
#define TPM2_CC_NV_WRITELOCK   0x00000138
367
#define TPM2_CC_SHUTDOWN       0x00000145
368
#define TPM2_CC_FLUSHCONTEXT   0x00000165
369
#define TPM2_CC_GETCAPABILITY  0x0000017a
370

371
#define TPM2_SU_CLEAR        0x0000
372

373
#define TPM2_RH_OWNER        0x40000001
374
#define TPM2_RS_PW           0x40000009
375
#define TPM2_RH_ENDORSEMENT  0x4000000b
376
#define TPM2_RH_PLATFORM     0x4000000c
377

378
#define TPM2_ALG_RSA      0x0001
379
#define TPM2_ALG_SHA1     0x0004
380
#define TPM2_ALG_AES      0x0006
381
#define TPM2_ALG_SHA256   0x000b
382
#define TPM2_ALG_SHA384   0x000c
383
#define TPM2_ALG_SHA512   0x000d
384
#define TPM2_ALG_SHA3_256 0x0027
385
#define TPM2_ALG_SHA3_384 0x0028
386
#define TPM2_ALG_SHA3_512 0x0029
387
#define TPM2_ALG_NULL     0x0010
388
#define TPM2_ALG_SM3      0x0012
389
#define TPM2_ALG_ECC      0x0023
390
#define TPM2_ALG_CFB      0x0043
391

392
#define TPM2_CAP_PCRS     0x00000005
393

394
#define TPM2_ECC_NIST_P384 0x0004
395

396
#define TPMA_NV_PLATFORMCREATE 0x40000000
397
#define TPMA_NV_AUTHREAD       0x40000
398
#define TPMA_NV_NO_DA          0x2000000
399
#define TPMA_NV_PPWRITE        0x1
400
#define TPMA_NV_PPREAD         0x10000
401
#define TPMA_NV_OWNERREAD      0x20000
402
#define TPMA_NV_WRITEDEFINE    0x2000
403

404
// Use standard EK Cert NVRAM, EK and SRK handles per IWG spec.
405
// "TCG TPM v2.0 Provisioning Guide"; Version 1.0, Rev 1.0, March 15, 2017
406
// Table 2
407
#define TPM2_NV_INDEX_RSA2048_EKCERT         0x01c00002
408
#define TPM2_NV_INDEX_RSA2048_EKTEMPLATE     0x01c00004
409
#define TPM2_NV_INDEX_RSA3072_HI_EKCERT      0x01c0001c
410
#define TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE  0x01c0001d
411
// For ECC follow "TCG EK Credential Profile For TPM Family 2.0; Level 0"
412
// Specification Version 2.1; Revision 13; 10 December 2018
413
#define TPM2_NV_INDEX_PLATFORMCERT           0x01c08000
414

415
#define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT     0x01c00016
416
#define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE 0x01c00017
417

418
#define TPM2_EK_RSA_HANDLE           0x81010001
419
#define TPM2_EK_RSA3072_HANDLE       0x8101001c
420
#define TPM2_EK_ECC_SECP384R1_HANDLE 0x81010016
421
#define TPM2_SPK_HANDLE              0x81000001
422

423
#define TPM2_DURATION_SHORT     2000 /* ms */
424
#define TPM2_DURATION_MEDIUM    7500 /* ms */
425
#define TPM2_DURATION_LONG     15000 /* ms */
426

427
#define TPM_REQ_HEADER_INITIALIZER(TAG, SIZE, ORD) \
428
    { \
429
        .tag = htobe16(TAG), \
430
        .size = htobe32(SIZE), \
431
        .ordinal = htobe32(ORD), \
432
    }
433

434
struct tpm2_authblock {
435
    uint32_t auth;
436
    uint16_t foo; // FIXME
437
    uint8_t continueSession;
438
    uint16_t bar; // FIMXE
439
} __attribute__((packed));
440

441
#define TPM2_AUTHBLOCK_INITIALIZER(AUTH, FOO, CS, BAR) \
442
    { \
443
        .auth = htobe32(AUTH), \
444
        .foo = htobe16(FOO), \
445
        .continueSession = CS, \
446
        .bar = htobe16(BAR), \
447
    }
448

449
static const unsigned char NONCE_EMPTY[2] = {AS2BE(0)};
450
static const unsigned char NONCE_RSA2048[2+0x100] = {AS2BE(0x100), 0, };
451
static const unsigned char NONCE_RSA3072[2+0x180] = {AS2BE(0x180), 0, };
452
static const unsigned char NONCE_ECC_384[2+0x30] = {AS2BE(0x30), 0, };
453

454
static const struct bank_to_name {
455
    uint16_t hashAlg;
456
    const char *name;
457
} banks_to_names[] = {
458
    {TPM2_ALG_SHA1, "sha1"},
459
    {TPM2_ALG_SHA256, "sha256"},
460
    {TPM2_ALG_SHA384, "sha384"},
461
    {TPM2_ALG_SHA512, "sha512"},
462
    {TPM2_ALG_SM3, "sm3-256"},
463
    {TPM2_ALG_SHA3_256, "sha3-256"},
464
    {TPM2_ALG_SHA3_384, "sha3-384"},
465
    {TPM2_ALG_SHA3_512, "sha3-512"},
466
    {0, NULL},
467
};
468

469
/* function prototypes */
470
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
471
                                        const unsigned char *symkeydata, size_t symkeydata_len,
472
                                        const unsigned char *authpolicy, size_t authpolicy_len,
473
                                        unsigned int rsa_keysize, gboolean havenonce, size_t off,
474
                                        uint32_t *curr_handle,
475
                                        unsigned char *ektemplate, size_t *ektemplate_len,
476
                                        gchar **ekparam, const gchar **key_description);
477

478
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
479
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
480
                                  const char *purpose);
481

482
/* Given a hash algo identifier, return the name of the hash bank */
483
static const char *get_name_for_bank(uint16_t hashAlg) {
188✔
484
    size_t i;
188✔
485

486
    for (i = 0; banks_to_names[i].name; i++) {
470✔
487
        if (banks_to_names[i].hashAlg == hashAlg)
470✔
488
            return banks_to_names[i].name;
489
    }
490
    return NULL;
491
}
492

493
/* Give the name of a hash bank, return its algo identifier */
494
static uint16_t get_hashalg_by_bankname(const char *name) {
188✔
495
    size_t i;
188✔
496

497
    for (i = 0; banks_to_names[i].name; i++) {
470✔
498
        if (strcmp(banks_to_names[i].name, name) == 0)
470✔
499
            return banks_to_names[i].hashAlg;
188✔
500
    }
501
    return 0;
502
}
503

504
/* Do an SU_CLEAR shutdown of the TPM 2 */
505
static int swtpm_tpm2_shutdown(struct swtpm *self)
47✔
506
{
507
    struct tpm2_shutdown_req {
47✔
508
        struct tpm_req_header hdr;
509
        uint16_t shutdownType;
510
    } __attribute__((packed)) req = {
47✔
511
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_SHUTDOWN),
47✔
512
        .shutdownType = htobe16(TPM2_SU_CLEAR)
47✔
513
    };
514

515
    return transfer(self, &req, sizeof(req), "TPM2_Shutdown", FALSE,
47✔
516
                    NULL, NULL, TPM2_DURATION_SHORT);
517
}
518

519
/* Get all available PCR banks */
520
static int swtpm_tpm2_get_all_pcr_banks(struct swtpm *self, gchar ***all_pcr_banks)
47✔
521
{
522
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, 0, TPM2_CC_GETCAPABILITY);
47✔
523
    g_autofree unsigned char *req = NULL;
94✔
524
    ssize_t req_len;
47✔
525
    unsigned char tpmresp[256];
47✔
526
    size_t tpmresp_len = sizeof(tpmresp);
47✔
527
    uint16_t count, bank;
47✔
528
    const char *name;
47✔
529
    uint8_t length;
47✔
530
    size_t offset;
47✔
531
    size_t i;
47✔
532
    int ret;
47✔
533

534
    req_len = memconcat(&req,
94✔
535
                        &hdr, sizeof(hdr),
536
                        (unsigned char[]){AS4BE(TPM2_CAP_PCRS), AS4BE(0), AS4BE(64)}, (size_t)12,
47✔
537
                        NULL);
538
    if (req_len < 0) {
47✔
539
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
540
        return 1;
×
541
    }
542
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
47✔
543

544
    ret = transfer(self, req, req_len, "TPM2_GetCapability", FALSE,
47✔
545
                   tpmresp, &tpmresp_len, TPM2_DURATION_MEDIUM);
546
    if (ret != 0)
47✔
547
        return 1;
548

549
    *all_pcr_banks = NULL;
47✔
550

551
    if (tpmresp_len < 17 + sizeof(count))
47✔
552
        goto err_too_short;
×
553
    memcpy(&count, &tpmresp[17], sizeof(count));
47✔
554
    count = be16toh(count);
47✔
555

556
    /* unreasonable number of PCR banks ? */
557
    if (count > 20)
47✔
558
        goto err_num_pcrbanks;
×
559

560
    *all_pcr_banks = g_malloc0(sizeof(char *) * (count + 1));
47✔
561

562
    offset = 19;
47✔
563

564
    for (i = 0; i < count; i++) {
235✔
565
        gchar *n;
188✔
566

567
        if (tpmresp_len < offset + sizeof(bank))
188✔
568
            goto err_too_short;
×
569
        memcpy(&bank, &tpmresp[offset], sizeof(bank));
188✔
570
        bank = be16toh(bank);
188✔
571

572
        if (tpmresp_len < offset + 2 + sizeof(length))
188✔
573
            goto err_too_short;
×
574
        length = tpmresp[offset + 2];
188✔
575

576
        name = get_name_for_bank(bank);
188✔
577
        if (name != NULL)
188✔
578
            n = g_strdup(name);
188✔
579
        else
580
            n = g_strdup_printf("%02x", bank);
×
581

582
        (*all_pcr_banks)[i] = n;
188✔
583

584
        offset += 2 + 1 + length;
188✔
585
    }
586
    return 0;
587

588
err_num_pcrbanks:
×
589
    logerr(self->logfile, "Unreasonable number of PCR banks (%u) returned.\n", count);
×
590
    goto err_exit;
×
591

592
err_too_short:
×
593
    logerr(self->logfile, "Response from TPM2_GetCapability is too short!\n");
×
594

595
err_exit:
×
596
    g_strfreev(*all_pcr_banks);
×
597
    *all_pcr_banks = NULL;
×
598

599
    return 1;
×
600
}
601

602
/* Activate all user-chosen PCR banks and deactivate all others */
603
static int swtpm_tpm2_set_active_pcr_banks(struct swtpm *self, gchar **pcr_banks,
47✔
604
                                           gchar **all_pcr_banks, gchar ***active)
605
{
606
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_PCR_ALLOCATE);
47✔
607
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0);
47✔
608
    unsigned char pcrselects[6 * 10]; // supports up to 10 PCR banks
47✔
609
    ssize_t pcrselects_len = 0;
47✔
610
    size_t count = 0;
47✔
611
    size_t idx, j;
47✔
612
    uint16_t hashAlg;
47✔
613
    g_autofree unsigned char *req = NULL;
94✔
614
    ssize_t req_len, len;
47✔
615
    int ret;
47✔
616
    uint64_t activated_mask = 0;
47✔
617

618
    for (idx = 0; pcr_banks[idx] != NULL; idx++)
100✔
619
        ;
620
    *active = g_malloc0(sizeof(char *) * (idx + 1));
47✔
621

622
    for (idx = 0; pcr_banks[idx] != NULL; idx++) {
100✔
623
        hashAlg = 0;
114✔
624
        // Is user-chosen pcr_banks[idx] available?
625
        for (j = 0; all_pcr_banks[j] != NULL; j++) {
114✔
626
            if (strcmp(pcr_banks[idx], all_pcr_banks[j]) == 0) {
114✔
627
                hashAlg = get_hashalg_by_bankname(pcr_banks[idx]);
53✔
628
                break;
53✔
629
            }
630
        }
631
        if (hashAlg != 0 && (activated_mask & ((uint64_t)1 << j)) == 0) {
53✔
632
            (*active)[count] = g_strdup(pcr_banks[idx]);
53✔
633
            len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
106✔
634
                         (unsigned char[]){AS2BE(hashAlg), 3, 0xff, 0xff, 0xff} , (size_t)6,
53✔
635
                         NULL);
636
            if (len < 0) {
53✔
637
                logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
638
                return 1;
×
639
            }
640
            pcrselects_len += len;
53✔
641
            count++;
53✔
642
            activated_mask |= ((uint64_t)1 << j);
53✔
643
        }
644
    }
645

646
    if (count == 0) {
47✔
647
        logerr(self->logfile,
×
648
               "No PCR banks could be allocated. None of the selected algorithms are supported.\n");
649
        goto error;
×
650
    }
651

652
    // disable all the other ones not chosen by the user
653
    for (idx = 0; all_pcr_banks[idx] != NULL; idx++) {
235✔
654
        gboolean found = FALSE;
339✔
655

656
        for (j = 0; pcr_banks[j] != NULL; j++) {
339✔
657
            if (strcmp(pcr_banks[j], all_pcr_banks[idx]) == 0) {
204✔
658
                found = TRUE;
659
                break;
660
            }
661
        }
662
        if (found)
188✔
663
            continue;
53✔
664

665
        /* not found, so not chosen by user */
666
        hashAlg = get_hashalg_by_bankname(all_pcr_banks[idx]);
135✔
667

668
        len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
270✔
669
                     (unsigned char[]){AS2BE(hashAlg), 3, 0, 0, 0}, (size_t)6,
135✔
670
                     NULL);
671
        if (len < 0) {
135✔
672
            logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
673
            goto error;
×
674
        }
675
        pcrselects_len += len;
135✔
676
        count++;
135✔
677
    }
678

679
    req_len = memconcat(&req,
94✔
680
                        &hdr, sizeof(hdr),
681
                        (unsigned char[]){
47✔
682
                             AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))
683
                        }, (size_t)8,
684
                        &authblock, sizeof(authblock),
685
                        (unsigned char[]){AS4BE(count)}, (size_t)4,
47✔
686
                        pcrselects, pcrselects_len,
687
                        NULL);
688
    if (req_len < 0) {
47✔
689
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
690
        goto error;
×
691
    }
692
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
47✔
693

694
    ret = transfer(self, req, req_len, "TPM2_PCR_Allocate", FALSE,
47✔
695
                   NULL, NULL, TPM2_DURATION_SHORT);
696
    if (ret != 0)
47✔
697
        goto error;
×
698

699
    return 0;
700

701
error:
×
702
    g_strfreev(*active);
×
703
    *active = NULL;
×
704

705
    return 1;
×
706
}
707

708
static int swtpm_tpm2_flushcontext(struct swtpm *self, uint32_t handle)
3✔
709
{
710
    struct tpm2_flushcontext_req {
3✔
711
        struct tpm_req_header hdr;
712
        uint32_t flushHandle;
713
    } __attribute__((packed)) req = {
3✔
714
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_FLUSHCONTEXT),
3✔
715
        .flushHandle = htobe32(handle),
3✔
716
    };
717

718
    return transfer(self, &req, sizeof(req), "TPM2_FlushContext", FALSE,
3✔
719
                    NULL, NULL, TPM2_DURATION_SHORT);
720
}
721

722
/* Make object at the curr_handler permanent with the perm_handle */
723
static int swtpm_tpm2_evictcontrol(struct swtpm *self, uint32_t curr_handle, uint32_t perm_handle)
81✔
724
{
725
    struct tpm2_evictcontrol_req {
81✔
726
        struct tpm_req_header hdr;
727
        uint32_t auth;
728
        uint32_t objectHandle;
729
        uint32_t authblockLen;
730
        struct tpm2_authblock authblock;
731
        uint32_t persistentHandle;
732
    } __attribute__((packed)) req = {
81✔
733
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, sizeof(req), TPM2_CC_EVICTCONTROL),
81✔
734
        .auth = htobe32(TPM2_RH_OWNER),
81✔
735
        .objectHandle = htobe32(curr_handle),
81✔
736
        .authblockLen = htobe32(sizeof(req.authblock)),
81✔
737
        .authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0),
81✔
738
        .persistentHandle = htobe32(perm_handle),
81✔
739
    };
740

741
    return transfer(self, &req, sizeof(req), "TPM2_EvictControl", FALSE,
81✔
742
                    NULL, NULL, TPM2_DURATION_SHORT);
743
}
744

745
/* Create an RSA EK */
746
static int swtpm_tpm2_createprimary_ek_rsa(struct swtpm *self, unsigned int rsa_keysize,
39✔
747
                                           gboolean allowsigning, gboolean decryption,
748
                                           uint32_t *curr_handle,
749
                                           unsigned char *ektemplate, size_t *ektemplate_len,
750
                                           gchar **ekparam, const gchar **key_description)
751
{
752
    unsigned char authpolicy[48];
39✔
753
    size_t authpolicy_len;
39✔
754
    unsigned char symkeydata[6];
39✔
755
    size_t symkeydata_len;
39✔
756
    unsigned int keyflags;
39✔
757
    unsigned int symkeylen;
39✔
758
    gboolean havenonce;
39✔
759
    size_t addlen, off;
39✔
760

761
    if (rsa_keysize == 2048) {
39✔
762
        authpolicy_len = 32;
27✔
763
        memcpy(authpolicy, ((unsigned char []){
27✔
764
            0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d,
765
            0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64,
766
            0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa
767
        }), authpolicy_len);
768
        keyflags = 0;
27✔
769
        symkeylen = 128;
27✔
770
        havenonce = TRUE;
27✔
771
        addlen = 0;
27✔
772
    } else if (rsa_keysize == 3072) {
12✔
773
        authpolicy_len = 48;
12✔
774
        memcpy(authpolicy, ((unsigned char []){
12✔
775
            0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC, 0x53, 0xD8, 0x82, 0xBC,
776
            0xF5, 0xFD, 0x3A, 0x1A, 0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4,
777
            0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA, 0xCB, 0x47, 0xBA, 0x09,
778
            0x69, 0x96, 0x46, 0x15, 0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12
779
        }), authpolicy_len);
780
        keyflags = 0x40;
12✔
781
        symkeylen = 256;
12✔
782
        havenonce = FALSE;
12✔
783
        addlen = 16;
12✔
784
    } else {
785
        logerr(self->logfile, "Internal error in %s: unsupported RSA keysize %d.\n",
×
786
               __func__, rsa_keysize);
787
        return 1;
×
788
    }
789

790
    if (allowsigning && decryption) {
39✔
791
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
792
        // adminWithPolicy, sign, decrypt
793
        keyflags |= 0x000600b2;
6✔
794
        // symmetric: TPM_ALG_NULL
795
        symkeydata_len = 2;
6✔
796
        memcpy(symkeydata, ((unsigned char[]) {AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
6✔
797
        off = 72 + addlen;
6✔
798
    } else if (allowsigning) {
33✔
799
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
800
        // adminWithPolicy, sign
801
        keyflags |= 0x000400b2;
16✔
802
        // symmetric: TPM_ALG_NULL
803
        symkeydata_len = 2;
16✔
804
        memcpy(symkeydata, ((unsigned char[]) {AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
16✔
805
        off = 72 + addlen;
16✔
806
    } else {
807
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
808
        // adminWithPolicy, restricted, decrypt
809
        keyflags |= 0x000300b2;
17✔
810
        // symmetric: TPM_ALG_AES, 128bit or 256bit, TPM_ALG_CFB
811
        symkeydata_len = 6;
17✔
812
        memcpy(symkeydata,
17✔
813
               ((unsigned char[]) {AS2BE(TPM2_ALG_AES), AS2BE(symkeylen), AS2BE(TPM2_ALG_CFB)}),
17✔
814
               symkeydata_len);
815
        off = 76 + addlen;
17✔
816
    }
817

818
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_ENDORSEMENT, keyflags,
39✔
819
                                        symkeydata, symkeydata_len,
820
                                        authpolicy, authpolicy_len, rsa_keysize,
821
                                        havenonce, off, curr_handle,
822
                                        ektemplate, ektemplate_len, ekparam, key_description);
823
}
824

825
/* Create an RSA key with the given parameters */
826
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
41✔
827
                                        const unsigned char *symkeydata, size_t symkeydata_len,
828
                                        const unsigned char *authpolicy, size_t authpolicy_len,
829
                                        unsigned int rsa_keysize, gboolean havenonce, size_t off,
830
                                        uint32_t *curr_handle,
831
                                        unsigned char *ektemplate, size_t *ektemplate_len,
832
                                        gchar **ekparam, const gchar **key_description)
833
{
834
    const unsigned char *nonce;
41✔
835
    size_t nonce_len;
41✔
836
    uint16_t hashalg;
41✔
837
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY);
41✔
838
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0);
41✔
839
    g_autofree unsigned char *public = NULL;
82✔
840
    ssize_t public_len;
41✔
841
    g_autofree unsigned char *createprimary = NULL;
41✔
842
    ssize_t createprimary_len;
41✔
843
    int ret;
41✔
844
    unsigned char tpmresp[2048];
41✔
845
    size_t tpmresp_len = sizeof(tpmresp);
41✔
846
    uint16_t modlen;
41✔
847

848
    if (rsa_keysize == 2048) {
41✔
849
        nonce = NONCE_RSA2048;
28✔
850
        nonce_len = sizeof(NONCE_RSA2048);
28✔
851
        hashalg = TPM2_ALG_SHA256;
28✔
852
        if (key_description)
28✔
853
            *key_description = "rsa2048";
27✔
854
    } else if (rsa_keysize == 3072) {
13✔
855
        if (!havenonce) {
13✔
856
           nonce = NONCE_EMPTY;
857
           nonce_len = sizeof(NONCE_EMPTY);
858
        } else {
859
           nonce = NONCE_RSA3072;
1✔
860
           nonce_len = sizeof(NONCE_RSA3072);
1✔
861
        }
862
        hashalg = TPM2_ALG_SHA384;
13✔
863
        if (key_description)
13✔
864
            *key_description = "rsa3072";
12✔
865
    } else {
866
        logerr(self->logfile, "Internal error in %s: unsupported RSA keysize %d.\n",
×
867
               __func__, rsa_keysize);
868
        return 1;
×
869
    }
870

871
    public_len =
41✔
872
        memconcat(&public,
82✔
873
                  (unsigned char[]) {
41✔
874
                      AS2BE(TPM2_ALG_RSA), AS2BE(hashalg),
875
                      AS4BE(keyflags), AS2BE(authpolicy_len)
41✔
876
                  }, (size_t)10,
877
                  authpolicy, authpolicy_len,
878
                  symkeydata, symkeydata_len,
879
                  (unsigned char[]) {
41✔
880
                      AS2BE(TPM2_ALG_NULL), AS2BE(rsa_keysize), AS4BE(0)
41✔
881
                  }, (size_t)8,
882
                  nonce, nonce_len,
883
                  NULL);
884
    if (public_len < 0) {
41✔
885
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
886
        return 1;
×
887
    }
888
    if (ektemplate) {
41✔
889
        if (*ektemplate_len < (size_t)public_len) {
39✔
890
            logerr(self->logfile, "Internal error in %s: Need %zu bytes for ektemplate (rsa) but got only %zu\n",
×
891
                   __func__, public_len, *ektemplate_len);
892
            return 1;
×
893
        }
894
        memcpy(ektemplate, public, public_len);
39✔
895
        *ektemplate_len = public_len;
39✔
896
    }
897

898
    createprimary_len =
41✔
899
        memconcat(&createprimary,
82✔
900
                  &hdr, sizeof(hdr),
901
                  (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8,
41✔
902
                  &authblock, sizeof(authblock),
903
                  (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8,
41✔
904
                  public, public_len,
905
                  (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
41✔
906
                  NULL);
907
    if (createprimary_len < 0) {
41✔
908
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
909
        return 1;
×
910
    }
911
    ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len);
41✔
912

913
    ret = transfer(self, createprimary, createprimary_len, "TPM2_CreatePrimary(RSA)", FALSE,
41✔
914
                   tpmresp, &tpmresp_len, TPM2_DURATION_LONG);
915
    if (ret != 0)
41✔
916
        return 1;
917

918
    if (curr_handle) {
41✔
919
        if (tpmresp_len < 10 + sizeof(*curr_handle))
41✔
920
            goto err_too_short;
×
921
        memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle));
41✔
922
        *curr_handle = be32toh(*curr_handle);
41✔
923
    }
924

925
    if (tpmresp_len < off + sizeof(modlen))
41✔
926
         goto err_too_short;
×
927
    memcpy(&modlen, &tpmresp[off], sizeof(modlen));
41✔
928
    modlen = be16toh(modlen);
41✔
929
    if (modlen != rsa_keysize >> 3) {
41✔
930
        logerr(self->logfile, "Internal error in %s: Getting modulus from wrong offset %zu\n",
×
931
               __func__, off);
932
        return 1;
×
933
    }
934
    if (ekparam) {
41✔
935
        if (tpmresp_len < off + 2 + modlen)
39✔
936
            goto err_too_short;
×
937
        *ekparam = print_as_hex(&tpmresp[off + 2], modlen);
39✔
938
    }
939

940
    return 0;
941

942
err_too_short:
×
943
    logerr(self->logfile, "Response from TPM2_CreatePrimary(RSA) is too short!\n");
×
944
    return 1;
×
945
}
946

947
/* Create an ECC key with the given parameters */
948
static int swtpm_tpm2_createprimary_ecc(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
40✔
949
                                        const unsigned char *symkeydata, size_t symkeydata_len,
950
                                        const unsigned char *authpolicy, size_t authpolicy_len,
951
                                        const unsigned char *schemedata, size_t schemedata_len,
952
                                        unsigned short curveid, unsigned short hashalg,
953
                                        const unsigned char *nonce, size_t nonce_len,
954
                                        size_t off, uint32_t *curr_handle,
955
                                        unsigned char *ektemplate, size_t *ektemplate_len,
956
                                        gchar **ekparam, const gchar **key_description)
957
{
958
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY);
40✔
959
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0);
40✔
960
    g_autofree unsigned char *public = NULL;
80✔
961
    ssize_t public_len;
40✔
962
    g_autofree unsigned char *createprimary = NULL;
40✔
963
    ssize_t createprimary_len;
40✔
964
    int ret;
40✔
965
    unsigned char tpmresp[2048];
40✔
966
    size_t tpmresp_len = sizeof(tpmresp);
40✔
967
    size_t off2;
40✔
968
    uint16_t exp_ksize, ksize1, ksize2;
40✔
969
    const char *cid;
40✔
970

971
    public_len =
40✔
972
        memconcat(&public,
80✔
973
                  (unsigned char[]){
40✔
974
                      AS2BE(TPM2_ALG_ECC), AS2BE(hashalg), AS4BE(keyflags), AS2BE(authpolicy_len)
40✔
975
                  }, (size_t)10,
976
                  authpolicy, authpolicy_len,
977
                  symkeydata, symkeydata_len,
978
                  schemedata, schemedata_len,
979
                  nonce, nonce_len,
980
                  nonce, nonce_len,
981
                  NULL);
982
    if (public_len < 0) {
40✔
983
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
984
        return 1;
×
985
    }
986
    if (ektemplate) {
40✔
987
        if (*ektemplate_len < (size_t)public_len) {
39✔
988
            logerr(self->logfile, "Internal error: Need %zu bytes for ektemplate (ecc) but got only %zu\n",
×
989
                   public_len, ektemplate_len);
990
            return 1;
×
991
        }
992
        memcpy(ektemplate, public, public_len);
39✔
993
        *ektemplate_len = public_len;
39✔
994
    }
995

996
    createprimary_len =
40✔
997
        memconcat(&createprimary,
80✔
998
                  &hdr, sizeof(hdr),
999
                  (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8,
40✔
1000
                  &authblock, sizeof(authblock),
1001
                  (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8,
40✔
1002
                  public, public_len,
1003
                  (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
40✔
1004
                  NULL);
1005
    if (createprimary_len < 0) {
40✔
1006
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1007
        return 1;
×
1008
    }
1009
    ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len);
40✔
1010

1011
    ret = transfer(self, createprimary, createprimary_len, "TPM2_CreatePrimary(ECC)", FALSE,
40✔
1012
                   tpmresp, &tpmresp_len, TPM2_DURATION_LONG);
1013
    if (ret != 0)
40✔
1014
        return 1;
1015
    if (curr_handle) {
40✔
1016
        if (tpmresp_len < 10 + sizeof(*curr_handle))
40✔
1017
            goto err_too_short;
×
1018
        memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle));
40✔
1019
        *curr_handle = be32toh(*curr_handle);
40✔
1020
    }
1021

1022
    if (curveid == TPM2_ECC_NIST_P384) {
40✔
1023
        exp_ksize = 48;
40✔
1024
        cid = "secp384r1";
40✔
1025
        if (key_description)
40✔
1026
            *key_description = cid;
39✔
1027
    } else {
1028
        logerr(self->logfile, "Unknown curveid 0x%x\n", curveid);
×
1029
        return 1;
×
1030
    }
1031

1032
    if (tpmresp_len < off + sizeof(ksize1))
40✔
1033
        goto err_too_short;
×
1034
    memcpy(&ksize1, &tpmresp[off], sizeof(ksize1));
40✔
1035
    ksize1 = be16toh(ksize1);
40✔
1036
    off2 = off + 2 + ksize1;
40✔
1037

1038
    if (tpmresp_len < off2 + sizeof(ksize2))
40✔
1039
        goto err_too_short;
×
1040
    memcpy(&ksize2, &tpmresp[off2], sizeof(ksize2));
40✔
1041
    ksize2 = be16toh(ksize2);
40✔
1042

1043
    if (ksize1 != exp_ksize || ksize2 != exp_ksize) {
40✔
1044
        logerr(self->logfile, "ECC: Getting key parameters from wrong offset\n");
×
1045
        return 1;
×
1046
    }
1047

1048
    if (ekparam) {
40✔
1049
        unsigned char *xparam = &tpmresp[off + 2];
39✔
1050
        unsigned char *yparam = &tpmresp[off2 + 2];
39✔
1051
        if (tpmresp_len < off + 2 + ksize1 || tpmresp_len < off2 + 2 + ksize2)
39✔
1052
            goto err_too_short;
×
1053
        g_autofree gchar *xparam_str = print_as_hex(xparam, ksize1);
78✔
1054
        g_autofree gchar *yparam_str = print_as_hex(yparam, ksize2);
78✔
1055

1056
        *ekparam = g_strdup_printf("x=%s,y=%s,id=%s", xparam_str, yparam_str, cid);
39✔
1057
    }
1058

1059
    return 0;
1060

1061
err_too_short:
×
1062
    logerr(self->logfile, "Response from TPM2_CreatePrimary(ECC) is too short!\n");
×
1063
    return 1;
×
1064
}
1065

1066
static int swtpm_tpm2_createprimary_spk_ecc_nist_p384(struct swtpm *self,
1✔
1067
                                                      uint32_t *curr_handle)
1068
{
1069
    unsigned int keyflags = 0x00030472;
1✔
1070
    const unsigned char authpolicy[0];
1✔
1071
    size_t authpolicy_len = sizeof(authpolicy);
1✔
1072
    const unsigned char symkeydata[] = {AS2BE(TPM2_ALG_AES), AS2BE(256), AS2BE(TPM2_ALG_CFB)};
1✔
1073
    size_t symkeydata_len = sizeof(symkeydata);
1✔
1074
    const unsigned char schemedata[] = {
1✔
1075
        AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P384), AS2BE(TPM2_ALG_NULL)
1076
    };
1077
    size_t schemedata_len = sizeof(schemedata);
1✔
1078
    size_t off = 42;
1✔
1079

1080
    return swtpm_tpm2_createprimary_ecc(self, TPM2_RH_OWNER, keyflags, symkeydata, symkeydata_len,
1✔
1081
                                        authpolicy, authpolicy_len, schemedata, schemedata_len,
1082
                                        TPM2_ECC_NIST_P384, TPM2_ALG_SHA384,
1083
                                        NONCE_ECC_384, sizeof(NONCE_ECC_384), off, curr_handle,
1084
                                        NULL, 0, NULL, NULL);
1085
}
1086

1087
static int swtpm_tpm2_createprimary_spk_rsa(struct swtpm *self, unsigned int rsa_keysize,
2✔
1088
                                            uint32_t *curr_handle)
1089
{
1090
    unsigned int keyflags = 0x00030472;
2✔
1091
    const unsigned char authpolicy[0];
2✔
1092
    size_t authpolicy_len = sizeof(authpolicy);
2✔
1093
    unsigned short symkeylen = 0;
2✔
1094
    unsigned char symkeydata[6];
2✔
1095
    size_t symkeydata_len;
2✔
1096
    size_t off = 44;
2✔
1097

1098
    if (rsa_keysize == 2048)
2✔
1099
        symkeylen = 128;
1100
    else if (rsa_keysize == 3072)
1✔
1101
        symkeylen = 256;
1✔
1102

1103
    symkeydata_len = 6;
2✔
1104
    memcpy(symkeydata,
2✔
1105
           ((unsigned char[]) {AS2BE(TPM2_ALG_AES), AS2BE(symkeylen), AS2BE(TPM2_ALG_CFB)}),
2✔
1106
           symkeydata_len);
1107

1108
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_OWNER, keyflags,
2✔
1109
                                        symkeydata, symkeydata_len,
1110
                                        authpolicy, authpolicy_len, rsa_keysize, TRUE,
1111
                                        off, curr_handle, NULL, 0, NULL, NULL);
1112
}
1113

1114
/* Create either an ECC or RSA storage primary key */
1115
static int swtpm_tpm2_create_spk(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize)
3✔
1116
{
1117
    int ret;
3✔
1118
    uint32_t curr_handle;
3✔
1119

1120
    if (isecc)
3✔
1121
        ret = swtpm_tpm2_createprimary_spk_ecc_nist_p384(self, &curr_handle);
1✔
1122
    else
1123
        ret = swtpm_tpm2_createprimary_spk_rsa(self, rsa_keysize, &curr_handle);
2✔
1124

1125
    if (ret != 0)
3✔
1126
        return 1;
1127

1128
    ret = swtpm_tpm2_evictcontrol(self, curr_handle, TPM2_SPK_HANDLE);
3✔
1129
    if (ret == 0)
3✔
1130
        logit(self->logfile,
3✔
1131
              "Successfully created storage primary key with handle 0x%x.\n", TPM2_SPK_HANDLE);
1132

1133
    ret = swtpm_tpm2_flushcontext(self, curr_handle);
3✔
1134
    if (ret != 0) {
3✔
1135
        logerr(self->logfile, "Could not flush storage primary key.\n");
×
1136
        ret = 1;
×
1137
    }
1138

1139
    return ret;
1140
}
1141

1142
/* Create an ECC EK key that may be allowed to sign and/or decrypt */
1143
static int swtpm_tpm2_createprimary_ek_ecc_nist_p384(struct swtpm *self, gboolean allowsigning,
39✔
1144
                                                     gboolean decryption, uint32_t *curr_handle,
1145
                                                     unsigned char *ektemplate, size_t *ektemplate_len,
1146
                                                     gchar **ekparam, const char **key_description)
1147
{
1148
    unsigned char authpolicy[48]= {
39✔
1149
        0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC, 0x53, 0xD8, 0x82, 0xBC,
1150
        0xF5, 0xFD, 0x3A, 0x1A, 0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4,
1151
        0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA, 0xCB, 0x47, 0xBA, 0x09,
1152
        0x69, 0x96, 0x46, 0x15, 0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12
1153
    };
1154
    const unsigned char schemedata[] = {
39✔
1155
        AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P384), AS2BE(TPM2_ALG_NULL)
1156
    };
1157
    size_t schemedata_len = sizeof(schemedata);
39✔
1158
    size_t authpolicy_len = 48;
39✔
1159
    unsigned char symkeydata[6];
39✔
1160
    size_t symkeydata_len;
39✔
1161
    unsigned int keyflags;
39✔
1162
    size_t off;
39✔
1163
    int ret;
39✔
1164

1165
    if (allowsigning && decryption) {
39✔
1166
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1167
        // userWithAuth, adminWithPolicy, sign, decrypt
1168
        keyflags = 0x000600f2;
6✔
1169
        // symmetric: TPM_ALG_NULL
1170
        symkeydata_len = 2;
6✔
1171
        memcpy(symkeydata, ((unsigned char[]){AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
6✔
1172
        off = 86;
6✔
1173
    } else if (allowsigning) {
33✔
1174
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1175
        // userWithAuth, adminWithPolicy, sign
1176
        keyflags = 0x000400f2;
16✔
1177
        // symmetric: TPM_ALG_NULL
1178
        symkeydata_len = 2;
16✔
1179
        memcpy(symkeydata, ((unsigned char[]){AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
16✔
1180
        off = 86;
16✔
1181
    } else {
1182
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1183
        // userWithAuth, adminWithPolicy, restricted, decrypt
1184
        keyflags = 0x000300f2;
17✔
1185
        // symmetric: TPM_ALG_AES, 256bit, TPM_ALG_CFB
1186
        symkeydata_len = 6;
17✔
1187
        memcpy(symkeydata,
17✔
1188
               ((unsigned char[]){ AS2BE(TPM2_ALG_AES), AS2BE(256), AS2BE(TPM2_ALG_CFB)}),
17✔
1189
               symkeydata_len);
1190
        off = 90;
17✔
1191
    }
1192

1193
    ret = swtpm_tpm2_createprimary_ecc(self, TPM2_RH_ENDORSEMENT, keyflags,
39✔
1194
                                       symkeydata, symkeydata_len,
1195
                                       authpolicy, authpolicy_len,
1196
                                       schemedata, schemedata_len,
1197
                                       TPM2_ECC_NIST_P384, TPM2_ALG_SHA384,
1198
                                       NONCE_EMPTY, sizeof(NONCE_EMPTY), off, curr_handle,
1199
                                       ektemplate, ektemplate_len, ekparam, key_description);
1200
    if (ret != 0)
39✔
1201
       logerr(self->logfile, "%s failed\n", __func__);
×
1202

1203
    return ret;
39✔
1204
}
1205

1206
/* Create an ECC or RSA EK */
1207
static int swtpm_tpm2_create_ek(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize,
78✔
1208
                                gboolean allowsigning, gboolean decryption, gboolean lock_nvram,
1209
                                gchar **ekparam, const  gchar **key_description)
1210
{
1211
    uint32_t tpm2_ek_handle, nvindex, curr_handle;
78✔
1212
    const char *keytype;
78✔
1213
    int ret;
78✔
1214
    unsigned char ektemplate[512];
78✔
1215
    size_t ektemplate_len = sizeof(ektemplate);
78✔
1216

1217
    if (isecc) {
78✔
1218
        tpm2_ek_handle = TPM2_EK_ECC_SECP384R1_HANDLE;
1219
        keytype = "ECC";
1220
        nvindex = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE;
1221
    } else {
1222
        if (rsa_keysize == 2048) {
39✔
1223
            tpm2_ek_handle = TPM2_EK_RSA_HANDLE;
1224
            keytype = "RSA 2048";
1225
            nvindex = TPM2_NV_INDEX_RSA2048_EKTEMPLATE;
1226
        } else if (rsa_keysize == 3072) {
12✔
1227
            tpm2_ek_handle = TPM2_EK_RSA3072_HANDLE;
1228
            keytype = "RSA 3072";
1229
            nvindex = TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE;
1230
        } else {
1231
            logerr(self->logfile, "Internal error: Unsupported RSA keysize %u.\n", rsa_keysize);
×
1232
            return 1;
×
1233
        }
1234
    }
1235
    if (isecc)
78✔
1236
        ret = swtpm_tpm2_createprimary_ek_ecc_nist_p384(self, allowsigning, decryption, &curr_handle,
39✔
1237
                                                        ektemplate, &ektemplate_len, ekparam,
1238
                                                        key_description);
1239
    else
1240
        ret = swtpm_tpm2_createprimary_ek_rsa(self, rsa_keysize, allowsigning, decryption, &curr_handle,
39✔
1241
                                              ektemplate, &ektemplate_len, ekparam, key_description);
1242

1243
    if (ret == 0)
78✔
1244
        ret = swtpm_tpm2_evictcontrol(self, curr_handle, tpm2_ek_handle);
78✔
1245
    if (ret != 0) {
78✔
1246
        logerr(self->logfile, "create_ek failed: 0x%x\n", ret);
×
1247
        return 1;
×
1248
    }
1249

1250
    logit(self->logfile,
78✔
1251
          "Successfully created %s EK with handle 0x%x.\n", keytype, tpm2_ek_handle);
1252

1253
    if (allowsigning) {
78✔
1254
        uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE | \
44✔
1255
                TPMA_NV_AUTHREAD | \
1256
                TPMA_NV_OWNERREAD | \
1257
                TPMA_NV_PPREAD | \
1258
                TPMA_NV_PPWRITE | \
1259
                TPMA_NV_NO_DA | \
1260
                TPMA_NV_WRITEDEFINE;
1261
        ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, ektemplate, ektemplate_len,
44✔
1262
                                     lock_nvram, "EK template");
1263
        if (ret == 0)
44✔
1264
            logit(self->logfile,
44✔
1265
                  "Successfully created NVRAM area 0x%x for %s EK template.\n",
1266
                  nvindex, keytype);
1267
    }
1268

1269
    return ret;
1270
}
1271

1272
static int swtpm_tpm2_nvdefinespace(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
143✔
1273
                                    uint16_t data_len)
1274
{
1275
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_DEFINESPACE);
143✔
1276
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0);
143✔
1277
    g_autofree unsigned char *nvpublic = NULL;
286✔
1278
    ssize_t nvpublic_len;
143✔
1279
    g_autofree unsigned char *req = NULL;
143✔
1280
    ssize_t req_len;
143✔
1281

1282
    nvpublic_len = memconcat(&nvpublic,
286✔
1283
                             (unsigned char[]){
143✔
1284
                                 AS4BE(nvindex), AS2BE(TPM2_ALG_SHA256), AS4BE(nvindexattrs),
143✔
1285
                                 AS2BE(0), AS2BE(data_len)}, (size_t)14,
1286
                             NULL);
1287
    if (nvpublic_len < 0) {
143✔
1288
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1289
        return 1;
×
1290
    }
1291

1292
    req_len = memconcat(&req,
286✔
1293
                        &hdr, sizeof(hdr),
1294
                        (unsigned char[]){AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))}, (size_t)8,
143✔
1295
                        &authblock, sizeof(authblock),
1296
                        (unsigned char[]){AS2BE(0), AS2BE(nvpublic_len)}, (size_t)4,
143✔
1297
                        nvpublic, nvpublic_len,
1298
                        NULL);
1299
    if (req_len < 0) {
143✔
1300
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1301
        return 1;
×
1302
    }
1303

1304
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
143✔
1305

1306
    return transfer(self, req, req_len, "TPM2_NV_DefineSpace", FALSE,
143✔
1307
                    NULL, NULL, TPM2_DURATION_SHORT);
1308
}
1309

1310
/* Write the data into the given NVIndex */
1311
static int swtpm_tpm2_nv_write(struct swtpm *self, uint32_t nvindex,
143✔
1312
                               const unsigned char *data, size_t data_len)
1313
{
1314
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITE);
143✔
1315
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0);
143✔
1316
    g_autofree unsigned char *req = NULL;
286✔
1317
    ssize_t req_len;
143✔
1318
    size_t offset = 0, txlen;
143✔
1319
    int ret;
143✔
1320

1321
    while (offset < data_len) {
288✔
1322
        txlen = min(data_len - offset, 1024);
145✔
1323

1324
        g_free(req);
145✔
1325
        req_len = memconcat(&req,
290✔
1326
                            &hdr, sizeof(hdr),
1327
                            (unsigned char[]){
145✔
1328
                                AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
145✔
1329
                            }, (size_t)12,
1330
                            &authblock, sizeof(authblock),
1331
                            (unsigned char[]){AS2BE(txlen)}, (size_t)2,
145✔
1332
                            &data[offset], txlen,
1333
                            (unsigned char[]){AS2BE(offset)}, (size_t)2,
145✔
1334
                            NULL);
1335
        if (req_len < 0) {
145✔
1336
            logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1337
            return 1;
×
1338
        }
1339
        ((struct tpm_req_header *)req)->size = htobe32(req_len);
145✔
1340

1341
        ret = transfer(self, req, req_len, "TPM2_NV_Write", FALSE,
145✔
1342
                       NULL, NULL, TPM2_DURATION_SHORT);
1343
        if (ret != 0)
145✔
1344
            return 1;
1345

1346
        offset += txlen;
145✔
1347
    }
1348
    return 0;
1349
}
1350

1351
static int swtpm_tpm2_nv_writelock(struct swtpm *self, uint32_t nvindex)
9✔
1352
{
1353
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITELOCK);
9✔
1354
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0);
9✔
1355
    g_autofree unsigned char *req;
18✔
1356
    ssize_t req_len;
9✔
1357

1358
    req_len = memconcat(&req,
18✔
1359
                        &hdr, sizeof(hdr),
1360
                        (unsigned char[]){
9✔
1361
                           AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
9✔
1362
                        }, (size_t)12,
1363
                        &authblock, sizeof(authblock),
1364
                        NULL);
1365
    if (req_len < 0) {
9✔
1366
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1367
        return 1;
×
1368
    }
1369

1370
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
9✔
1371

1372
    return transfer(self, req, req_len, "TPM2_NV_WriteLock", FALSE,
9✔
1373
                    NULL, NULL, TPM2_DURATION_SHORT);
1374
}
1375

1376
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
143✔
1377
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
1378
                                  const char *certtype)
1379
{
1380
    int ret = swtpm_tpm2_nvdefinespace(self, nvindex, nvindexattrs, data_len);
143✔
1381
    if (ret != 0) {
143✔
1382
        logerr(self->logfile, "Could not create NVRAM area 0x%x for %s.\n", nvindex, certtype);
×
1383
        return 1;
×
1384
    }
1385

1386
    ret = swtpm_tpm2_nv_write(self, nvindex, data, data_len);
143✔
1387
    if (ret != 0) {
143✔
1388
        logerr(self->logfile,
×
1389
               "Could not write %s into NVRAM area 0x%x.\n", certtype, nvindex);
1390
        return 1;
×
1391
    }
1392

1393
    if (lock_nvram) {
143✔
1394
        ret = swtpm_tpm2_nv_writelock(self, nvindex);
9✔
1395
        if (ret != 0) {
9✔
1396
            logerr(self->logfile, "Could not lock EK template NVRAM area 0x%x.\n", nvindex);
×
1397
            return 1;
×
1398
        }
1399
    }
1400

1401
    return 0;
1402
}
1403

1404
static int swtpm_tpm2_write_cert_nvram(struct swtpm *self, uint32_t nvindex,
99✔
1405
                                       uint32_t nvindexattrs,
1406
                                       const unsigned char *data, size_t data_len,
1407
                                       gboolean lock_nvram, const char *keytype,
1408
                                       const char *certtype)
1409
{
1410
    int ret;
99✔
1411

1412
    ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, data, data_len, lock_nvram,
99✔
1413
                                 certtype);
1414
    if (ret == 0)
99✔
1415
        logit(self->logfile,
99✔
1416
              "Successfully created NVRAM area 0x%x for %s%s.\n",
1417
              nvindex, keytype, certtype);
1418

1419
    return ret;
99✔
1420
}
1421

1422
/* Write the platform certificate into an NVRAM area */
1423
static int swtpm_tpm2_write_ek_cert_nvram(struct swtpm *self, gboolean isecc,
66✔
1424
                                           unsigned int rsa_keysize, gboolean lock_nvram,
1425
                                           const unsigned char *data, size_t data_len)
1426
{
1427
    uint32_t nvindex = 0;
66✔
1428
    g_autofree gchar *keytype = NULL;
132✔
1429
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
66✔
1430
            TPMA_NV_AUTHREAD |
1431
            TPMA_NV_OWNERREAD |
1432
            TPMA_NV_PPREAD |
1433
            TPMA_NV_PPWRITE |
1434
            TPMA_NV_NO_DA |
1435
            TPMA_NV_WRITEDEFINE;
1436

1437
    if (!isecc) {
66✔
1438
        if (rsa_keysize == 2048)
33✔
1439
            nvindex = TPM2_NV_INDEX_RSA2048_EKCERT;
1440
        else if (rsa_keysize == 3072)
10✔
1441
            nvindex = TPM2_NV_INDEX_RSA3072_HI_EKCERT;
10✔
1442
        keytype = g_strdup_printf("RSA %d ", rsa_keysize);
33✔
1443
    } else {
1444
        nvindex = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT;
33✔
1445
        keytype = g_strdup("ECC ");
33✔
1446
    }
1447

1448
    return swtpm_tpm2_write_cert_nvram(self, nvindex, nvindexattrs, data, data_len,
66✔
1449
                                       lock_nvram, keytype, "EK certificate");
1450
}
1451

1452
static int swtpm_tpm2_write_platform_cert_nvram(struct swtpm *self, gboolean lock_nvram,
33✔
1453
                                                const unsigned char *data, size_t data_len)
1454
{
1455
    uint32_t nvindex = TPM2_NV_INDEX_PLATFORMCERT;
33✔
1456
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
33✔
1457
            TPMA_NV_AUTHREAD |
1458
            TPMA_NV_OWNERREAD |
1459
            TPMA_NV_PPREAD |
1460
            TPMA_NV_PPWRITE |
1461
            TPMA_NV_NO_DA |
1462
            TPMA_NV_WRITEDEFINE;
1463

1464
    return swtpm_tpm2_write_cert_nvram(self, nvindex, nvindexattrs, data, data_len,
33✔
1465
                                       lock_nvram, "", "platform certificate");
1466
}
1467

1468
static const struct swtpm2_ops swtpm_tpm2_ops = {
1469
    .shutdown = swtpm_tpm2_shutdown,
1470
    .create_spk = swtpm_tpm2_create_spk,
1471
    .create_ek = swtpm_tpm2_create_ek,
1472
    .get_all_pcr_banks = swtpm_tpm2_get_all_pcr_banks,
1473
    .set_active_pcr_banks = swtpm_tpm2_set_active_pcr_banks,
1474
    .write_ek_cert_nvram = swtpm_tpm2_write_ek_cert_nvram,
1475
    .write_platform_cert_nvram = swtpm_tpm2_write_platform_cert_nvram,
1476
};
1477

1478
/*
1479
 * TPM 1.2 support
1480
 */
1481
#define TPM_TAG_RQU_COMMAND       0x00c1
1482
#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
1483

1484
#define TPM_ORD_OIAP                     0x0000000A
1485
#define TPM_ORD_TAKE_OWNERSHIP           0x0000000D
1486
#define TPM_ORD_PHYSICAL_ENABLE          0x0000006F
1487
#define TPM_ORD_PHYSICAL_SET_DEACTIVATED 0x00000072
1488
#define TPM_ORD_NV_DEFINE_SPACE          0x000000CC
1489
#define TPM_ORD_NV_WRITE_VALUE           0x000000CD
1490
#define TSC_ORD_PHYSICAL_PRESENCE        0x4000000A
1491

1492
#define TPM_ST_CLEAR 0x0001
1493

1494
#define TPM_PHYSICAL_PRESENCE_CMD_ENABLE  0x0020
1495
#define TPM_PHYSICAL_PRESENCE_PRESENT     0x0008
1496

1497
#define TPM_ALG_RSA 0x00000001
1498

1499
#define TPM_KEY_STORAGE 0x0011
1500

1501
#define TPM_AUTH_ALWAYS 0x01
1502

1503
#define TPM_PID_OWNER  0x0005
1504

1505
#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003
1506
#define TPM_SS_NONE 0x0001
1507

1508
#define TPM_TAG_PCR_INFO_LONG   0x0006
1509
#define TPM_TAG_NV_ATTRIBUTES   0x0017
1510
#define TPM_TAG_NV_DATA_PUBLIC  0x0018
1511
#define TPM_TAG_KEY12           0x0028
1512

1513
#define TPM_LOC_ZERO   0x01
1514
#define TPM_LOC_ALL    0x1f
1515

1516
#define TPM_NV_INDEX_D_BIT        0x10000000
1517
#define TPM_NV_INDEX_EKCERT       0xF000
1518
#define TPM_NV_INDEX_PLATFORMCERT 0xF002
1519

1520
#define TPM_NV_INDEX_LOCK 0xFFFFFFFF
1521

1522
#define TPM_NV_PER_OWNERREAD   0x00020000
1523
#define TPM_NV_PER_OWNERWRITE  0x00000002
1524

1525
#define TPM_ET_OWNER 0x02
1526
#define TPM_ET_NV    0x0b
1527

1528
#define TPM_KH_EK    0x40000006
1529

1530
#define TPM_DURATION_SHORT     2000  /* ms */
1531
#define TPM_DURATION_MEDIUM    7500  /* ms */
1532
#define TPM_DURATION_LONG     15000  /* ms */
1533

1534
static int swtpm_tpm12_tsc_physicalpresence(struct swtpm *self, uint16_t physicalpresence)
52✔
1535
{
1536
    struct tpm12_tsc_physicalpresence {
52✔
1537
        struct tpm_req_header hdr;
1538
        uint16_t pp;
1539
    } req = {
52✔
1540
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TSC_ORD_PHYSICAL_PRESENCE),
52✔
1541
        .pp = htobe16(physicalpresence),
52✔
1542
    };
1543

1544
    /* use medium duration to avoid t/o on busy system */
1545
    return transfer(self, &req, sizeof(req), "TSC_PhysicalPresence", FALSE,
52✔
1546
                    NULL, NULL, TPM_DURATION_MEDIUM);
1547
}
1548

1549
static int swtpm_tpm12_physical_enable(struct swtpm *self)
26✔
1550
{
1551
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_ENABLE);
26✔
1552

1553
    return transfer(self, &req, sizeof(req), "TPM_PhysicalEnable", FALSE,
26✔
1554
                    NULL, NULL, TPM_DURATION_SHORT);
1555
}
1556

1557
static int swtpm_tpm12_physical_set_deactivated(struct swtpm *self, uint8_t state)
26✔
1558
{
1559
    struct tpm12_tsc_physical_set_deactivated {
26✔
1560
        struct tpm_req_header hdr;
1561
        uint8_t state;
1562
    } req = {
26✔
1563
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_SET_DEACTIVATED),
26✔
1564
        .state = state,
1565
    };
1566

1567
    return transfer(self, &req, sizeof(req), "TSC_PhysicalSetDeactivated", FALSE,
26✔
1568
                    NULL, NULL, TPM_DURATION_SHORT);
1569
}
1570

1571
/* Initialize the TPM1.2 */
1572
static int swtpm_tpm12_run_swtpm_bios(struct swtpm *self)
26✔
1573
{
1574
    if (swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_CMD_ENABLE) ||
52✔
1575
        swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_PRESENT) ||
52✔
1576
        swtpm_tpm12_physical_enable(self) ||
52✔
1577
        swtpm_tpm12_physical_set_deactivated(self, 0))
26✔
1578
        return 1;
×
1579

1580
    return 0;
1581
}
1582

1583
static int swptm_tpm12_create_endorsement_keypair(struct swtpm *self,
19✔
1584
                                                  gchar **pubek, size_t *pubek_len)
1585
{
1586
    unsigned char req[] = {
19✔
1587
        0x00, 0xc1, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x78, 0x38, 0xf0, 0x30, 0x81, 0x07, 0x2b,
1588
        0x0c, 0xa9, 0x10, 0x98, 0x08, 0xc0, 0x4B, 0x05, 0x11, 0xc9, 0x50, 0x23, 0x52, 0xc4, 0x00, 0x00,
1589
        0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1590
        0x00, 0x02, 0x00, 0x00, 0x00, 0x00
1591
    };
1592
    unsigned char tpmresp[512];
19✔
1593
    size_t tpmresp_len = sizeof(tpmresp);
19✔
1594
    uint32_t length;
19✔
1595
    int ret;
19✔
1596

1597
    ret = transfer(self, &req, sizeof(req), "TPM_CreateEndorsementKeyPair", FALSE,
19✔
1598
                   &tpmresp, &tpmresp_len, TPM_DURATION_LONG);
1599
    if (ret != 0)
19✔
1600
        return 1;
1601

1602
    if (tpmresp_len < 34 + sizeof(length))
19✔
1603
        goto err_too_short;
×
1604
    memcpy(&length, &tpmresp[34], sizeof(length));
19✔
1605
    length = be32toh(length);
19✔
1606
    if (length != 256) {
19✔
1607
        logerr(self->logfile, "Offset to EK Public key is wrong.\n");
×
1608
        return 1;
×
1609
    }
1610

1611
    *pubek_len = 256;
19✔
1612
    if (tpmresp_len < 38 + *pubek_len)
19✔
1613
        goto err_too_short;
×
1614
    *pubek = g_malloc(256);
19✔
1615
    memcpy(*pubek, &tpmresp[38], *pubek_len);
19✔
1616

1617
    return 0;
19✔
1618

1619
err_too_short:
×
1620
    logerr(self->logfile, "Response from TPM_CreateEndorsementKeyPair is too short!\n");
×
1621
    return 1;
×
1622
}
1623

1624
/* Create an OIAP session */
1625
static int swtpm_tpm12_oiap(struct swtpm *self, uint32_t *authhandle, unsigned char nonce_even[SHA_DIGEST_LENGTH])
9✔
1626
{
1627
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_OIAP);
9✔
1628
    unsigned char tpmresp[64];
9✔
1629
    size_t tpmresp_len = sizeof(tpmresp);
9✔
1630
    int ret;
9✔
1631

1632
    ret = transfer(self, &req, sizeof(req), "TPM_OIAP", FALSE,
9✔
1633
                   &tpmresp, &tpmresp_len, TPM_DURATION_SHORT);
1634
    if (ret != 0)
9✔
1635
        return ret;
1636

1637
    if (tpmresp_len < 10 + sizeof(*authhandle) || tpmresp_len < 14 + SHA_DIGEST_LENGTH)
9✔
1638
        goto err_too_short;
×
1639
    memcpy(authhandle, &tpmresp[10], sizeof(*authhandle));
9✔
1640
    *authhandle = be32toh(*authhandle);
9✔
1641
    memcpy(nonce_even, &tpmresp[14], SHA_DIGEST_LENGTH);
9✔
1642

1643
    return 0;
9✔
1644

1645
err_too_short:
×
1646
    logerr(self->logfile, "Response from TPM_OIAP is too short!\n");
×
1647
    return 1;
×
1648
}
1649

1650
static int swtpm_tpm12_take_ownership(struct swtpm *self, const unsigned char ownerpass_digest[SHA_DIGEST_LENGTH],
9✔
1651
                                      const unsigned char srkpass_digest[SHA_DIGEST_LENGTH],
1652
                                      const unsigned char *pubek, size_t pubek_len)
1653
{
1654
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_AUTH1_COMMAND, 0, TPM_ORD_TAKE_OWNERSHIP);
9✔
1655
    EVP_PKEY *pkey = NULL;
9✔
1656
    EVP_PKEY_CTX *ctx = NULL;
9✔
1657
    BIGNUM *exp = BN_new();
9✔
1658
    BIGNUM *mod = NULL;
9✔
1659
#if OPENSSL_VERSION_NUMBER < 0x30000000L
1660
    RSA *rsakey = RSA_new();
1661
#endif
1662
    int ret = 1;
9✔
1663
    const EVP_MD *sha1 = EVP_sha1();
9✔
1664
    g_autofree unsigned char *enc_owner_auth = g_malloc(pubek_len);
9✔
1665
    size_t enc_owner_auth_len = pubek_len;
9✔
1666
    g_autofree unsigned char *enc_srk_auth = g_malloc(pubek_len);
18✔
1667
    size_t enc_srk_auth_len = pubek_len;
9✔
1668
    uint32_t auth_handle;
9✔
1669
    unsigned char nonce_even[SHA_DIGEST_LENGTH];
9✔
1670
    unsigned char nonce_odd[SHA_DIGEST_LENGTH] = {1, 2, 3, 4, 5, 6, };
9✔
1671
    g_autofree unsigned char *tpm_rsa_key_parms = NULL;
9✔
1672
    ssize_t tpm_rsa_key_parms_len;
9✔
1673
    g_autofree unsigned char *tpm_key_parms = NULL;
9✔
1674
    ssize_t tpm_key_parms_len;
9✔
1675
    g_autofree unsigned char *tpm_key12 = NULL;
9✔
1676
    ssize_t tpm_key12_len;
9✔
1677
    g_autofree unsigned char *in_auth_setup_params = NULL;
9✔
1678
    ssize_t in_auth_setup_params_len;
9✔
1679
    g_autofree unsigned char *macinput = NULL;
9✔
1680
    ssize_t macinput_len;
9✔
1681
    unsigned char in_param_digest[SHA_DIGEST_LENGTH];
9✔
1682
    unsigned char owner_auth[SHA_DIGEST_LENGTH];
9✔
1683
    unsigned int owner_auth_len = sizeof(owner_auth);
9✔
1684
    uint8_t continue_auth_session = 0;
9✔
1685
    unsigned char req[1024];
9✔
1686
    ssize_t req_len, len;
9✔
1687
    struct tpm_req_header *trh;
9✔
1688

1689
    mod = BN_bin2bn((const unsigned char *)pubek, pubek_len, NULL);
9✔
1690
    if (exp == NULL || mod == NULL ||
18✔
1691
        BN_hex2bn(&exp, "10001") == 0) {
9✔
1692
        logerr(self->logfile, "Could not create public RSA key!\n");
×
1693
        goto error_free_bn;
×
1694
    }
1695

1696
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1697
    ctx = EVP_PKEY_CTX_new_from_name(NULL, "rsa", NULL);
9✔
1698
    if (ctx != NULL) {
9✔
1699
        OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
9✔
1700
        OSSL_PARAM *params;
9✔
1701

1702
        if (bld == NULL ||
18✔
1703
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, exp) != 1 ||
18✔
1704
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, mod) != 1 ||
9✔
1705
            (params = OSSL_PARAM_BLD_to_param(bld)) == NULL) {
9✔
1706
            OSSL_PARAM_BLD_free(bld);
×
1707
            goto error_free_bn;
×
1708
        }
1709
        OSSL_PARAM_BLD_free(bld);
9✔
1710

1711
        if (EVP_PKEY_fromdata_init(ctx) != 1 ||
18✔
1712
            EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) != 1) {
9✔
1713
            logerr(self->logfile, "Could not set pkey parameters!\n");
×
1714
            OSSL_PARAM_free(params);
×
1715
            goto error_free_bn;
×
1716
        }
1717
        OSSL_PARAM_free(params);
9✔
1718

1719
        EVP_PKEY_CTX_free(ctx);
9✔
1720
    } else {
1721
        logerr(self->logfile, "Could not create key creation context!\n");
×
1722
        goto error_free_bn;
×
1723
    }
1724
    ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
9✔
1725
    if (ctx == NULL)
9✔
1726
        goto error_free_bn;
×
1727
#else
1728
    pkey = EVP_PKEY_new();
1729
    if (pkey == NULL) {
1730
        logerr(self->logfile, "Could not allocate pkey!\n");
1731
        goto error_free_bn;
1732
    }
1733

1734
# if OPENSSL_VERSION_NUMBER < 0x10100000
1735
    rsakey->n = mod;
1736
    rsakey->e = exp;
1737
# else
1738
    if (RSA_set0_key(rsakey, mod, exp, NULL) != 1) {
1739
        logerr(self->logfile, "Could not create public RSA key!\n");
1740
        goto error_free_bn;
1741
    }
1742
# endif
1743
    if (EVP_PKEY_assign_RSA(pkey, rsakey) != 1) {
1744
        logerr(self->logfile, "Could not create public RSA key!\n");
1745
        goto error_free_pkey_and_rsa;
1746
    }
1747

1748
    ctx = EVP_PKEY_CTX_new(pkey, NULL);
1749
    if (ctx == NULL)
1750
        goto error_free_pkey;
1751
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
1752

1753
    if (EVP_PKEY_encrypt_init(ctx) < 1 ||
18✔
1754
        EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) < 1 ||
18✔
1755
        EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sha1) < 1 ||
18✔
1756
        EVP_PKEY_CTX_set_rsa_oaep_md(ctx, sha1) < 1 ||
18✔
1757
        EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, g_strdup("TCPA"), 4) < 1 ||
18✔
1758
        EVP_PKEY_encrypt(ctx, enc_owner_auth, &enc_owner_auth_len,
9✔
1759
                         ownerpass_digest, SHA_DIGEST_LENGTH) < 1||
9✔
1760
        EVP_PKEY_encrypt(ctx, enc_srk_auth, &enc_srk_auth_len,
9✔
1761
                         srkpass_digest, SHA_DIGEST_LENGTH) < 1) {
1762
        logerr(self->logfile, "Internal error in %s: encryption failed\n", __func__);
×
1763
        goto error;
×
1764
    }
1765
    ret = swtpm_tpm12_oiap(self, &auth_handle, nonce_even);
9✔
1766
    if (ret != 0)
9✔
1767
        goto error;
×
1768

1769
    tpm_rsa_key_parms_len = memconcat(&tpm_rsa_key_parms,
18✔
1770
                                      (unsigned char[]){
9✔
1771
                                          AS4BE(2048), AS4BE(2), AS4BE(0)
1772
                                      }, (size_t)12,
1773
                                      NULL);
1774
    if (tpm_rsa_key_parms_len < 0) {
9✔
1775
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1776
        goto error;
×
1777
    }
1778

1779
    tpm_key_parms_len = memconcat(&tpm_key_parms,
18✔
1780
                                  (unsigned char[]){
9✔
1781
                                      AS4BE(TPM_ALG_RSA),
1782
                                      AS2BE(TPM_ES_RSAESOAEP_SHA1_MGF1),
1783
                                      AS2BE(TPM_SS_NONE),
1784
                                      AS4BE(tpm_rsa_key_parms_len)}, (size_t)12,
9✔
1785
                                  tpm_rsa_key_parms, tpm_rsa_key_parms_len,
1786
                                  NULL);
1787
    if (tpm_key_parms_len < 0) {
9✔
1788
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1789
        goto error;
×
1790
    }
1791

1792
    tpm_key12_len = memconcat(&tpm_key12,
18✔
1793
                              (unsigned char[]){
9✔
1794
                                  AS2BE(TPM_TAG_KEY12), AS2BE(0),
1795
                                  AS2BE(TPM_KEY_STORAGE), AS4BE(0), TPM_AUTH_ALWAYS
1796
                              }, (size_t)11,
1797
                              tpm_key_parms, tpm_key_parms_len,
1798
                              (unsigned char[]){AS4BE(0), AS4BE(0), AS4BE(0)}, (size_t)12,
9✔
1799
                              NULL);
1800
    if (tpm_key12_len < 0) {
9✔
1801
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1802
        goto error;
×
1803
    }
1804

1805
    req_len = concat(req, sizeof(req),
18✔
1806
                     &hdr, sizeof(hdr),
1807
                     (unsigned char[]){AS2BE(TPM_PID_OWNER), AS4BE(enc_owner_auth_len)}, (size_t)6,
9✔
1808
                     enc_owner_auth, enc_owner_auth_len,
1809
                     (unsigned char[]){AS4BE(enc_srk_auth_len)}, (size_t)4,
9✔
1810
                     enc_srk_auth, enc_srk_auth_len,
1811
                     tpm_key12, tpm_key12_len,
1812
                     NULL);
1813
    if (req_len < 0) {
9✔
1814
        logerr(self->logfile, "Internal error in %s: req is too small\n");
×
1815
        goto error;
×
1816
    }
1817
    SHA1(&req[6], req_len - 6, in_param_digest);
9✔
1818

1819
    in_auth_setup_params_len = memconcat(&in_auth_setup_params,
9✔
1820
                                         nonce_even, sizeof(nonce_even),
1821
                                         nonce_odd, sizeof(nonce_odd),
1822
                                         &continue_auth_session, (size_t)1,
1823
                                         NULL);
1824
    if (in_auth_setup_params_len < 0) {
9✔
1825
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1826
        goto error;
×
1827
    }
1828

1829
    macinput_len = memconcat(&macinput,
9✔
1830
                             in_param_digest, sizeof(in_param_digest),
1831
                             in_auth_setup_params, in_auth_setup_params_len,
1832
                             NULL);
1833
    if (macinput_len < 0) {
9✔
1834
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1835
        goto error;
×
1836
    }
1837

1838
    HMAC(sha1, ownerpass_digest, SHA_DIGEST_LENGTH, macinput, macinput_len,
9✔
1839
         owner_auth, &owner_auth_len);
1840

1841
    len = concat(&req[req_len], sizeof(req) - req_len,
18✔
1842
                 (unsigned char[]){AS4BE(auth_handle)}, (size_t)4,
9✔
1843
                 nonce_odd, sizeof(nonce_odd),
1844
                 &continue_auth_session, (size_t)1,
1845
                 owner_auth, owner_auth_len,
1846
                 NULL);
1847
    if (len < 0) {
9✔
1848
        logerr(self->logfile, "Internal error in %s: req is too small\n");
×
1849
        goto error;
×
1850
    }
1851
    req_len += len;
9✔
1852

1853
    trh = (struct tpm_req_header *)req; /* old gcc type-punned pointer */
9✔
1854
    trh->size = htobe32(req_len);
9✔
1855

1856
    ret = transfer(self, req, req_len, "TPM_TakeOwnership", FALSE,
9✔
1857
                   NULL, NULL, TPM_DURATION_LONG);
1858

1859
error:
9✔
1860
    EVP_PKEY_free(pkey);
9✔
1861
    EVP_PKEY_CTX_free(ctx);
9✔
1862
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1863
    BN_free(exp);
9✔
1864
    BN_free(mod);
9✔
1865
#endif
1866
    return ret;
9✔
1867

1868
error_free_bn:
×
1869
    BN_free(exp);
×
1870
    BN_free(mod);
×
1871

1872
#if OPENSSL_VERSION_NUMBER < 0x30000000L
1873
error_free_pkey_and_rsa:
1874
    RSA_free(rsakey);
1875
error_free_pkey:
1876
#else
1877
    EVP_PKEY_CTX_free(ctx);
×
1878
#endif
1879
    EVP_PKEY_free(pkey);
×
1880

1881
    return 1;
×
1882
}
1883

1884
static int swtpm_tpm12_nv_define_space(struct swtpm *self, uint32_t nvindex,
27✔
1885
                                       uint32_t nvindexattrs, size_t size)
1886
{
1887
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_DEFINE_SPACE);
27✔
1888
    g_autofree unsigned char *pcr_info_short = NULL;
54✔
1889
    ssize_t pcr_info_short_len;
27✔
1890
    g_autofree unsigned char *nv_data_public = NULL;
27✔
1891
    ssize_t nv_data_public_len;
27✔
1892
    g_autofree unsigned char *req = NULL;
27✔
1893
    ssize_t req_len;
27✔
1894
    unsigned char zeroes[SHA_DIGEST_LENGTH] = {0, };
27✔
1895

1896
    pcr_info_short_len = memconcat(&pcr_info_short,
54✔
1897
                                   (unsigned char[]){AS2BE(3), 0, 0, 0, TPM_LOC_ALL}, (size_t)6,
27✔
1898
                                   zeroes, sizeof(zeroes),
1899
                                   NULL);
1900
    if (pcr_info_short_len < 0) {
27✔
1901
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1902
        return 1;
×
1903
    }
1904

1905
    nv_data_public_len = memconcat(&nv_data_public,
54✔
1906
                                   (unsigned char[]){
27✔
1907
                                       AS2BE(TPM_TAG_NV_DATA_PUBLIC), AS4BE(nvindex)
27✔
1908
                                   }, (size_t)6,
1909
                                   pcr_info_short, pcr_info_short_len,
1910
                                   pcr_info_short, pcr_info_short_len,
1911
                                   (unsigned char[]){
27✔
1912
                                       AS2BE(TPM_TAG_NV_ATTRIBUTES), AS4BE(nvindexattrs),
27✔
1913
                                       0, 0, 0, AS4BE(size)
27✔
1914
                                   }, (size_t)13,
1915
                                   NULL);
1916
    if (nv_data_public_len < 0) {
27✔
1917
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1918
        return 1;
×
1919
    }
1920

1921
    req_len = memconcat(&req,
27✔
1922
                        &hdr, sizeof(hdr),
1923
                        nv_data_public, nv_data_public_len,
1924
                        zeroes, sizeof(zeroes),
1925
                        NULL);
1926
    if (req_len < 0) {
27✔
1927
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1928
        return 1;
×
1929
    }
1930

1931
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
27✔
1932

1933
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE,
27✔
1934
                    NULL, NULL, TPM_DURATION_SHORT);
1935
}
1936

1937
static int swtpm_tpm12_nv_write_value(struct swtpm *self, uint32_t nvindex,
15✔
1938
                                      const unsigned char *data, size_t data_len)
1939
{
1940
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_WRITE_VALUE);
15✔
1941
    g_autofree unsigned char *req = NULL;
30✔
1942
    ssize_t req_len;
15✔
1943

1944
    req_len = memconcat(&req,
30✔
1945
                        &hdr, sizeof(hdr),
1946
                        (unsigned char[]){AS4BE(nvindex), AS4BE(0), AS4BE(data_len)}, (size_t)12,
15✔
1947
                        data, data_len,
1948
                        NULL);
1949
    if (req_len < 0) {
15✔
1950
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1951
        return 1;
×
1952
    }
1953

1954
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
15✔
1955

1956
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE,
15✔
1957
                    NULL, NULL, TPM_DURATION_SHORT);
1958
}
1959

1960
/* Write the EK Certificate into NVRAM */
1961
static int swtpm_tpm12_write_ek_cert_nvram(struct swtpm *self,
8✔
1962
                                           const unsigned char *data, size_t data_len)
1963
{
1964
    uint32_t nvindex = TPM_NV_INDEX_EKCERT | TPM_NV_INDEX_D_BIT;
8✔
1965
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
8✔
1966
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
1967
    if (ret != 0)
8✔
1968
        return 1;
1969

1970
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
8✔
1971
    if (ret != 0)
8✔
1972
        return 1;
×
1973

1974
    return 0;
1975
}
1976

1977
/* Write the Platform Certificate into NVRAM */
1978
static int swtpm_tpm12_write_platform_cert_nvram(struct swtpm *self,
7✔
1979
                                                 const unsigned char *data, size_t data_len)
1980
{
1981
    uint32_t nvindex = TPM_NV_INDEX_PLATFORMCERT | TPM_NV_INDEX_D_BIT;
7✔
1982
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
7✔
1983
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
1984
    if (ret != 0)
7✔
1985
        return 1;
1986

1987
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
7✔
1988
    if (ret != 0)
7✔
1989
        return 1;
×
1990

1991
    return 0;
1992
}
1993

1994
static int swtpm_tpm12_nv_lock(struct swtpm *self)
12✔
1995
{
1996
    return swtpm_tpm12_nv_define_space(self, TPM_NV_INDEX_LOCK, 0, 0);
12✔
1997
}
1998

1999
static const struct swtpm12_ops swtpm_tpm12_ops = {
2000
    .run_swtpm_bios = swtpm_tpm12_run_swtpm_bios,
2001
    .create_endorsement_key_pair = swptm_tpm12_create_endorsement_keypair,
2002
    .take_ownership = swtpm_tpm12_take_ownership,
2003
    .write_ek_cert_nvram = swtpm_tpm12_write_ek_cert_nvram,
2004
    .write_platform_cert_nvram = swtpm_tpm12_write_platform_cert_nvram,
2005
    .nv_lock = swtpm_tpm12_nv_lock,
2006
};
2007

2008
static void swtpm_init(struct swtpm *swtpm,
73✔
2009
                       gchar **swtpm_exec_l, const gchar *state_path,
2010
                       const gchar *keyopts, const gchar *logfile,
2011
                       int *fds_to_pass, size_t n_fds_to_pass,
2012
                       gboolean is_tpm2)
2013
{
2014
    swtpm->cops = &swtpm_cops;
73✔
2015
    swtpm->swtpm_exec_l = swtpm_exec_l;
73✔
2016
    swtpm->state_path = state_path;
73✔
2017
    swtpm->keyopts = keyopts;
73✔
2018
    swtpm->logfile = logfile;
73✔
2019
    swtpm->fds_to_pass = fds_to_pass;
73✔
2020
    swtpm->n_fds_to_pass = n_fds_to_pass;
73✔
2021
    swtpm->is_tpm2 = is_tpm2;
73✔
2022

2023
    swtpm->pid = -1;
73✔
2024
    swtpm->ctrl_fds[0] = swtpm->ctrl_fds[1] = -1;
73✔
2025
    swtpm->data_fds[0] = swtpm->data_fds[1] = -1;
73✔
2026
}
2027

2028
struct swtpm12 *swtpm12_new(gchar **swtpm_exec_l, const gchar *state_path,
26✔
2029
                            const gchar *keyopts, const gchar *logfile,
2030
                            int *fds_to_pass, size_t n_fds_to_pass)
2031
{
2032
    struct swtpm12 *swtpm12 = g_malloc0(sizeof(struct swtpm12));
26✔
2033

2034
    swtpm_init(&swtpm12->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
26✔
2035
               fds_to_pass, n_fds_to_pass, FALSE);
2036
    swtpm12->ops = &swtpm_tpm12_ops;
26✔
2037

2038
    return swtpm12;
26✔
2039
}
2040

2041
struct swtpm2 *swtpm2_new(gchar **swtpm_exec_l, const gchar *state_path,
47✔
2042
                         const gchar *keyopts, const gchar *logfile,
2043
                         int *fds_to_pass, size_t n_fds_to_pass)
2044
{
2045
    struct swtpm2 *swtpm2 = g_malloc0(sizeof(struct swtpm2));
47✔
2046

2047
    swtpm_init(&swtpm2->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
47✔
2048
               fds_to_pass, n_fds_to_pass, TRUE);
2049
    swtpm2->ops = &swtpm_tpm2_ops;
47✔
2050

2051
    return swtpm2;
47✔
2052
}
2053

2054
void swtpm_free(struct swtpm *swtpm) {
73✔
2055
    if (!swtpm)
73✔
2056
        return;
2057
    g_free(swtpm);
73✔
2058
}
2059

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