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

stefanberger / swtpm / #2824

13 May 2025 12:34PM UTC coverage: 72.964% (-0.5%) from 73.462%
#2824

push

travis-ci

web-flow
Merge c2b02e9b2 into 1544c99ca

7033 of 9639 relevant lines covered (72.96%)

13748.12 hits per line

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

81.23
/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 <stdio.h>
14
#include <stdint.h>
15
#include <string.h>
16
#include <sys/types.h>
17
#include <sys/socket.h>
18
#include <sys/stat.h>
19
#include <sys/wait.h>
20
#include <unistd.h>
21

22
#include <glib.h>
23

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

36
#include "swtpm.h"
37
#include "swtpm_utils.h"
38
#include "tpm_ioctl.h"
39
#include "sys_dependencies.h"
40

41
#define AS2BE(VAL) (((VAL) >> 8) & 0xff), ((VAL) & 0xff)
42
#define AS4BE(VAL) AS2BE((VAL) >> 16), AS2BE(VAL)
43
#define AS8BE(VAL) AS4BE((VAL) >> 32), AS4BE(VAL)
44

45
struct tpm_req_header {
46
    uint16_t tag;
47
    uint32_t size;
48
    uint32_t ordinal;
49
} __attribute__((packed));
50

51
struct tpm_resp_header {
52
    uint16_t tag;
53
    uint32_t size;
54
    uint32_t errcode;
55
} __attribute__((packed));
56

57
static int swtpm_start(struct swtpm *self)
72✔
58
{
59
    g_autofree gchar *tpmstate = g_strdup_printf("backend-uri=%s", self->state_path);
72✔
60
    g_autofree gchar *pidfile_arg = NULL;
72✔
61
    g_autofree gchar *server_fd = NULL;
72✔
62
    g_autofree gchar *ctrl_fd = NULL;
72✔
63
    g_autofree gchar *keyopts = NULL;
72✔
64
    g_autofree gchar *logop = NULL;
72✔
65
    g_autofree gchar **argv = NULL;
72✔
66
    struct stat statbuf;
72✔
67
    gboolean success;
72✔
68
    GError *error = NULL;
72✔
69
    GSpawnFlags flags;
72✔
70
    unsigned ctr;
72✔
71
    int pidfile_fd;
72✔
72
    int ret = 1;
72✔
73
    char pidfile[] = "/tmp/.swtpm_setup.pidfile.XXXXXX";
72✔
74

75
    pidfile_fd = mkstemp(pidfile);
72✔
76
    if (pidfile_fd < 0) {
72✔
77
        logerr(self->logfile, "Could not create pidfile: %s\n", strerror(errno));
×
78
        goto error_no_pidfile;
×
79
    }
80
    // pass filename rather than fd (Cygwin)
81
    pidfile_arg = g_strdup_printf("file=%s", pidfile);
72✔
82

83
    argv = concat_arrays(self->swtpm_exec_l,
144✔
84
                         (gchar*[]){
72✔
85
                              "--flags", "not-need-init,startup-clear",
86
                              "--tpmstate", tpmstate,
87
                              "--pid", pidfile_arg,
88
#if 0
89
                              "--log", "file=/tmp/log,level=20",
90
#endif
91
                              NULL
92
                         }, FALSE);
93

94
    if (self->is_tpm2)
72✔
95
        argv = concat_arrays(argv, (gchar*[]){"--tpm2", NULL}, TRUE);
46✔
96

97
    if (self->keyopts != NULL) {
72✔
98
        keyopts = g_strdup(self->keyopts);
30✔
99
        argv = concat_arrays(argv, (gchar*[]){"--key", keyopts, NULL}, TRUE);
30✔
100
    }
101

102
    if (gl_LOGFILE != NULL) {
72✔
103
        logop = g_strdup_printf("file=%s", gl_LOGFILE);
14✔
104
        argv = concat_arrays(argv, (gchar*[]){"--log", logop, NULL}, TRUE);
14✔
105
    }
106

107
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, self->ctrl_fds) != 0) {
72✔
108
        logerr(self->logfile, "Could not create socketpair: %s\n", strerror(errno));
×
109
        goto error;
×
110
    }
111
    ctrl_fd = g_strdup_printf("type=unixio,clientfd=%d", self->ctrl_fds[1]);
72✔
112

113
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, self->data_fds) != 0) {
72✔
114
        logerr(self->logfile, "Could not create socketpair: %s\n", strerror(errno));
×
115
        goto error;
×
116
    }
117
    server_fd = g_strdup_printf("type=tcp,fd=%d", self->data_fds[1]);
72✔
118

119
    argv = concat_arrays(argv, (gchar*[]){
72✔
120
                             "--server", server_fd,
121
                             "--ctrl", ctrl_fd,
122
                             NULL
123
                         }, TRUE);
124

125
#if 0
126
    {
127
        g_autofree gchar *join = g_strjoinv(" ", argv);
128
        logit(self->logfile, "Starting swtpm: %s\n", join);
129
    }
130
#endif
131

132
    flags = G_SPAWN_LEAVE_DESCRIPTORS_OPEN;
72✔
133
    if (gl_LOGFILE) {
72✔
134
        flags |= G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
14✔
135
    } else {
136
#if GLIB_CHECK_VERSION(2, 74, 0)
137
        flags |= G_SPAWN_CHILD_INHERITS_STDOUT | G_SPAWN_CHILD_INHERITS_STDERR;
138
#endif
139
    }
72✔
140

141
    success = g_spawn_async(NULL, argv, NULL, flags,
72✔
142
                            NULL, NULL, &self->pid, &error);
143
    if (!success) {
72✔
144
        logerr(self->logfile, "Could not start swtpm: %s\n", error->message);
×
145
        g_error_free(error);
×
146
        goto error;
×
147
    }
148

149
    /* wait until the pidfile is written to or swtpm terminates */
150
    for (ctr = 0; ctr < 1000; ctr++) {
437✔
151
        if (kill(self->pid, 0) < 0) {
437✔
152
            /* swtpm terminated */
153
            self->pid = 0;
×
154
            logerr(self->logfile, "swtpm process terminated unexpectedly.\n");
×
155
            self->cops->stop(self);
×
156
            goto error;
×
157
        }
158
        if (fstat(pidfile_fd, &statbuf) == 0 && statbuf.st_size > 0) {
437✔
159
            printf("TPM is listening on Unix socket.\n");
72✔
160
            ret = 0;
72✔
161
            break;
72✔
162
        }
163
        usleep(5000);
365✔
164
    }
165

166
error:
×
167
    close(pidfile_fd);
72✔
168
    unlink(pidfile);
72✔
169

170
error_no_pidfile:
72✔
171
    return ret;
72✔
172
}
173

174
/* Stop a running swtpm instance and close all the file descriptors connecting to it */
175
static void swtpm_stop(struct swtpm *self)
72✔
176
{
177
    unsigned c;
72✔
178
    gboolean ended = FALSE;
72✔
179

180
    if (self->pid > 0) {
72✔
181
        self->cops->ctrl_shutdown(self);
72✔
182
        for (c = 0; c < 500; c++) {
306✔
183
            if (kill(self->pid, 0) < 0) {
234✔
184
                ended = TRUE;
185
                break;
186
            }
187
            usleep(1000);
162✔
188
        }
189
        if (!ended)
72✔
190
            kill(self->pid, SIGKILL);
×
191
        waitpid(self->pid, NULL, 0);
72✔
192

193
        self->pid = 0;
72✔
194
    }
195

196
    if (self->ctrl_fds[0] >= 0) {
72✔
197
        close(self->ctrl_fds[0]);
72✔
198
        close(self->ctrl_fds[1]);
72✔
199
        self->ctrl_fds[0] = self->ctrl_fds[1] = -1;
72✔
200
    }
201

202
    if (self->data_fds[0] >= 0) {
72✔
203
        close(self->data_fds[0]);
72✔
204
        close(self->data_fds[1]);
72✔
205
        self->data_fds[0] = self->data_fds[1] = -1;
72✔
206
    }
207
}
72✔
208

209
/* Destroy a running swtpm instance */
210
static void swtpm_destroy(struct swtpm *self)
72✔
211
{
212
    self->cops->stop(self);
72✔
213
}
72✔
214

215
/* Send a command to swtpm and receive the response either via control or data channel */
216
static int transfer(struct swtpm *self, void *buffer, size_t buffer_len,
908✔
217
                    const char *cmdname, gboolean use_ctrl,
218
                    void *respbuffer, size_t *respbuffer_len)
219
{
220
    size_t offset;
908✔
221
    int sockfd;
908✔
222
    ssize_t n;
908✔
223
    unsigned char resp[4096];
908✔
224
    ssize_t resplen;
908✔
225
    uint32_t returncode;
908✔
226

227
    if (use_ctrl) {
908✔
228
        sockfd = self->ctrl_fds[0];
144✔
229
        offset = 0;
144✔
230
    } else {
231
        sockfd = self->data_fds[0];
764✔
232
        offset = 6;
764✔
233
    }
234

235
    n = write(sockfd, buffer, buffer_len);
908✔
236
    if (n < 0) {
908✔
237
        logerr(self->logfile, "Could not send %s buffer to swtpm: %s\n",
×
238
               cmdname, strerror(errno));
×
239
        return 1;
×
240
    }
241
    if ((size_t)n != buffer_len) {
908✔
242
        logerr(self->logfile, "Could not send all bytes to swtpm: %zu < %zu\n",
×
243
               (size_t)n, buffer_len);
244
        return 1;
×
245
    }
246

247
    resplen = read(sockfd, resp, sizeof(resp));
908✔
248
    if (resplen < 0) {
908✔
249
        logerr(self->logfile, "Could not receive response to %s from swtpm: %s\n",
×
250
               cmdname, strerror(errno));
×
251
        return 1;
×
252
    }
253

254
    if (!use_ctrl) {
908✔
255
        if ((size_t)resplen < sizeof(struct tpm_resp_header)) {
764✔
256
            logerr(self->logfile,
×
257
                   "Response for %s has only %d bytes.\n", cmdname, resplen);
258
            return 1;
×
259
        }
260
    } else if ((size_t)resplen < 4) {
144✔
261
        logerr(self->logfile,
×
262
               "Response for %s has only %d bytes.\n", cmdname, resplen);
263
        return 1;
×
264
    }
265

266
    memcpy(&returncode, &resp[offset], sizeof(returncode));
908✔
267
    returncode = be32toh(returncode);
908✔
268
    if (returncode != 0) {
908✔
269
        logerr(self->logfile,
×
270
               "%s failed: 0x%x\n", cmdname, returncode);
271
        return 1;
×
272
    }
273

274
    if (respbuffer) {
908✔
275
        *respbuffer_len = min((size_t)resplen, *respbuffer_len);
225✔
276
        memcpy(respbuffer, resp, *respbuffer_len);
225✔
277
    }
278

279
    return 0;
280
}
281

282
/* Send a CMD_SHUTDOWN over the control channel */
283
static int swtpm_ctrl_shutdown(struct swtpm *self)
72✔
284
{
285
    uint32_t cmd = htobe32(CMD_SHUTDOWN);
72✔
286

287
    return transfer(self, &cmd, sizeof(cmd), "CMD_SHUTDOWN", TRUE, NULL, 0);
72✔
288
}
289

290
/* Get the TPM specification parameters over the control channel */
291
static int swtpm_ctrl_get_tpm_specs_and_attrs(struct swtpm *self, gchar **result)
72✔
292
{
293
    unsigned char req[] = {AS4BE(CMD_GET_INFO),
72✔
294
                           AS8BE(SWTPM_INFO_TPMSPECIFICATION | SWTPM_INFO_TPMATTRIBUTES),
295
                           AS4BE(0), AS4BE(0)};
296
    unsigned char tpmresp[1024];
72✔
297
    size_t tpmresp_len = sizeof(tpmresp);
72✔
298
    int ret;
72✔
299
    uint32_t length;
72✔
300

301
    ret = transfer(self, req, sizeof(req), "CMD_GET_INFO", TRUE, tpmresp, &tpmresp_len);
72✔
302
    if (ret != 0)
72✔
303
        return 1;
304

305
    if (tpmresp_len < 8 + sizeof(length))
72✔
306
        goto err_too_short;
×
307
    memcpy(&length, &tpmresp[8], sizeof(length));
72✔
308
    length = htobe32(length);
72✔
309

310
    if (tpmresp_len < 12 + length)
72✔
311
        goto err_too_short;
×
312
    *result = g_strndup((gchar *)&tpmresp[12], length);
72✔
313

314
    return 0;
72✔
315

316
err_too_short:
×
317
    logerr(self->logfile, "Response from CMD_GET_INFO is too short!\n");
×
318

319
    return 1;
×
320
}
321

322
static const struct swtpm_cops swtpm_cops = {
323
    .start = swtpm_start,
324
    .stop = swtpm_stop,
325
    .destroy = swtpm_destroy,
326
    .ctrl_shutdown = swtpm_ctrl_shutdown,
327
    .ctrl_get_tpm_specs_and_attrs = swtpm_ctrl_get_tpm_specs_and_attrs,
328
};
329

330
/*
331
 * TPM 2 support
332
 */
333

334
#define TPM2_ST_NO_SESSIONS  0x8001
335
#define TPM2_ST_SESSIONS     0x8002
336

337
#define TPM2_CC_EVICTCONTROL   0x00000120
338
#define TPM2_CC_NV_DEFINESPACE 0x0000012a
339
#define TPM2_CC_PCR_ALLOCATE   0x0000012b
340
#define TPM2_CC_CREATEPRIMARY  0x00000131
341
#define TPM2_CC_NV_WRITE       0x00000137
342
#define TPM2_CC_NV_WRITELOCK   0x00000138
343
#define TPM2_CC_SHUTDOWN       0x00000145
344
#define TPM2_CC_GETCAPABILITY  0x0000017a
345

346
#define TPM2_SU_CLEAR        0x0000
347

348
#define TPM2_RH_OWNER        0x40000001
349
#define TPM2_RS_PW           0x40000009
350
#define TPM2_RH_ENDORSEMENT  0x4000000b
351
#define TPM2_RH_PLATFORM     0x4000000c
352

353
#define TPM2_ALG_RSA      0x0001
354
#define TPM2_ALG_SHA1     0x0004
355
#define TPM2_ALG_AES      0x0006
356
#define TPM2_ALG_SHA256   0x000b
357
#define TPM2_ALG_SHA384   0x000c
358
#define TPM2_ALG_SHA512   0x000d
359
#define TPM2_ALG_SHA3_256 0x0027
360
#define TPM2_ALG_SHA3_384 0x0028
361
#define TPM2_ALG_SHA3_512 0x0029
362
#define TPM2_ALG_NULL     0x0010
363
#define TPM2_ALG_SM3      0x0012
364
#define TPM2_ALG_ECC      0x0023
365
#define TPM2_ALG_CFB      0x0043
366

367
#define TPM2_CAP_PCRS     0x00000005
368

369
#define TPM2_ECC_NIST_P384 0x0004
370

371
#define TPMA_NV_PLATFORMCREATE 0x40000000
372
#define TPMA_NV_AUTHREAD       0x40000
373
#define TPMA_NV_NO_DA          0x2000000
374
#define TPMA_NV_PPWRITE        0x1
375
#define TPMA_NV_PPREAD         0x10000
376
#define TPMA_NV_OWNERREAD      0x20000
377
#define TPMA_NV_WRITEDEFINE    0x2000
378

379
// Use standard EK Cert NVRAM, EK and SRK handles per IWG spec.
380
// "TCG TPM v2.0 Provisioning Guide"; Version 1.0, Rev 1.0, March 15, 2017
381
// Table 2
382
#define TPM2_NV_INDEX_RSA2048_EKCERT         0x01c00002
383
#define TPM2_NV_INDEX_RSA2048_EKTEMPLATE     0x01c00004
384
#define TPM2_NV_INDEX_RSA3072_HI_EKCERT      0x01c0001c
385
#define TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE  0x01c0001d
386
// For ECC follow "TCG EK Credential Profile For TPM Family 2.0; Level 0"
387
// Specification Version 2.1; Revision 13; 10 December 2018
388
#define TPM2_NV_INDEX_PLATFORMCERT           0x01c08000
389

390
#define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT     0x01c00016
391
#define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE 0x01c00017
392

393
#define TPM2_EK_RSA_HANDLE           0x81010001
394
#define TPM2_EK_RSA3072_HANDLE       0x8101001c
395
#define TPM2_EK_ECC_SECP384R1_HANDLE 0x81010016
396
#define TPM2_SPK_HANDLE              0x81000001
397

398
#define TPM_REQ_HEADER_INITIALIZER(TAG, SIZE, ORD) \
399
    { \
400
        .tag = htobe16(TAG), \
401
        .size = htobe32(SIZE), \
402
        .ordinal = htobe32(ORD), \
403
    }
404

405
struct tpm2_authblock {
406
    uint32_t auth;
407
    uint16_t foo; // FIXME
408
    uint8_t continueSession;
409
    uint16_t bar; // FIMXE
410
} __attribute__((packed));
411

412
#define TPM2_AUTHBLOCK_INITIALIZER(AUTH, FOO, CS, BAR) \
413
    { \
414
        .auth = htobe32(AUTH), \
415
        .foo = htobe16(FOO), \
416
        .continueSession = CS, \
417
        .bar = htobe16(BAR), \
418
    }
419

420
static const unsigned char NONCE_EMPTY[2] = {AS2BE(0)};
421
static const unsigned char NONCE_RSA2048[2+0x100] = {AS2BE(0x100), 0, };
422
static const unsigned char NONCE_RSA3072[2+0x180] = {AS2BE(0x180), 0, };
423
static const unsigned char NONCE_ECC_384[2+0x30] = {AS2BE(0x30), 0, };
424

425
static const struct bank_to_name {
426
    uint16_t hashAlg;
427
    const char *name;
428
} banks_to_names[] = {
429
    {TPM2_ALG_SHA1, "sha1"},
430
    {TPM2_ALG_SHA256, "sha256"},
431
    {TPM2_ALG_SHA384, "sha384"},
432
    {TPM2_ALG_SHA512, "sha512"},
433
    {TPM2_ALG_SM3, "sm3-256"},
434
    {TPM2_ALG_SHA3_256, "sha3-256"},
435
    {TPM2_ALG_SHA3_384, "sha3-384"},
436
    {TPM2_ALG_SHA3_512, "sha3-512"},
437
    {0, NULL},
438
};
439

440
/* function prototypes */
441
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
442
                                        const unsigned char *symkeydata, size_t symkeydata_len,
443
                                        const unsigned char *authpolicy, size_t authpolicy_len,
444
                                        unsigned int rsa_keysize, gboolean havenonce, size_t off,
445
                                        uint32_t *curr_handle,
446
                                        unsigned char *ektemplate, size_t *ektemplate_len,
447
                                        gchar **ekparam, const gchar **key_description);
448

449
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
450
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
451
                                  const char *purpose);
452

453
/* Given a hash algo identifier, return the name of the hash bank */
454
static const char *get_name_for_bank(uint16_t hashAlg) {
184✔
455
    size_t i;
184✔
456

457
    for (i = 0; banks_to_names[i].name; i++) {
460✔
458
        if (banks_to_names[i].hashAlg == hashAlg)
460✔
459
            return banks_to_names[i].name;
460
    }
461
    return NULL;
462
}
463

464
/* Give the name of a hash bank, return its algo identifer */
465
static uint16_t get_hashalg_by_bankname(const char *name) {
184✔
466
    size_t i;
184✔
467

468
    for (i = 0; banks_to_names[i].name; i++) {
460✔
469
        if (strcmp(banks_to_names[i].name, name) == 0)
460✔
470
            return banks_to_names[i].hashAlg;
184✔
471
    }
472
    return 0;
473
}
474

475
/* Do an SU_CLEAR shutdown of the TPM 2 */
476
static int swtpm_tpm2_shutdown(struct swtpm *self)
46✔
477
{
478
    struct tpm2_shutdown_req {
46✔
479
        struct tpm_req_header hdr;
480
        uint16_t shutdownType;
481
    } __attribute__((packed)) req = {
46✔
482
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_SHUTDOWN),
46✔
483
        .shutdownType = htobe16(TPM2_SU_CLEAR)
46✔
484
    };
485

486
    return transfer(self, &req, sizeof(req), "TPM2_Shutdown", FALSE, NULL, NULL);
46✔
487
}
488

489
/* Get all available PCR banks */
490
static int swtpm_tpm2_get_all_pcr_banks(struct swtpm *self, gchar ***all_pcr_banks)
46✔
491
{
492
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, 0, TPM2_CC_GETCAPABILITY);
46✔
493
    g_autofree unsigned char *req = NULL;
92✔
494
    ssize_t req_len;
46✔
495
    unsigned char tpmresp[256];
46✔
496
    size_t tpmresp_len = sizeof(tpmresp);
46✔
497
    uint16_t count, bank;
46✔
498
    const char *name;
46✔
499
    uint8_t length;
46✔
500
    size_t offset;
46✔
501
    size_t i;
46✔
502
    int ret;
46✔
503

504
    req_len = memconcat(&req,
92✔
505
                        &hdr, sizeof(hdr),
506
                        (unsigned char[]){AS4BE(TPM2_CAP_PCRS), AS4BE(0), AS4BE(64)}, (size_t)12,
46✔
507
                        NULL);
508
    if (req_len < 0) {
46✔
509
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
510
        return 1;
×
511
    }
512
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
46✔
513

514
    ret = transfer(self, req, req_len, "TPM2_GetCapability", FALSE, tpmresp, &tpmresp_len);
46✔
515
    if (ret != 0)
46✔
516
        return 1;
517

518
    *all_pcr_banks = NULL;
46✔
519

520
    if (tpmresp_len < 17 + sizeof(count))
46✔
521
        goto err_too_short;
×
522
    memcpy(&count, &tpmresp[17], sizeof(count));
46✔
523
    count = be16toh(count);
46✔
524

525
    /* unreasonable number of PCR banks ? */
526
    if (count > 20)
46✔
527
        goto err_num_pcrbanks;
×
528

529
    *all_pcr_banks = g_malloc0(sizeof(char *) * (count + 1));
46✔
530

531
    offset = 19;
46✔
532

533
    for (i = 0; i < count; i++) {
230✔
534
        gchar *n;
184✔
535

536
        if (tpmresp_len < offset + sizeof(bank))
184✔
537
            goto err_too_short;
×
538
        memcpy(&bank, &tpmresp[offset], sizeof(bank));
184✔
539
        bank = be16toh(bank);
184✔
540

541
        if (tpmresp_len < offset + 2 + sizeof(length))
184✔
542
            goto err_too_short;
×
543
        length = tpmresp[offset + 2];
184✔
544

545
        name = get_name_for_bank(bank);
184✔
546
        if (name != NULL)
184✔
547
            n = g_strdup(name);
184✔
548
        else
549
            n = g_strdup_printf("%02x", bank);
×
550

551
        (*all_pcr_banks)[i] = n;
184✔
552

553
        offset += 2 + 1 + length;
184✔
554
    }
555
    return 0;
556

557
err_num_pcrbanks:
×
558
    logerr(self->logfile, "Unreasonable number of PCR banks (%u) returned.\n", count);
×
559
    goto err_exit;
×
560

561
err_too_short:
×
562
    logerr(self->logfile, "Response from TPM2_GetCapability is too short!\n");
×
563

564
err_exit:
×
565
    g_strfreev(*all_pcr_banks);
×
566
    *all_pcr_banks = NULL;
×
567

568
    return 1;
×
569
}
570

571
/* Activate all user-chosen PCR banks and deactivate all others */
572
static int swtpm_tpm2_set_active_pcr_banks(struct swtpm *self, gchar **pcr_banks,
46✔
573
                                           gchar **all_pcr_banks, gchar ***active)
574
{
575
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_PCR_ALLOCATE);
46✔
576
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0);
46✔
577
    unsigned char pcrselects[6 * 10]; // supports up to 10 PCR banks
46✔
578
    ssize_t pcrselects_len = 0;
46✔
579
    size_t count = 0;
46✔
580
    size_t idx, j;
46✔
581
    uint16_t hashAlg;
46✔
582
    g_autofree unsigned char *req = NULL;
92✔
583
    ssize_t req_len, len;
46✔
584
    int ret;
46✔
585
    uint64_t activated_mask = 0;
46✔
586

587
    for (idx = 0; pcr_banks[idx] != NULL; idx++)
98✔
588
        ;
589
    *active = g_malloc0(sizeof(char *) * (idx + 1));
46✔
590

591
    for (idx = 0; pcr_banks[idx] != NULL; idx++) {
98✔
592
        hashAlg = 0;
112✔
593
        // Is user-chosen pcr_banks[idx] available?
594
        for (j = 0; all_pcr_banks[j] != NULL; j++) {
112✔
595
            if (strcmp(pcr_banks[idx], all_pcr_banks[j]) == 0) {
112✔
596
                hashAlg = get_hashalg_by_bankname(pcr_banks[idx]);
52✔
597
                break;
52✔
598
            }
599
        }
600
        if (hashAlg != 0 && (activated_mask & ((uint64_t)1 << j)) == 0) {
52✔
601
            (*active)[count] = g_strdup(pcr_banks[idx]);
52✔
602
            len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
104✔
603
                         (unsigned char[]){AS2BE(hashAlg), 3, 0xff, 0xff, 0xff} , (size_t)6,
52✔
604
                         NULL);
605
            if (len < 0) {
52✔
606
                logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
607
                return 1;
×
608
            }
609
            pcrselects_len += len;
52✔
610
            count++;
52✔
611
            activated_mask |= ((uint64_t)1 << j);
52✔
612
        }
613
    }
614

615
    if (count == 0) {
46✔
616
        logerr(self->logfile,
×
617
               "No PCR banks could be allocated. None of the selected algorithms are supported.\n");
618
        goto error;
×
619
    }
620

621
    // disable all the other ones not chosen by the user
622
    for (idx = 0; all_pcr_banks[idx] != NULL; idx++) {
230✔
623
        gboolean found = FALSE;
332✔
624

625
        for (j = 0; pcr_banks[j] != NULL; j++) {
332✔
626
            if (strcmp(pcr_banks[j], all_pcr_banks[idx]) == 0) {
200✔
627
                found = TRUE;
628
                break;
629
            }
630
        }
631
        if (found)
184✔
632
            continue;
52✔
633

634
        /* not found, so not chosen by user */
635
        hashAlg = get_hashalg_by_bankname(all_pcr_banks[idx]);
132✔
636

637
        len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
264✔
638
                     (unsigned char[]){AS2BE(hashAlg), 3, 0, 0, 0}, (size_t)6,
132✔
639
                     NULL);
640
        if (len < 0) {
132✔
641
            logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
642
            goto error;
×
643
        }
644
        pcrselects_len += len;
132✔
645
        count++;
132✔
646
    }
647

648
    req_len = memconcat(&req,
92✔
649
                        &hdr, sizeof(hdr),
650
                        (unsigned char[]){
46✔
651
                             AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))
652
                        }, (size_t)8,
653
                        &authblock, sizeof(authblock),
654
                        (unsigned char[]){AS4BE(count)}, (size_t)4,
46✔
655
                        pcrselects, pcrselects_len,
656
                        NULL);
657
    if (req_len < 0) {
46✔
658
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
659
        goto error;
×
660
    }
661
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
46✔
662

663
    ret = transfer(self, req, req_len, "TPM2_PCR_Allocate", FALSE, NULL, 0);
46✔
664
    if (ret != 0)
46✔
665
        goto error;
×
666

667
    return 0;
668

669
error:
×
670
    g_strfreev(*active);
×
671
    *active = NULL;
×
672

673
    return 1;
×
674
}
675

676
/* Make object at the curr_handler permanent with the perm_handle */
677
static int swtpm_tpm2_evictcontrol(struct swtpm *self, uint32_t curr_handle, uint32_t perm_handle)
79✔
678
{
679
    struct tpm2_evictcontrol_req {
79✔
680
        struct tpm_req_header hdr;
681
        uint32_t auth;
682
        uint32_t objectHandle;
683
        uint32_t authblockLen;
684
        struct tpm2_authblock authblock;
685
        uint32_t persistentHandle;
686
    } __attribute__((packed)) req = {
79✔
687
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, sizeof(req), TPM2_CC_EVICTCONTROL),
79✔
688
        .auth = htobe32(TPM2_RH_OWNER),
79✔
689
        .objectHandle = htobe32(curr_handle),
79✔
690
        .authblockLen = htobe32(sizeof(req.authblock)),
79✔
691
        .authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0),
79✔
692
        .persistentHandle = htobe32(perm_handle),
79✔
693
    };
694

695
    return transfer(self, &req, sizeof(req), "TPM2_EvictControl", FALSE, NULL, 0);
79✔
696
}
697

698
/* Create an RSA EK */
699
static int swtpm_tpm2_createprimary_ek_rsa(struct swtpm *self, unsigned int rsa_keysize,
38✔
700
                                           gboolean allowsigning, gboolean decryption,
701
                                           uint32_t *curr_handle,
702
                                           unsigned char *ektemplate, size_t *ektemplate_len,
703
                                           gchar **ekparam, const gchar **key_description)
704
{
705
    unsigned char authpolicy[48];
38✔
706
    size_t authpolicy_len;
38✔
707
    unsigned char symkeydata[6];
38✔
708
    size_t symkeydata_len;
38✔
709
    unsigned int keyflags;
38✔
710
    unsigned int symkeylen;
38✔
711
    gboolean havenonce;
38✔
712
    size_t addlen, off;
38✔
713

714
    if (rsa_keysize == 2048) {
38✔
715
        authpolicy_len = 32;
27✔
716
        memcpy(authpolicy, ((unsigned char []){
27✔
717
            0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d,
718
            0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64,
719
            0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa
720
        }), authpolicy_len);
721
        keyflags = 0;
27✔
722
        symkeylen = 128;
27✔
723
        havenonce = TRUE;
27✔
724
        addlen = 0;
27✔
725
    } else if (rsa_keysize == 3072) {
11✔
726
        authpolicy_len = 48;
11✔
727
        memcpy(authpolicy, ((unsigned char []){
11✔
728
            0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC, 0x53, 0xD8, 0x82, 0xBC,
729
            0xF5, 0xFD, 0x3A, 0x1A, 0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4,
730
            0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA, 0xCB, 0x47, 0xBA, 0x09,
731
            0x69, 0x96, 0x46, 0x15, 0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12
732
        }), authpolicy_len);
733
        keyflags = 0x40;
11✔
734
        symkeylen = 256;
11✔
735
        havenonce = FALSE;
11✔
736
        addlen = 16;
11✔
737
    } else {
738
        logerr(self->logfile, "Internal error in %s: unsupported RSA keysize %d.\n",
×
739
               __func__, rsa_keysize);
740
        return 1;
×
741
    }
742

743
    if (allowsigning && decryption) {
38✔
744
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
745
        // adminWithPolicy, sign, decrypt
746
        keyflags |= 0x000600b2;
6✔
747
        // symmetric: TPM_ALG_NULL
748
        symkeydata_len = 2;
6✔
749
        memcpy(symkeydata, ((unsigned char[]) {AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
6✔
750
        off = 72 + addlen;
6✔
751
    } else if (allowsigning) {
32✔
752
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
753
        // adminWithPolicy, sign
754
        keyflags |= 0x000400b2;
15✔
755
        // symmetric: TPM_ALG_NULL
756
        symkeydata_len = 2;
15✔
757
        memcpy(symkeydata, ((unsigned char[]) {AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
15✔
758
        off = 72 + addlen;
15✔
759
    } else {
760
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
761
        // adminWithPolicy, restricted, decrypt
762
        keyflags |= 0x000300b2;
17✔
763
        // symmetric: TPM_ALG_AES, 128bit or 256bit, TPM_ALG_CFB
764
        symkeydata_len = 6;
17✔
765
        memcpy(symkeydata,
17✔
766
               ((unsigned char[]) {AS2BE(TPM2_ALG_AES), AS2BE(symkeylen), AS2BE(TPM2_ALG_CFB)}),
17✔
767
               symkeydata_len);
768
        off = 76 + addlen;
17✔
769
    }
770

771
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_ENDORSEMENT, keyflags,
38✔
772
                                        symkeydata, symkeydata_len,
773
                                        authpolicy, authpolicy_len, rsa_keysize,
774
                                        havenonce, off, curr_handle,
775
                                        ektemplate, ektemplate_len, ekparam, key_description);
776
}
777

778
/* Create an RSA key with the given parameters */
779
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
40✔
780
                                        const unsigned char *symkeydata, size_t symkeydata_len,
781
                                        const unsigned char *authpolicy, size_t authpolicy_len,
782
                                        unsigned int rsa_keysize, gboolean havenonce, size_t off,
783
                                        uint32_t *curr_handle,
784
                                        unsigned char *ektemplate, size_t *ektemplate_len,
785
                                        gchar **ekparam, const gchar **key_description)
786
{
787
    const unsigned char *nonce;
40✔
788
    size_t nonce_len;
40✔
789
    uint16_t hashalg;
40✔
790
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY);
40✔
791
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0);
40✔
792
    g_autofree unsigned char *public = NULL;
80✔
793
    ssize_t public_len;
40✔
794
    g_autofree unsigned char *createprimary = NULL;
40✔
795
    ssize_t createprimary_len;
40✔
796
    int ret;
40✔
797
    unsigned char tpmresp[2048];
40✔
798
    size_t tpmresp_len = sizeof(tpmresp);
40✔
799
    uint16_t modlen;
40✔
800

801
    if (rsa_keysize == 2048) {
40✔
802
        nonce = NONCE_RSA2048;
28✔
803
        nonce_len = sizeof(NONCE_RSA2048);
28✔
804
        hashalg = TPM2_ALG_SHA256;
28✔
805
        if (key_description)
28✔
806
            *key_description = "rsa2048";
27✔
807
    } else if (rsa_keysize == 3072) {
12✔
808
        if (!havenonce) {
12✔
809
           nonce = NONCE_EMPTY;
810
           nonce_len = sizeof(NONCE_EMPTY);
811
        } else {
812
           nonce = NONCE_RSA3072;
1✔
813
           nonce_len = sizeof(NONCE_RSA3072);
1✔
814
        }
815
        hashalg = TPM2_ALG_SHA384;
12✔
816
        if (key_description)
12✔
817
            *key_description = "rsa3072";
11✔
818
    } else {
819
        logerr(self->logfile, "Internal error in %s: unsupported RSA keysize %d.\n",
×
820
               __func__, rsa_keysize);
821
        return 1;
×
822
    }
823

824
    public_len =
40✔
825
        memconcat(&public,
80✔
826
                  (unsigned char[]) {
40✔
827
                      AS2BE(TPM2_ALG_RSA), AS2BE(hashalg),
828
                      AS4BE(keyflags), AS2BE(authpolicy_len)
40✔
829
                  }, (size_t)10,
830
                  authpolicy, authpolicy_len,
831
                  symkeydata, symkeydata_len,
832
                  (unsigned char[]) {
40✔
833
                      AS2BE(TPM2_ALG_NULL), AS2BE(rsa_keysize), AS4BE(0)
40✔
834
                  }, (size_t)8,
835
                  nonce, nonce_len,
836
                  NULL);
837
    if (public_len < 0) {
40✔
838
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
839
        return 1;
×
840
    }
841
    if (ektemplate) {
40✔
842
        if (*ektemplate_len < (size_t)public_len) {
38✔
843
            logerr(self->logfile, "Internal error in %s: Need %zu bytes for ektemplate (rsa) but got only %zu\n",
×
844
                   __func__, public_len, *ektemplate_len);
845
            return 1;
×
846
        }
847
        memcpy(ektemplate, public, public_len);
38✔
848
        *ektemplate_len = public_len;
38✔
849
    }
850

851
    createprimary_len =
40✔
852
        memconcat(&createprimary,
80✔
853
                  &hdr, sizeof(hdr),
854
                  (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8,
40✔
855
                  &authblock, sizeof(authblock),
856
                  (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8,
40✔
857
                  public, public_len,
858
                  (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
40✔
859
                  NULL);
860
    if (createprimary_len < 0) {
40✔
861
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
862
        return 1;
×
863
    }
864
    ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len);
40✔
865

866
    ret = transfer(self, createprimary, createprimary_len, "TPM2_CreatePrimary(RSA)", FALSE,
40✔
867
                   tpmresp, &tpmresp_len);
868
    if (ret != 0)
40✔
869
        return 1;
870

871
    if (curr_handle) {
40✔
872
        if (tpmresp_len < 10 + sizeof(*curr_handle))
40✔
873
            goto err_too_short;
×
874
        memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle));
40✔
875
        *curr_handle = be32toh(*curr_handle);
40✔
876
    }
877

878
    if (tpmresp_len < off + sizeof(modlen))
40✔
879
         goto err_too_short;
×
880
    memcpy(&modlen, &tpmresp[off], sizeof(modlen));
40✔
881
    modlen = be16toh(modlen);
40✔
882
    if (modlen != rsa_keysize >> 3) {
40✔
883
        logerr(self->logfile, "Internal error in %s: Getting modulus from wrong offset %zu\n",
×
884
               __func__, off);
885
        return 1;
×
886
    }
887
    if (ekparam) {
40✔
888
        if (tpmresp_len < off + 2 + modlen)
38✔
889
            goto err_too_short;
×
890
        *ekparam = print_as_hex(&tpmresp[off + 2], modlen);
38✔
891
    }
892

893
    return 0;
894

895
err_too_short:
×
896
    logerr(self->logfile, "Response from TPM2_CreatePrimary(RSA) is too short!\n");
×
897
    return 1;
×
898
}
899

900
/* Create an ECC key with the given parameters */
901
static int swtpm_tpm2_createprimary_ecc(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
39✔
902
                                        const unsigned char *symkeydata, size_t symkeydata_len,
903
                                        const unsigned char *authpolicy, size_t authpolicy_len,
904
                                        unsigned short curveid, unsigned short hashalg,
905
                                        const unsigned char *nonce, size_t nonce_len,
906
                                        size_t off, uint32_t *curr_handle,
907
                                        unsigned char *ektemplate, size_t *ektemplate_len,
908
                                        gchar **ekparam, const gchar **key_description)
909
{
910
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY);
39✔
911
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0);
39✔
912
    g_autofree unsigned char *public = NULL;
78✔
913
    ssize_t public_len;
39✔
914
    g_autofree unsigned char *createprimary = NULL;
39✔
915
    ssize_t createprimary_len;
39✔
916
    int ret;
39✔
917
    unsigned char tpmresp[2048];
39✔
918
    size_t tpmresp_len = sizeof(tpmresp);
39✔
919
    size_t off2;
39✔
920
    uint16_t exp_ksize, ksize1, ksize2;
39✔
921
    const char *cid;
39✔
922

923
    public_len =
39✔
924
        memconcat(&public,
78✔
925
                  (unsigned char[]){
39✔
926
                      AS2BE(TPM2_ALG_ECC), AS2BE(hashalg), AS4BE(keyflags), AS2BE(authpolicy_len)
39✔
927
                  }, (size_t)10,
928
                  authpolicy, authpolicy_len,
929
                  symkeydata, symkeydata_len,
930
                  (unsigned char[]) {AS2BE(TPM2_ALG_NULL), AS2BE(curveid), AS2BE(TPM2_ALG_NULL)}, (size_t)6,
39✔
931
                  nonce, nonce_len,
932
                  nonce, nonce_len,
933
                  NULL);
934
    if (public_len < 0) {
39✔
935
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
936
        return 1;
×
937
    }
938
    if (ektemplate) {
39✔
939
        if (*ektemplate_len < (size_t)public_len) {
38✔
940
            logerr(self->logfile, "Internal error: Need %zu bytes for ektemplate (ecc) but got only %zu\n",
×
941
                   public_len, ektemplate_len);
942
            return 1;
×
943
        }
944
        memcpy(ektemplate, public, public_len);
38✔
945
        *ektemplate_len = public_len;
38✔
946
    }
947

948
    createprimary_len =
39✔
949
        memconcat(&createprimary,
78✔
950
                  &hdr, sizeof(hdr),
951
                  (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8,
39✔
952
                  &authblock, sizeof(authblock),
953
                  (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8,
39✔
954
                  public, public_len,
955
                  (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
39✔
956
                  NULL);
957
    if (createprimary_len < 0) {
39✔
958
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
959
        return 1;
×
960
    }
961
    ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len);
39✔
962

963
    ret = transfer(self, createprimary, createprimary_len, "TPM2_CreatePrimary(ECC)", FALSE,
39✔
964
                   tpmresp, &tpmresp_len);
965
    if (ret != 0)
39✔
966
        return 1;
967
    if (curr_handle) {
39✔
968
        if (tpmresp_len < 10 + sizeof(*curr_handle))
39✔
969
            goto err_too_short;
×
970
        memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle));
39✔
971
        *curr_handle = be32toh(*curr_handle);
39✔
972
    }
973

974
    if (curveid == TPM2_ECC_NIST_P384) {
39✔
975
        exp_ksize = 48;
39✔
976
        cid = "secp384r1";
39✔
977
        if (key_description)
39✔
978
            *key_description = cid;
38✔
979
    } else {
980
        logerr(self->logfile, "Unknown curveid 0x%x\n", curveid);
×
981
        return 1;
×
982
    }
983

984
    if (tpmresp_len < off + sizeof(ksize1))
39✔
985
        goto err_too_short;
×
986
    memcpy(&ksize1, &tpmresp[off], sizeof(ksize1));
39✔
987
    ksize1 = be16toh(ksize1);
39✔
988
    off2 = off + 2 + ksize1;
39✔
989

990
    if (tpmresp_len < off2 + sizeof(ksize2))
39✔
991
        goto err_too_short;
×
992
    memcpy(&ksize2, &tpmresp[off2], sizeof(ksize2));
39✔
993
    ksize2 = be16toh(ksize2);
39✔
994

995
    if (ksize1 != exp_ksize || ksize2 != exp_ksize) {
39✔
996
        logerr(self->logfile, "ECC: Getting key parameters from wrong offset\n");
×
997
        return 1;
×
998
    }
999

1000
    if (ekparam) {
39✔
1001
        unsigned char *xparam = &tpmresp[off + 2];
38✔
1002
        unsigned char *yparam = &tpmresp[off2 + 2];
38✔
1003
        if (tpmresp_len < off + 2 + ksize1 || tpmresp_len < off2 + 2 + ksize2)
38✔
1004
            goto err_too_short;
×
1005
        g_autofree gchar *xparam_str = print_as_hex(xparam, ksize1);
76✔
1006
        g_autofree gchar *yparam_str = print_as_hex(yparam, ksize2);
76✔
1007

1008
        *ekparam = g_strdup_printf("x=%s,y=%s,id=%s", xparam_str, yparam_str, cid);
38✔
1009
    }
1010

1011
    return 0;
1012

1013
err_too_short:
×
1014
    logerr(self->logfile, "Response from TPM2_CreatePrimary(ECC) is too short!\n");
×
1015
    return 1;
×
1016
}
1017

1018
static int swtpm_tpm2_createprimary_spk_ecc_nist_p384(struct swtpm *self,
1✔
1019
                                                      uint32_t *curr_handle)
1020
{
1021
    unsigned int keyflags = 0x00030472;
1✔
1022
    const unsigned char authpolicy[0];
1✔
1023
    size_t authpolicy_len = sizeof(authpolicy);
1✔
1024
    const unsigned char symkeydata[] = {AS2BE(TPM2_ALG_AES), AS2BE(256), AS2BE(TPM2_ALG_CFB)};
1✔
1025
    size_t symkeydata_len = sizeof(symkeydata);
1✔
1026
    size_t off = 42;
1✔
1027

1028
    return swtpm_tpm2_createprimary_ecc(self, TPM2_RH_OWNER, keyflags, symkeydata, symkeydata_len,
1✔
1029
                                        authpolicy, authpolicy_len, TPM2_ECC_NIST_P384, TPM2_ALG_SHA384,
1030
                                        NONCE_ECC_384, sizeof(NONCE_ECC_384), off, curr_handle,
1031
                                        NULL, 0, NULL, NULL);
1032
}
1033

1034
static int swtpm_tpm2_createprimary_spk_rsa(struct swtpm *self, unsigned int rsa_keysize,
2✔
1035
                                            uint32_t *curr_handle)
1036
{
1037
    unsigned int keyflags = 0x00030472;
2✔
1038
    const unsigned char authpolicy[0];
2✔
1039
    size_t authpolicy_len = sizeof(authpolicy);
2✔
1040
    unsigned short symkeylen = 0;
2✔
1041
    unsigned char symkeydata[6];
2✔
1042
    size_t symkeydata_len;
2✔
1043
    size_t off = 44;
2✔
1044

1045
    if (rsa_keysize == 2048)
2✔
1046
        symkeylen = 128;
1047
    else if (rsa_keysize == 3072)
1✔
1048
        symkeylen = 256;
1✔
1049

1050
    symkeydata_len = 6;
2✔
1051
    memcpy(symkeydata,
2✔
1052
           ((unsigned char[]) {AS2BE(TPM2_ALG_AES), AS2BE(symkeylen), AS2BE(TPM2_ALG_CFB)}),
2✔
1053
           symkeydata_len);
1054

1055
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_OWNER, keyflags,
2✔
1056
                                        symkeydata, symkeydata_len,
1057
                                        authpolicy, authpolicy_len, rsa_keysize, TRUE,
1058
                                        off, curr_handle, NULL, 0, NULL, NULL);
1059
}
1060

1061
/* Create either an ECC or RSA storage primary key */
1062
static int swtpm_tpm2_create_spk(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize)
3✔
1063
{
1064
    int ret;
3✔
1065
    uint32_t curr_handle;
3✔
1066

1067
    if (isecc)
3✔
1068
        ret = swtpm_tpm2_createprimary_spk_ecc_nist_p384(self, &curr_handle);
1✔
1069
    else
1070
        ret = swtpm_tpm2_createprimary_spk_rsa(self, rsa_keysize, &curr_handle);
2✔
1071

1072
    if (ret != 0)
3✔
1073
        return 1;
1074

1075
    ret = swtpm_tpm2_evictcontrol(self, curr_handle, TPM2_SPK_HANDLE);
3✔
1076
    if (ret == 0)
3✔
1077
        logit(self->logfile,
3✔
1078
              "Successfully created storage primary key with handle 0x%x.\n", TPM2_SPK_HANDLE);
1079

1080
    return ret;
1081
}
1082

1083
/* Create an ECC EK key that may be allowed to sign and/or decrypt */
1084
static int swtpm_tpm2_createprimary_ek_ecc_nist_p384(struct swtpm *self, gboolean allowsigning,
38✔
1085
                                                     gboolean decryption, uint32_t *curr_handle,
1086
                                                     unsigned char *ektemplate, size_t *ektemplate_len,
1087
                                                     gchar **ekparam, const char **key_description)
1088
{
1089
    unsigned char authpolicy[48]= {
38✔
1090
        0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC, 0x53, 0xD8, 0x82, 0xBC,
1091
        0xF5, 0xFD, 0x3A, 0x1A, 0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4,
1092
        0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA, 0xCB, 0x47, 0xBA, 0x09,
1093
        0x69, 0x96, 0x46, 0x15, 0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12
1094
    };
1095
    size_t authpolicy_len = 48;
38✔
1096
    unsigned char symkeydata[6];
38✔
1097
    size_t symkeydata_len;
38✔
1098
    unsigned int keyflags;
38✔
1099
    size_t off;
38✔
1100
    int ret;
38✔
1101

1102
    if (allowsigning && decryption) {
38✔
1103
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1104
        // userWithAuth, adminWithPolicy, sign, decrypt
1105
        keyflags = 0x000600f2;
6✔
1106
        // symmetric: TPM_ALG_NULL
1107
        symkeydata_len = 2;
6✔
1108
        memcpy(symkeydata, ((unsigned char[]){AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
6✔
1109
        off = 86;
6✔
1110
    } else if (allowsigning) {
32✔
1111
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1112
        // userWithAuth, adminWithPolicy, sign
1113
        keyflags = 0x000400f2;
15✔
1114
        // symmetric: TPM_ALG_NULL
1115
        symkeydata_len = 2;
15✔
1116
        memcpy(symkeydata, ((unsigned char[]){AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
15✔
1117
        off = 86;
15✔
1118
    } else {
1119
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1120
        // userWithAuth, adminWithPolicy, restricted, decrypt
1121
        keyflags = 0x000300f2;
17✔
1122
        // symmetric: TPM_ALG_AES, 256bit, TPM_ALG_CFB
1123
        symkeydata_len = 6;
17✔
1124
        memcpy(symkeydata,
17✔
1125
               ((unsigned char[]){ AS2BE(TPM2_ALG_AES), AS2BE(256), AS2BE(TPM2_ALG_CFB)}),
17✔
1126
               symkeydata_len);
1127
        off = 90;
17✔
1128
    }
1129

1130
    ret = swtpm_tpm2_createprimary_ecc(self, TPM2_RH_ENDORSEMENT, keyflags, symkeydata, symkeydata_len,
38✔
1131
                                       authpolicy, authpolicy_len, TPM2_ECC_NIST_P384, TPM2_ALG_SHA384,
1132
                                       NONCE_EMPTY, sizeof(NONCE_EMPTY), off, curr_handle,
1133
                                       ektemplate, ektemplate_len, ekparam, key_description);
1134
    if (ret != 0)
38✔
1135
       logerr(self->logfile, "%s failed\n", __func__);
×
1136

1137
    return ret;
38✔
1138
}
1139

1140
/* Create an ECC or RSA EK */
1141
static int swtpm_tpm2_create_ek(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize,
76✔
1142
                                gboolean allowsigning, gboolean decryption, gboolean lock_nvram,
1143
                                gchar **ekparam, const  gchar **key_description)
1144
{
1145
    uint32_t tpm2_ek_handle, nvindex, curr_handle;
76✔
1146
    const char *keytype;
76✔
1147
    int ret;
76✔
1148
    unsigned char ektemplate[512];
76✔
1149
    size_t ektemplate_len = sizeof(ektemplate);
76✔
1150

1151
    if (isecc) {
76✔
1152
        tpm2_ek_handle = TPM2_EK_ECC_SECP384R1_HANDLE;
1153
        keytype = "ECC";
1154
        nvindex = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE;
1155
    } else {
1156
        if (rsa_keysize == 2048) {
38✔
1157
            tpm2_ek_handle = TPM2_EK_RSA_HANDLE;
1158
            keytype = "RSA 2048";
1159
            nvindex = TPM2_NV_INDEX_RSA2048_EKTEMPLATE;
1160
        } else if (rsa_keysize == 3072) {
11✔
1161
            tpm2_ek_handle = TPM2_EK_RSA3072_HANDLE;
1162
            keytype = "RSA 3072";
1163
            nvindex = TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE;
1164
        } else {
1165
            logerr(self->logfile, "Internal error: Unsupported RSA keysize %u.\n", rsa_keysize);
×
1166
            return 1;
×
1167
        }
1168
    }
1169
    if (isecc)
76✔
1170
        ret = swtpm_tpm2_createprimary_ek_ecc_nist_p384(self, allowsigning, decryption, &curr_handle,
38✔
1171
                                                        ektemplate, &ektemplate_len, ekparam,
1172
                                                        key_description);
1173
    else
1174
        ret = swtpm_tpm2_createprimary_ek_rsa(self, rsa_keysize, allowsigning, decryption, &curr_handle,
38✔
1175
                                              ektemplate, &ektemplate_len, ekparam, key_description);
1176

1177
    if (ret == 0)
76✔
1178
        ret = swtpm_tpm2_evictcontrol(self, curr_handle, tpm2_ek_handle);
76✔
1179
    if (ret != 0) {
76✔
1180
        logerr(self->logfile, "create_ek failed: 0x%x\n", ret);
×
1181
        return 1;
×
1182
    }
1183

1184
    logit(self->logfile,
76✔
1185
          "Successfully created %s EK with handle 0x%x.\n", keytype, tpm2_ek_handle);
1186

1187
    if (allowsigning) {
76✔
1188
        uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE | \
42✔
1189
                TPMA_NV_AUTHREAD | \
1190
                TPMA_NV_OWNERREAD | \
1191
                TPMA_NV_PPREAD | \
1192
                TPMA_NV_PPWRITE | \
1193
                TPMA_NV_NO_DA | \
1194
                TPMA_NV_WRITEDEFINE;
1195
        ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, ektemplate, ektemplate_len,
42✔
1196
                                     lock_nvram, "EK template");
1197
        if (ret == 0)
42✔
1198
            logit(self->logfile,
42✔
1199
                  "Successfully created NVRAM area 0x%x for %s EK template.\n",
1200
                  nvindex, keytype);
1201
    }
1202

1203
    return ret;
1204
}
1205

1206
static int swtpm_tpm2_nvdefinespace(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
138✔
1207
                                    uint16_t data_len)
1208
{
1209
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_DEFINESPACE);
138✔
1210
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0);
138✔
1211
    g_autofree unsigned char *nvpublic = NULL;
276✔
1212
    ssize_t nvpublic_len;
138✔
1213
    g_autofree unsigned char *req = NULL;
138✔
1214
    ssize_t req_len;
138✔
1215

1216
    nvpublic_len = memconcat(&nvpublic,
276✔
1217
                             (unsigned char[]){
138✔
1218
                                 AS4BE(nvindex), AS2BE(TPM2_ALG_SHA256), AS4BE(nvindexattrs),
138✔
1219
                                 AS2BE(0), AS2BE(data_len)}, (size_t)14,
1220
                             NULL);
1221
    if (nvpublic_len < 0) {
138✔
1222
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1223
        return 1;
×
1224
    }
1225

1226
    req_len = memconcat(&req,
276✔
1227
                        &hdr, sizeof(hdr),
1228
                        (unsigned char[]){AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))}, (size_t)8,
138✔
1229
                        &authblock, sizeof(authblock),
1230
                        (unsigned char[]){AS2BE(0), AS2BE(nvpublic_len)}, (size_t)4,
138✔
1231
                        nvpublic, nvpublic_len,
1232
                        NULL);
1233
    if (req_len < 0) {
138✔
1234
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1235
        return 1;
×
1236
    }
1237

1238
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
138✔
1239

1240
    return transfer(self, req, req_len, "TPM2_NV_DefineSpace", FALSE, NULL, 0);
138✔
1241
}
1242

1243
/* Write the data into the given NVIndex */
1244
static int swtpm_tpm2_nv_write(struct swtpm *self, uint32_t nvindex,
138✔
1245
                               const unsigned char *data, size_t data_len)
1246
{
1247
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITE);
138✔
1248
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0);
138✔
1249
    g_autofree unsigned char *req = NULL;
276✔
1250
    ssize_t req_len;
138✔
1251
    size_t offset = 0, txlen;
138✔
1252
    int ret;
138✔
1253

1254
    while (offset < data_len) {
276✔
1255
        txlen = min(data_len - offset, 1024);
138✔
1256

1257
        g_free(req);
138✔
1258
        req_len = memconcat(&req,
276✔
1259
                            &hdr, sizeof(hdr),
1260
                            (unsigned char[]){
138✔
1261
                                AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
138✔
1262
                            }, (size_t)12,
1263
                            &authblock, sizeof(authblock),
1264
                            (unsigned char[]){AS2BE(txlen)}, (size_t)2,
138✔
1265
                            &data[offset], txlen,
1266
                            (unsigned char[]){AS2BE(offset)}, (size_t)2,
138✔
1267
                            NULL);
1268
        if (req_len < 0) {
138✔
1269
            logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1270
            return 1;
×
1271
        }
1272
        ((struct tpm_req_header *)req)->size = htobe32(req_len);
138✔
1273

1274
        ret = transfer(self, req, req_len, "TPM2_NV_Write", FALSE, NULL, 0);
138✔
1275
        if (ret != 0)
138✔
1276
            return 1;
1277

1278
        offset += txlen;
138✔
1279
    }
1280
    return 0;
1281
}
1282

1283
static int swtpm_tpm2_nv_writelock(struct swtpm *self, uint32_t nvindex)
9✔
1284
{
1285
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITELOCK);
9✔
1286
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0);
9✔
1287
    g_autofree unsigned char *req;
18✔
1288
    ssize_t req_len;
9✔
1289

1290
    req_len = memconcat(&req,
18✔
1291
                        &hdr, sizeof(hdr),
1292
                        (unsigned char[]){
9✔
1293
                           AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
9✔
1294
                        }, (size_t)12,
1295
                        &authblock, sizeof(authblock),
1296
                        NULL);
1297
    if (req_len < 0) {
9✔
1298
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1299
        return 1;
×
1300
    }
1301

1302
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
9✔
1303

1304
    return transfer(self, req, req_len, "TPM2_NV_WriteLock", FALSE, NULL, 0);
9✔
1305
}
1306

1307
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
138✔
1308
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
1309
                                  const char *purpose)
1310
{
1311
    int ret = swtpm_tpm2_nvdefinespace(self, nvindex, nvindexattrs, data_len);
138✔
1312
    if (ret != 0) {
138✔
1313
        logerr(self->logfile, "Could not create NVRAM area 0x%x for %s.\n", nvindex, purpose);
×
1314
        return 1;
×
1315
    }
1316

1317
    ret = swtpm_tpm2_nv_write(self, nvindex, data, data_len);
138✔
1318
    if (ret != 0) {
138✔
1319
        logerr(self->logfile,
×
1320
               "Could not write %s into NVRAM area 0x%x.\n", purpose, nvindex);
1321
        return 1;
×
1322
    }
1323

1324
    if (lock_nvram) {
138✔
1325
        ret = swtpm_tpm2_nv_writelock(self, nvindex);
9✔
1326
        if (ret != 0) {
9✔
1327
            logerr(self->logfile, "Could not lock EK template NVRAM area 0x%x.\n", nvindex);
×
1328
            return 1;
×
1329
        }
1330
    }
1331

1332
    return 0;
1333
}
1334

1335
/* Write the platform certificate into an NVRAM area */
1336
static int swtpm_tpm2_write_ek_cert_nvram(struct swtpm *self, gboolean isecc,
64✔
1337
                                           unsigned int rsa_keysize, gboolean lock_nvram,
1338
                                           const unsigned char *data, size_t data_len)
1339
{
1340
    uint32_t nvindex = 0;
64✔
1341
    g_autofree gchar *keytype = NULL;
128✔
1342
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
64✔
1343
            TPMA_NV_AUTHREAD |
1344
            TPMA_NV_OWNERREAD |
1345
            TPMA_NV_PPREAD |
1346
            TPMA_NV_PPWRITE |
1347
            TPMA_NV_NO_DA |
1348
            TPMA_NV_WRITEDEFINE;
1349
    int ret;
64✔
1350

1351
    if (!isecc) {
64✔
1352
        if (rsa_keysize == 2048)
32✔
1353
            nvindex = TPM2_NV_INDEX_RSA2048_EKCERT;
1354
        else if (rsa_keysize == 3072)
9✔
1355
            nvindex = TPM2_NV_INDEX_RSA3072_HI_EKCERT;
9✔
1356
        keytype = g_strdup_printf("RSA %d", rsa_keysize);
32✔
1357
    } else {
1358
        nvindex = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT;
32✔
1359
        keytype = g_strdup("ECC");
32✔
1360
    }
1361

1362
    ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, data, data_len, lock_nvram,
64✔
1363
                                 "EK Certificate");
1364
    if (ret == 0)
64✔
1365
        logit(self->logfile,
64✔
1366
              "Successfully created NVRAM area 0x%x for %s EK certificate.\n",
1367
              nvindex, keytype);
1368
    else
1369
        logerr(self->logfile,
×
1370
               "Could not create NVRAM area 0x%x for %s EK certificate.\n",
1371
               nvindex, keytype);
1372
    return ret;
64✔
1373
}
1374

1375
static int swtpm_tpm2_write_platform_cert_nvram(struct swtpm *self, gboolean lock_nvram,
32✔
1376
                                                const unsigned char *data, size_t data_len)
1377
{
1378
    uint32_t nvindex = TPM2_NV_INDEX_PLATFORMCERT;
32✔
1379
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
32✔
1380
            TPMA_NV_AUTHREAD |
1381
            TPMA_NV_OWNERREAD |
1382
            TPMA_NV_PPREAD |
1383
            TPMA_NV_PPWRITE |
1384
            TPMA_NV_NO_DA |
1385
            TPMA_NV_WRITEDEFINE;
1386
    int ret;
32✔
1387

1388
    ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, data, data_len, lock_nvram,
32✔
1389
                                 "Platform Certificate");
1390
    if (ret == 0)
32✔
1391
        logit(self->logfile,
32✔
1392
              "Successfully created NVRAM area 0x%x for platform certificate.\n", nvindex);
1393
    else
1394
        logerr(self->logfile,
×
1395
               "Could not create NVRAM area 0x%x for platform certificate.\n", nvindex);
1396

1397
    return ret;
32✔
1398
}
1399

1400
static const struct swtpm2_ops swtpm_tpm2_ops = {
1401
    .shutdown = swtpm_tpm2_shutdown,
1402
    .create_spk = swtpm_tpm2_create_spk,
1403
    .create_ek = swtpm_tpm2_create_ek,
1404
    .get_all_pcr_banks = swtpm_tpm2_get_all_pcr_banks,
1405
    .set_active_pcr_banks = swtpm_tpm2_set_active_pcr_banks,
1406
    .write_ek_cert_nvram = swtpm_tpm2_write_ek_cert_nvram,
1407
    .write_platform_cert_nvram = swtpm_tpm2_write_platform_cert_nvram,
1408
};
1409

1410
/*
1411
 * TPM 1.2 support
1412
 */
1413
#define TPM_TAG_RQU_COMMAND       0x00c1
1414
#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
1415

1416
#define TPM_ORD_OIAP                     0x0000000A
1417
#define TPM_ORD_TAKE_OWNERSHIP           0x0000000D
1418
#define TPM_ORD_PHYSICAL_ENABLE          0x0000006F
1419
#define TPM_ORD_PHYSICAL_SET_DEACTIVATED 0x00000072
1420
#define TPM_ORD_NV_DEFINE_SPACE          0x000000CC
1421
#define TPM_ORD_NV_WRITE_VALUE           0x000000CD
1422
#define TSC_ORD_PHYSICAL_PRESENCE        0x4000000A
1423

1424
#define TPM_ST_CLEAR 0x0001
1425

1426
#define TPM_PHYSICAL_PRESENCE_CMD_ENABLE  0x0020
1427
#define TPM_PHYSICAL_PRESENCE_PRESENT     0x0008
1428

1429
#define TPM_ALG_RSA 0x00000001
1430

1431
#define TPM_KEY_STORAGE 0x0011
1432

1433
#define TPM_AUTH_ALWAYS 0x01
1434

1435
#define TPM_PID_OWNER  0x0005
1436

1437
#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003
1438
#define TPM_SS_NONE 0x0001
1439

1440
#define TPM_TAG_PCR_INFO_LONG   0x0006
1441
#define TPM_TAG_NV_ATTRIBUTES   0x0017
1442
#define TPM_TAG_NV_DATA_PUBLIC  0x0018
1443
#define TPM_TAG_KEY12           0x0028
1444

1445
#define TPM_LOC_ZERO   0x01
1446
#define TPM_LOC_ALL    0x1f
1447

1448
#define TPM_NV_INDEX_D_BIT        0x10000000
1449
#define TPM_NV_INDEX_EKCERT       0xF000
1450
#define TPM_NV_INDEX_PLATFORMCERT 0xF002
1451

1452
#define TPM_NV_INDEX_LOCK 0xFFFFFFFF
1453

1454
#define TPM_NV_PER_OWNERREAD   0x00020000
1455
#define TPM_NV_PER_OWNERWRITE  0x00000002
1456

1457
#define TPM_ET_OWNER 0x02
1458
#define TPM_ET_NV    0x0b
1459

1460
#define TPM_KH_EK    0x40000006
1461

1462

1463
static int swtpm_tpm12_tsc_physicalpresence(struct swtpm *self, uint16_t physicalpresence)
52✔
1464
{
1465
    struct tpm12_tsc_physicalpresence {
52✔
1466
        struct tpm_req_header hdr;
1467
        uint16_t pp;
1468
    } req = {
52✔
1469
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TSC_ORD_PHYSICAL_PRESENCE),
52✔
1470
        .pp = htobe16(physicalpresence),
52✔
1471
    };
1472

1473
    return transfer(self, &req, sizeof(req), "TSC_PhysicalPresence", FALSE, NULL, NULL);
52✔
1474
}
1475

1476
static int swtpm_tpm12_physical_enable(struct swtpm *self)
26✔
1477
{
1478
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_ENABLE);
26✔
1479

1480
    return transfer(self, &req, sizeof(req), "TPM_PhysicalEnable", FALSE, NULL, NULL);
26✔
1481
}
1482

1483
static int swtpm_tpm12_physical_set_deactivated(struct swtpm *self, uint8_t state)
26✔
1484
{
1485
    struct tpm12_tsc_physical_set_deactivated {
26✔
1486
        struct tpm_req_header hdr;
1487
        uint8_t state;
1488
    } req = {
26✔
1489
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_SET_DEACTIVATED),
26✔
1490
        .state = state,
1491
    };
1492

1493
    return transfer(self, &req, sizeof(req), "TSC_PhysicalSetDeactivated", FALSE, NULL, NULL);
26✔
1494
}
1495

1496
/* Initialize the TPM1.2 */
1497
static int swtpm_tpm12_run_swtpm_bios(struct swtpm *self)
26✔
1498
{
1499
    if (swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_CMD_ENABLE) ||
52✔
1500
        swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_PRESENT) ||
52✔
1501
        swtpm_tpm12_physical_enable(self) ||
52✔
1502
        swtpm_tpm12_physical_set_deactivated(self, 0))
26✔
1503
        return 1;
×
1504

1505
    return 0;
1506
}
1507

1508
static int swptm_tpm12_create_endorsement_keypair(struct swtpm *self,
19✔
1509
                                                  gchar **pubek, size_t *pubek_len)
1510
{
1511
    unsigned char req[] = {
19✔
1512
        0x00, 0xc1, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x78, 0x38, 0xf0, 0x30, 0x81, 0x07, 0x2b,
1513
        0x0c, 0xa9, 0x10, 0x98, 0x08, 0xc0, 0x4B, 0x05, 0x11, 0xc9, 0x50, 0x23, 0x52, 0xc4, 0x00, 0x00,
1514
        0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1515
        0x00, 0x02, 0x00, 0x00, 0x00, 0x00
1516
    };
1517
    unsigned char tpmresp[512];
19✔
1518
    size_t tpmresp_len = sizeof(tpmresp);
19✔
1519
    uint32_t length;
19✔
1520
    int ret;
19✔
1521

1522
    ret = transfer(self, &req, sizeof(req), "TPM_CreateEndorsementKeyPair", FALSE, &tpmresp, &tpmresp_len);
19✔
1523
    if (ret != 0)
19✔
1524
        return 1;
1525

1526
    if (tpmresp_len < 34 + sizeof(length))
19✔
1527
        goto err_too_short;
×
1528
    memcpy(&length, &tpmresp[34], sizeof(length));
19✔
1529
    length = be32toh(length);
19✔
1530
    if (length != 256) {
19✔
1531
        logerr(self->logfile, "Offset to EK Public key is wrong.\n");
×
1532
        return 1;
×
1533
    }
1534

1535
    *pubek_len = 256;
19✔
1536
    if (tpmresp_len < 38 + *pubek_len)
19✔
1537
        goto err_too_short;
×
1538
    *pubek = g_malloc(256);
19✔
1539
    memcpy(*pubek, &tpmresp[38], *pubek_len);
19✔
1540

1541
    return 0;
19✔
1542

1543
err_too_short:
×
1544
    logerr(self->logfile, "Response from TPM_CreateEndorsementKeyPair is too short!\n");
×
1545
    return 1;
×
1546
}
1547

1548
/* Create an OIAP session */
1549
static int swtpm_tpm12_oiap(struct swtpm *self, uint32_t *authhandle, unsigned char nonce_even[SHA_DIGEST_LENGTH])
9✔
1550
{
1551
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_OIAP);
9✔
1552
    unsigned char tpmresp[64];
9✔
1553
    size_t tpmresp_len = sizeof(tpmresp);
9✔
1554
    int ret;
9✔
1555

1556
    ret = transfer(self, &req, sizeof(req), "TPM_OIAP", FALSE, &tpmresp, &tpmresp_len);
9✔
1557
    if (ret != 0)
9✔
1558
        return ret;
1559

1560
    if (tpmresp_len < 10 + sizeof(*authhandle) || tpmresp_len < 14 + SHA_DIGEST_LENGTH)
9✔
1561
        goto err_too_short;
×
1562
    memcpy(authhandle, &tpmresp[10], sizeof(*authhandle));
9✔
1563
    *authhandle = be32toh(*authhandle);
9✔
1564
    memcpy(nonce_even, &tpmresp[14], SHA_DIGEST_LENGTH);
9✔
1565

1566
    return 0;
9✔
1567

1568
err_too_short:
×
1569
    logerr(self->logfile, "Response from TPM_OIAP is too short!\n");
×
1570
    return 1;
×
1571
}
1572

1573
static int swtpm_tpm12_take_ownership(struct swtpm *self, const unsigned char ownerpass_digest[SHA_DIGEST_LENGTH],
9✔
1574
                                      const unsigned char srkpass_digest[SHA_DIGEST_LENGTH],
1575
                                      const unsigned char *pubek, size_t pubek_len)
1576
{
1577
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_AUTH1_COMMAND, 0, TPM_ORD_TAKE_OWNERSHIP);
9✔
1578
    EVP_PKEY *pkey = NULL;
9✔
1579
    EVP_PKEY_CTX *ctx = NULL;
9✔
1580
    BIGNUM *exp = BN_new();
9✔
1581
    BIGNUM *mod = NULL;
9✔
1582
#if OPENSSL_VERSION_NUMBER < 0x30000000L
1583
    RSA *rsakey = RSA_new();
1584
#endif
1585
    int ret = 1;
9✔
1586
    const EVP_MD *sha1 = EVP_sha1();
9✔
1587
    g_autofree unsigned char *enc_owner_auth = g_malloc(pubek_len);
9✔
1588
    size_t enc_owner_auth_len = pubek_len;
9✔
1589
    g_autofree unsigned char *enc_srk_auth = g_malloc(pubek_len);
18✔
1590
    size_t enc_srk_auth_len = pubek_len;
9✔
1591
    uint32_t auth_handle;
9✔
1592
    unsigned char nonce_even[SHA_DIGEST_LENGTH];
9✔
1593
    unsigned char nonce_odd[SHA_DIGEST_LENGTH] = {1, 2, 3, 4, 5, 6, };
9✔
1594
    g_autofree unsigned char *tpm_rsa_key_parms = NULL;
9✔
1595
    ssize_t tpm_rsa_key_parms_len;
9✔
1596
    g_autofree unsigned char *tpm_key_parms = NULL;
9✔
1597
    ssize_t tpm_key_parms_len;
9✔
1598
    g_autofree unsigned char *tpm_key12 = NULL;
9✔
1599
    ssize_t tpm_key12_len;
9✔
1600
    g_autofree unsigned char *in_auth_setup_params = NULL;
9✔
1601
    ssize_t in_auth_setup_params_len;
9✔
1602
    g_autofree unsigned char *macinput = NULL;
9✔
1603
    ssize_t macinput_len;
9✔
1604
    unsigned char in_param_digest[SHA_DIGEST_LENGTH];
9✔
1605
    unsigned char owner_auth[SHA_DIGEST_LENGTH];
9✔
1606
    unsigned int owner_auth_len = sizeof(owner_auth);
9✔
1607
    uint8_t continue_auth_session = 0;
9✔
1608
    unsigned char req[1024];
9✔
1609
    ssize_t req_len, len;
9✔
1610
    struct tpm_req_header *trh;
9✔
1611

1612
    mod = BN_bin2bn((const unsigned char *)pubek, pubek_len, NULL);
9✔
1613
    if (exp == NULL || mod == NULL ||
18✔
1614
        BN_hex2bn(&exp, "10001") == 0) {
9✔
1615
        logerr(self->logfile, "Could not create public RSA key!\n");
×
1616
        goto error_free_bn;
×
1617
    }
1618

1619
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1620
    ctx = EVP_PKEY_CTX_new_from_name(NULL, "rsa", NULL);
9✔
1621
    if (ctx != NULL) {
9✔
1622
        OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
9✔
1623
        OSSL_PARAM *params;
9✔
1624

1625
        if (bld == NULL ||
18✔
1626
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, exp) != 1 ||
18✔
1627
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, mod) != 1 ||
9✔
1628
            (params = OSSL_PARAM_BLD_to_param(bld)) == NULL) {
9✔
1629
            OSSL_PARAM_BLD_free(bld);
×
1630
            goto error_free_bn;
×
1631
        }
1632
        OSSL_PARAM_BLD_free(bld);
9✔
1633

1634
        if (EVP_PKEY_fromdata_init(ctx) != 1 ||
18✔
1635
            EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) != 1) {
9✔
1636
            logerr(self->logfile, "Could not set pkey parameters!\n");
×
1637
            OSSL_PARAM_free(params);
×
1638
            goto error_free_bn;
×
1639
        }
1640
        OSSL_PARAM_free(params);
9✔
1641

1642
        EVP_PKEY_CTX_free(ctx);
9✔
1643
    } else {
1644
        logerr(self->logfile, "Could not create key creation context!\n");
×
1645
        goto error_free_bn;
×
1646
    }
1647
    ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
9✔
1648
    if (ctx == NULL)
9✔
1649
        goto error_free_bn;
×
1650
#else
1651
    pkey = EVP_PKEY_new();
1652
    if (pkey == NULL) {
1653
        logerr(self->logfile, "Could not allocate pkey!\n");
1654
        goto error_free_bn;
1655
    }
1656

1657
# if OPENSSL_VERSION_NUMBER < 0x10100000
1658
    rsakey->n = mod;
1659
    rsakey->e = exp;
1660
# else
1661
    if (RSA_set0_key(rsakey, mod, exp, NULL) != 1) {
1662
        logerr(self->logfile, "Could not create public RSA key!\n");
1663
        goto error_free_bn;
1664
    }
1665
# endif
1666
    if (EVP_PKEY_assign_RSA(pkey, rsakey) != 1) {
1667
        logerr(self->logfile, "Could not create public RSA key!\n");
1668
        goto error_free_pkey_and_rsa;
1669
    }
1670

1671
    ctx = EVP_PKEY_CTX_new(pkey, NULL);
1672
    if (ctx == NULL)
1673
        goto error_free_pkey;
1674
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
1675

1676
    if (EVP_PKEY_encrypt_init(ctx) < 1 ||
18✔
1677
        EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) < 1 ||
18✔
1678
        EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sha1) < 1 ||
18✔
1679
        EVP_PKEY_CTX_set_rsa_oaep_md(ctx, sha1) < 1 ||
18✔
1680
        EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, g_strdup("TCPA"), 4) < 1 ||
18✔
1681
        EVP_PKEY_encrypt(ctx, enc_owner_auth, &enc_owner_auth_len,
9✔
1682
                         ownerpass_digest, SHA_DIGEST_LENGTH) < 1||
9✔
1683
        EVP_PKEY_encrypt(ctx, enc_srk_auth, &enc_srk_auth_len,
9✔
1684
                         srkpass_digest, SHA_DIGEST_LENGTH) < 1) {
1685
        logerr(self->logfile, "Internal error in %s: encryption failed\n", __func__);
×
1686
        goto error;
×
1687
    }
1688
    ret = swtpm_tpm12_oiap(self, &auth_handle, nonce_even);
9✔
1689
    if (ret != 0)
9✔
1690
        goto error;
×
1691

1692
    tpm_rsa_key_parms_len = memconcat(&tpm_rsa_key_parms,
18✔
1693
                                      (unsigned char[]){
9✔
1694
                                          AS4BE(2048), AS4BE(2), AS4BE(0)
1695
                                      }, (size_t)12,
1696
                                      NULL);
1697
    if (tpm_rsa_key_parms_len < 0) {
9✔
1698
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1699
        goto error;
×
1700
    }
1701

1702
    tpm_key_parms_len = memconcat(&tpm_key_parms,
18✔
1703
                                  (unsigned char[]){
9✔
1704
                                      AS4BE(TPM_ALG_RSA),
1705
                                      AS2BE(TPM_ES_RSAESOAEP_SHA1_MGF1),
1706
                                      AS2BE(TPM_SS_NONE),
1707
                                      AS4BE(tpm_rsa_key_parms_len)}, (size_t)12,
9✔
1708
                                  tpm_rsa_key_parms, tpm_rsa_key_parms_len,
1709
                                  NULL);
1710
    if (tpm_key_parms_len < 0) {
9✔
1711
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1712
        goto error;
×
1713
    }
1714

1715
    tpm_key12_len = memconcat(&tpm_key12,
18✔
1716
                              (unsigned char[]){
9✔
1717
                                  AS2BE(TPM_TAG_KEY12), AS2BE(0),
1718
                                  AS2BE(TPM_KEY_STORAGE), AS4BE(0), TPM_AUTH_ALWAYS
1719
                              }, (size_t)11,
1720
                              tpm_key_parms, tpm_key_parms_len,
1721
                              (unsigned char[]){AS4BE(0), AS4BE(0), AS4BE(0)}, (size_t)12,
9✔
1722
                              NULL);
1723
    if (tpm_key12_len < 0) {
9✔
1724
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1725
        goto error;
×
1726
    }
1727

1728
    req_len = concat(req, sizeof(req),
18✔
1729
                     &hdr, sizeof(hdr),
1730
                     (unsigned char[]){AS2BE(TPM_PID_OWNER), AS4BE(enc_owner_auth_len)}, (size_t)6,
9✔
1731
                     enc_owner_auth, enc_owner_auth_len,
1732
                     (unsigned char[]){AS4BE(enc_srk_auth_len)}, (size_t)4,
9✔
1733
                     enc_srk_auth, enc_srk_auth_len,
1734
                     tpm_key12, tpm_key12_len,
1735
                     NULL);
1736
    if (req_len < 0) {
9✔
1737
        logerr(self->logfile, "Internal error in %s: req is too small\n");
×
1738
        goto error;
×
1739
    }
1740
    SHA1(&req[6], req_len - 6, in_param_digest);
9✔
1741

1742
    in_auth_setup_params_len = memconcat(&in_auth_setup_params,
9✔
1743
                                         nonce_even, sizeof(nonce_even),
1744
                                         nonce_odd, sizeof(nonce_odd),
1745
                                         &continue_auth_session, (size_t)1,
1746
                                         NULL);
1747
    if (in_auth_setup_params_len < 0) {
9✔
1748
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1749
        goto error;
×
1750
    }
1751

1752
    macinput_len = memconcat(&macinput,
9✔
1753
                             in_param_digest, sizeof(in_param_digest),
1754
                             in_auth_setup_params, in_auth_setup_params_len,
1755
                             NULL);
1756
    if (macinput_len < 0) {
9✔
1757
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1758
        goto error;
×
1759
    }
1760

1761
    HMAC(sha1, ownerpass_digest, SHA_DIGEST_LENGTH, macinput, macinput_len,
9✔
1762
         owner_auth, &owner_auth_len);
1763

1764
    len = concat(&req[req_len], sizeof(req) - req_len,
18✔
1765
                 (unsigned char[]){AS4BE(auth_handle)}, (size_t)4,
9✔
1766
                 nonce_odd, sizeof(nonce_odd),
1767
                 &continue_auth_session, (size_t)1,
1768
                 owner_auth, owner_auth_len,
1769
                 NULL);
1770
    if (len < 0) {
9✔
1771
        logerr(self->logfile, "Internal error in %s: req is too small\n");
×
1772
        goto error;
×
1773
    }
1774
    req_len += len;
9✔
1775

1776
    trh = (struct tpm_req_header *)req; /* old gcc type-punned pointer */
9✔
1777
    trh->size = htobe32(req_len);
9✔
1778

1779
    ret = transfer(self, req, req_len, "TPM_TakeOwnership", FALSE, NULL, 0);
9✔
1780

1781
error:
9✔
1782
    EVP_PKEY_free(pkey);
9✔
1783
    EVP_PKEY_CTX_free(ctx);
9✔
1784
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1785
    BN_free(exp);
9✔
1786
    BN_free(mod);
9✔
1787
#endif
1788
    return ret;
9✔
1789

1790
error_free_bn:
×
1791
    BN_free(exp);
×
1792
    BN_free(mod);
×
1793

1794
#if OPENSSL_VERSION_NUMBER < 0x30000000L
1795
error_free_pkey_and_rsa:
1796
    RSA_free(rsakey);
1797
error_free_pkey:
1798
#else
1799
    EVP_PKEY_CTX_free(ctx);
×
1800
#endif
1801
    EVP_PKEY_free(pkey);
×
1802

1803
    return 1;
×
1804
}
1805

1806
static int swtpm_tpm12_nv_define_space(struct swtpm *self, uint32_t nvindex,
27✔
1807
                                       uint32_t nvindexattrs, size_t size)
1808
{
1809
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_DEFINE_SPACE);
27✔
1810
    g_autofree unsigned char *pcr_info_short = NULL;
54✔
1811
    ssize_t pcr_info_short_len;
27✔
1812
    g_autofree unsigned char *nv_data_public = NULL;
27✔
1813
    ssize_t nv_data_public_len;
27✔
1814
    g_autofree unsigned char *req = NULL;
27✔
1815
    ssize_t req_len;
27✔
1816
    unsigned char zeroes[SHA_DIGEST_LENGTH] = {0, };
27✔
1817

1818
    pcr_info_short_len = memconcat(&pcr_info_short,
54✔
1819
                                   (unsigned char[]){AS2BE(3), 0, 0, 0, TPM_LOC_ALL}, (size_t)6,
27✔
1820
                                   zeroes, sizeof(zeroes),
1821
                                   NULL);
1822
    if (pcr_info_short_len < 0) {
27✔
1823
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1824
        return 1;
×
1825
    }
1826

1827
    nv_data_public_len = memconcat(&nv_data_public,
54✔
1828
                                   (unsigned char[]){
27✔
1829
                                       AS2BE(TPM_TAG_NV_DATA_PUBLIC), AS4BE(nvindex)
27✔
1830
                                   }, (size_t)6,
1831
                                   pcr_info_short, pcr_info_short_len,
1832
                                   pcr_info_short, pcr_info_short_len,
1833
                                   (unsigned char[]){
27✔
1834
                                       AS2BE(TPM_TAG_NV_ATTRIBUTES), AS4BE(nvindexattrs),
27✔
1835
                                       0, 0, 0, AS4BE(size)
27✔
1836
                                   }, (size_t)13,
1837
                                   NULL);
1838
    if (nv_data_public_len < 0) {
27✔
1839
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1840
        return 1;
×
1841
    }
1842

1843
    req_len = memconcat(&req,
27✔
1844
                        &hdr, sizeof(hdr),
1845
                        nv_data_public, nv_data_public_len,
1846
                        zeroes, sizeof(zeroes),
1847
                        NULL);
1848
    if (req_len < 0) {
27✔
1849
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1850
        return 1;
×
1851
    }
1852

1853
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
27✔
1854

1855
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE, NULL, 0);
27✔
1856
}
1857

1858
static int swtpm_tpm12_nv_write_value(struct swtpm *self, uint32_t nvindex,
15✔
1859
                                      const unsigned char *data, size_t data_len)
1860
{
1861
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_WRITE_VALUE);
15✔
1862
    g_autofree unsigned char *req = NULL;
30✔
1863
    ssize_t req_len;
15✔
1864

1865
    req_len = memconcat(&req,
30✔
1866
                        &hdr, sizeof(hdr),
1867
                        (unsigned char[]){AS4BE(nvindex), AS4BE(0), AS4BE(data_len)}, (size_t)12,
15✔
1868
                        data, data_len,
1869
                        NULL);
1870
    if (req_len < 0) {
15✔
1871
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1872
        return 1;
×
1873
    }
1874

1875
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
15✔
1876

1877
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE, NULL, 0);
15✔
1878
}
1879

1880
/* Write the EK Certificate into NVRAM */
1881
static int swtpm_tpm12_write_ek_cert_nvram(struct swtpm *self,
8✔
1882
                                           const unsigned char *data, size_t data_len)
1883
{
1884
    uint32_t nvindex = TPM_NV_INDEX_EKCERT | TPM_NV_INDEX_D_BIT;
8✔
1885
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
8✔
1886
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
1887
    if (ret != 0)
8✔
1888
        return 1;
1889

1890
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
8✔
1891
    if (ret != 0)
8✔
1892
        return 1;
×
1893

1894
    return 0;
1895
}
1896

1897
/* Write the Platform Certificate into NVRAM */
1898
static int swtpm_tpm12_write_platform_cert_nvram(struct swtpm *self,
7✔
1899
                                                 const unsigned char *data, size_t data_len)
1900
{
1901
    uint32_t nvindex = TPM_NV_INDEX_PLATFORMCERT | TPM_NV_INDEX_D_BIT;
7✔
1902
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
7✔
1903
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
1904
    if (ret != 0)
7✔
1905
        return 1;
1906

1907
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
7✔
1908
    if (ret != 0)
7✔
1909
        return 1;
×
1910

1911
    return 0;
1912
}
1913

1914
static int swtpm_tpm12_nv_lock(struct swtpm *self)
12✔
1915
{
1916
    return swtpm_tpm12_nv_define_space(self, TPM_NV_INDEX_LOCK, 0, 0);
12✔
1917
}
1918

1919
static const struct swtpm12_ops swtpm_tpm12_ops = {
1920
    .run_swtpm_bios = swtpm_tpm12_run_swtpm_bios,
1921
    .create_endorsement_key_pair = swptm_tpm12_create_endorsement_keypair,
1922
    .take_ownership = swtpm_tpm12_take_ownership,
1923
    .write_ek_cert_nvram = swtpm_tpm12_write_ek_cert_nvram,
1924
    .write_platform_cert_nvram = swtpm_tpm12_write_platform_cert_nvram,
1925
    .nv_lock = swtpm_tpm12_nv_lock,
1926
};
1927

1928
static void swtpm_init(struct swtpm *swtpm,
72✔
1929
                       gchar **swtpm_exec_l, const gchar *state_path,
1930
                       const gchar *keyopts, const gchar *logfile,
1931
                       int *fds_to_pass, size_t n_fds_to_pass,
1932
                       gboolean is_tpm2)
1933
{
1934
    swtpm->cops = &swtpm_cops;
72✔
1935
    swtpm->swtpm_exec_l = swtpm_exec_l;
72✔
1936
    swtpm->state_path = state_path;
72✔
1937
    swtpm->keyopts = keyopts;
72✔
1938
    swtpm->logfile = logfile;
72✔
1939
    swtpm->fds_to_pass = fds_to_pass;
72✔
1940
    swtpm->n_fds_to_pass = n_fds_to_pass;
72✔
1941
    swtpm->is_tpm2 = is_tpm2;
72✔
1942

1943
    swtpm->pid = -1;
72✔
1944
    swtpm->ctrl_fds[0] = swtpm->ctrl_fds[1] = -1;
72✔
1945
    swtpm->data_fds[0] = swtpm->data_fds[1] = -1;
72✔
1946
}
1947

1948
struct swtpm12 *swtpm12_new(gchar **swtpm_exec_l, const gchar *state_path,
26✔
1949
                            const gchar *keyopts, const gchar *logfile,
1950
                            int *fds_to_pass, size_t n_fds_to_pass)
1951
{
1952
    struct swtpm12 *swtpm12 = g_malloc0(sizeof(struct swtpm12));
26✔
1953

1954
    swtpm_init(&swtpm12->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
26✔
1955
               fds_to_pass, n_fds_to_pass, FALSE);
1956
    swtpm12->ops = &swtpm_tpm12_ops;
26✔
1957

1958
    return swtpm12;
26✔
1959
}
1960

1961
struct swtpm2 *swtpm2_new(gchar **swtpm_exec_l, const gchar *state_path,
46✔
1962
                         const gchar *keyopts, const gchar *logfile,
1963
                         int *fds_to_pass, size_t n_fds_to_pass)
1964
{
1965
    struct swtpm2 *swtpm2 = g_malloc0(sizeof(struct swtpm2));
46✔
1966

1967
    swtpm_init(&swtpm2->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
46✔
1968
               fds_to_pass, n_fds_to_pass, TRUE);
1969
    swtpm2->ops = &swtpm_tpm2_ops;
46✔
1970

1971
    return swtpm2;
46✔
1972
}
1973

1974
void swtpm_free(struct swtpm *swtpm) {
72✔
1975
    if (!swtpm)
72✔
1976
        return;
1977
    g_free(swtpm);
72✔
1978
}
1979

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