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

stefanberger / swtpm / 621325588

05 May 2024 09:04PM UTC coverage: 73.542% (+0.2%) from 73.324%
621325588

push

travis-ci

web-flow
Merge defd1f468 into bfd6b8270

7163 of 9740 relevant lines covered (73.54%)

14121.07 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

24
#include <glib.h>
25

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

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

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

47
#define CMD_DURATION_SHORT  2000 /* ms */
48

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

300
    return 0;
301
}
302

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

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

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

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

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

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

337
    return 0;
74✔
338

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

342
    return 1;
×
343
}
344

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

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

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

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

370
#define TPM2_SU_CLEAR        0x0000
371

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

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

391
#define TPM2_CAP_PCRS     0x00000005
392

393
#define TPM2_ECC_NIST_P384 0x0004
394

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

548
    *all_pcr_banks = NULL;
47✔
549

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

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

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

561
    offset = 19;
47✔
562

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

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

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

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

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

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

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

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

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

598
    return 1;
×
599
}
600

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

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

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

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

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

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

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

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

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

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

698
    return 0;
699

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

704
    return 1;
×
705
}
706

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

939
    return 0;
940

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

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

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

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

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

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

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

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

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

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

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

1058
    return 0;
1059

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

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

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

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

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

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

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

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

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

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

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

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

1138
    return ret;
1139
}
1140

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

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

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

1202
    return ret;
39✔
1203
}
1204

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

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

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

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

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

1268
    return ret;
1269
}
1270

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1400
    return 0;
1401
}
1402

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

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

1418
    return ret;
99✔
1419
}
1420

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

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

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

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

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

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

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

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

1491
#define TPM_ST_CLEAR 0x0001
1492

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

1496
#define TPM_ALG_RSA 0x00000001
1497

1498
#define TPM_KEY_STORAGE 0x0011
1499

1500
#define TPM_AUTH_ALWAYS 0x01
1501

1502
#define TPM_PID_OWNER  0x0005
1503

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

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

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

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

1519
#define TPM_NV_INDEX_LOCK 0xFFFFFFFF
1520

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

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

1527
#define TPM_KH_EK    0x40000006
1528

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

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

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

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

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

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

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

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

1579
    return 0;
1580
}
1581

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

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

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

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

1616
    return 0;
19✔
1617

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

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

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

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

1642
    return 0;
9✔
1643

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1880
    return 1;
×
1881
}
1882

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

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

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

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

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

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

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

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

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

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

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

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

1973
    return 0;
1974
}
1975

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

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

1990
    return 0;
1991
}
1992

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

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

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

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

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

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

2037
    return swtpm12;
26✔
2038
}
2039

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

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

2050
    return swtpm2;
47✔
2051
}
2052

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

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