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

stefanberger / swtpm / #2935

15 Apr 2026 01:09PM UTC coverage: 73.485% (+0.07%) from 73.414%
#2935

push

travis-ci

web-flow
Merge fde6e50a4 into 8c3f99ce8

209 of 252 new or added lines in 2 files covered. (82.94%)

321 existing lines in 3 files now uncovered.

7824 of 10647 relevant lines covered (73.49%)

10090.02 hits per line

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

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

10
#include "config.h"
11

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

25
#include <glib.h>
26

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

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

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

49
#define CMD_DURATION_SHORT  (2000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
50

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

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

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

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

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

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

106
    argv = concat_arrays((const char **)self->swtpm_exec_l,
312✔
107
                         (const gchar*[]){
156✔
108
                              "--flags", "not-need-init,startup-clear",
109
                              "--tpmstate", tpmstate,
110
                              "--pid", pidfile_arg,
111
#if 0
112
                              "--log", "file=/tmp/log,level=20",
113
#endif
114
                              NULL
115
                         }, FALSE);
116

117
    if (self->is_tpm2)
156✔
118
        argv = concat_arrays(argv, (const gchar*[]){"--tpm2", NULL}, TRUE);
130✔
119

120
    if (self->keyopts != NULL) {
156✔
121
        keyopts = g_strdup(self->keyopts);
33✔
122
        argv = concat_arrays(argv, (const gchar*[]){"--key", keyopts, NULL}, TRUE);
33✔
123
    }
124

125
    if (self->json_profile_fd >= 0) {
156✔
126
        json_profile = g_strdup_printf("fd=%u", self->json_profile_fd);
31✔
127
    } else if (self->json_profile != NULL) {
125✔
128
        json_profile = g_strdup_printf("profile=%s", self->json_profile);
89✔
129
        logit(self->logfile, "Apply profile: %s\n", self->json_profile);
89✔
130
    }
131
    if (json_profile && self->profile_remove_disabled_param) {
120✔
132
        tmp = g_strdup_printf("%s,remove-disabled=%s",
6✔
133
                              json_profile,
134
                              self->profile_remove_disabled_param);
135
        g_free(json_profile);
6✔
136
        json_profile = tmp;
6✔
137
    }
138
    if (json_profile)
156✔
139
        argv = concat_arrays(argv, (const gchar*[]){
120✔
140
                                 "--profile",
141
                                 json_profile,
142
                                 json_profile_params,
143
                                 NULL
144
                             }, TRUE);
145

146
    if (gl_LOGFILE != NULL) {
156✔
147
        logop = g_strdup_printf("file=%s", gl_LOGFILE);
87✔
148
        argv = concat_arrays(argv, (const gchar*[]){"--log", logop, NULL}, TRUE);
87✔
149
    }
150

151
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, self->ctrl_fds) != 0) {
156✔
152
        logerr(self->logfile, "Could not create socketpair: %s\n", strerror(errno));
×
153
        goto error;
×
154
    }
155
    ctrl_fd = g_strdup_printf("type=unixio,clientfd=%d", self->ctrl_fds[1]);
156✔
156

157
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, self->data_fds) != 0) {
156✔
158
        logerr(self->logfile, "Could not create socketpair: %s\n", strerror(errno));
×
159
        goto error;
×
160
    }
161
    server_fd = g_strdup_printf("type=tcp,fd=%d", self->data_fds[1]);
156✔
162

163
    argv = concat_arrays(argv, (const gchar*[]){
156✔
164
                             "--server", server_fd,
165
                             "--ctrl", ctrl_fd,
166
                             NULL
167
                         }, TRUE);
168

169
#if 0
170
    {
171
        g_autofree gchar *join = g_strjoinv(" ", argv);
172
        logit(self->logfile, "Starting swtpm: %s\n", join);
173
    }
174
#endif
175

176
    flags = G_SPAWN_LEAVE_DESCRIPTORS_OPEN;
156✔
177
    if (gl_LOGFILE) {
156✔
178
        flags |= G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
179
    } else {
180
#if GLIB_CHECK_VERSION(2, 74, 0)
181
        flags |= G_SPAWN_CHILD_INHERITS_STDOUT | G_SPAWN_CHILD_INHERITS_STDERR;
69✔
182
#endif
183
    }
184

185
    success = spawn_async(NULL, argv, NULL, flags,
156✔
186
                          NULL, NULL, &self->pid, &error);
187
    if (!success) {
156✔
188
        logerr(self->logfile, "Could not start swtpm: %s\n", error->message);
×
189
        g_error_free(error);
×
190
        goto error;
×
191
    }
192

193
    /* wait until the pidfile is written to or swtpm terminates */
194
    for (ctr = 0; ctr < 1000; ctr++) {
920✔
195
        if (kill(self->pid, 0) < 0) {
920✔
196
            /* swtpm terminated */
197
            self->pid = 0;
1✔
198
            logerr(self->logfile, "swtpm process terminated unexpectedly.\n");
1✔
199
            self->cops->stop(self);
1✔
200
            goto error;
1✔
201
        }
202
        if (fstat(pidfile_fd, &statbuf) == 0 && statbuf.st_size > 0) {
919✔
203
            printf("TPM is listening on Unix socket.\n");
155✔
204
            ret = 0;
155✔
205
            break;
155✔
206
        }
207
        usleep(5000);
764✔
208
    }
209

210
error:
×
211
    swtpm_close_comm(self, ret != 0);
156✔
212

213
    close(pidfile_fd);
156✔
214
    unlink(pidfile);
156✔
215

216
error_no_pidfile:
156✔
217
    return ret;
156✔
218
}
219

220
/* Stop a running swtpm instance and close all the file descriptors connecting to it */
221
static void swtpm_stop(struct swtpm *self)
150✔
222
{
223
    unsigned c;
150✔
224
    gboolean ended = FALSE;
150✔
225

226
    if (self->pid > 0) {
150✔
227
        self->cops->ctrl_shutdown(self);
149✔
228
        for (c = 0; c < 500; c++) {
664✔
229
            if (kill(self->pid, 0) < 0) {
515✔
230
                ended = TRUE;
231
                break;
232
            }
233
            usleep(1000);
366✔
234
        }
235
        if (!ended)
149✔
236
            kill(self->pid, SIGKILL);
×
237
        waitpid(self->pid, NULL, 0);
149✔
238

239
        self->pid = 0;
149✔
240
    }
241

242
    swtpm_close_comm(self, true);
150✔
243
}
150✔
244

245
/* Destroy a running swtpm instance */
246
static void swtpm_destroy(struct swtpm *self)
149✔
247
{
248
    self->cops->stop(self);
149✔
249
}
149✔
250

251
/* Send a command to swtpm and receive the response either via control or data channel */
252
static int transfer(struct swtpm *self, void *buffer, size_t buffer_len,
1,520✔
253
                    const char *cmdname, gboolean use_ctrl,
254
                    void *respbuffer, size_t *respbuffer_len, int timeout_ms)
255
{
256
    size_t offset;
1,520✔
257
    int sockfd;
1,520✔
258
    ssize_t n;
1,520✔
259
    unsigned char resp[4096];
1,520✔
260
    ssize_t resplen;
1,520✔
261
    uint32_t returncode;
1,520✔
262
    struct pollfd fds = {
1,520✔
263
        .events = POLLIN | POLLERR | POLLHUP,
264
    };
265
    size_t respbuffer_size = 0;
1,520✔
266

267
    if (respbuffer_len) {
1,520✔
268
        respbuffer_size = *respbuffer_len;
479✔
269
        *respbuffer_len = 0; /* nothing returned in most error cases */
479✔
270
    }
271

272
    if (use_ctrl) {
1,520✔
273
        sockfd = self->ctrl_fds[0];
367✔
274
        offset = 0;
367✔
275
    } else {
276
        sockfd = self->data_fds[0];
1,153✔
277
        offset = 6;
1,153✔
278
    }
279

280
    n = write(sockfd, buffer, buffer_len);
1,520✔
281
    if (n < 0) {
1,520✔
282
        logerr(self->logfile, "Could not send %s buffer to swtpm: %s\n",
10✔
283
               cmdname, strerror(errno));
5✔
284
        return 1;
5✔
285
    }
286
    if ((size_t)n != buffer_len) {
1,515✔
287
        logerr(self->logfile, "Could not send all bytes to swtpm: %zu < %zu\n",
×
288
               (size_t)n, buffer_len);
289
        return 1;
×
290
    }
291

292
    fds.fd = sockfd;
1,515✔
293
    n = poll(&fds, 1, timeout_ms);
1,515✔
294
    if (n != 1 || (fds.revents & POLLIN) == 0) {
1,515✔
295
        logerr(self->logfile, "Could not receive response to %s from swtpm: %s\n",
×
296
               cmdname,
297
               n < 0 ? strerror(errno) : "timeout");
×
298
        return 1;
×
299
    }
300

301
    resplen = read(sockfd, resp, sizeof(resp));
1,515✔
302
    if (resplen < 0) {
1,515✔
303
        logerr(self->logfile, "Could not receive response to %s from swtpm: %s\n",
2✔
304
               cmdname, strerror(errno));
1✔
305
        return 1;
1✔
306
    }
307

308
    if (!use_ctrl) {
1,514✔
309
        if ((size_t)resplen < sizeof(struct tpm_resp_header)) {
1,153✔
310
            logerr(self->logfile,
×
311
                   "Response for %s has only %zd bytes.\n", cmdname, resplen);
312
            return 1;
×
313
        }
314
    } else if ((size_t)resplen < 4) {
361✔
315
        logerr(self->logfile,
×
316
               "Response for %s has only %zd bytes.\n", cmdname, resplen);
317
        return 1;
×
318
    }
319

320
    if (respbuffer && respbuffer_len) {
1,514✔
321
        /* give caller response even if command failed */
322
        *respbuffer_len = min((size_t)resplen, respbuffer_size);
473✔
323
        memcpy(respbuffer, resp, *respbuffer_len);
473✔
324
    }
325

326
    memcpy(&returncode, &resp[offset], sizeof(returncode));
1,514✔
327
    returncode = be32toh(returncode);
1,514✔
328
    if (returncode != 0) {
1,514✔
329
        logerr(self->logfile,
×
330
               "%s failed: 0x%x\n", cmdname, returncode);
331
        return 1;
×
332
    }
333

334
    return 0;
335
}
336

337
/* Send a CMD_SHUTDOWN over the control channel */
338
static int swtpm_ctrl_shutdown(struct swtpm *self)
149✔
339
{
340
    uint32_t cmd = htobe32(CMD_SHUTDOWN);
149✔
341

342
    return transfer(self, &cmd, sizeof(cmd), "CMD_SHUTDOWN", TRUE,
149✔
343
                    NULL, NULL, CMD_DURATION_SHORT);
344
}
345

346
/* Get the TPM specification parameters over the control channel */
347
static int do_cmd_get_info(struct swtpm *self, uint64_t swtpm_info_flags,
218✔
348
                           gchar **result)
349
{
350
    unsigned char req[] = {AS4BE(CMD_GET_INFO),
218✔
351
                           AS8BE(swtpm_info_flags),
218✔
352
                           AS4BE(0), AS4BE(0)};
353
    unsigned char tpmresp[16 * 1024];
218✔
354
    size_t tpmresp_len = sizeof(tpmresp);
218✔
355
    int ret;
218✔
356
    uint32_t length;
218✔
357

358
    ret = transfer(self, req, sizeof(req), "CMD_GET_INFO", TRUE,
218✔
359
                   tpmresp, &tpmresp_len, CMD_DURATION_SHORT);
360
    if (ret != 0)
218✔
361
        return 1;
362

363
    if (tpmresp_len < 8 + sizeof(length))
212✔
364
        goto err_too_short;
×
365
    memcpy(&length, &tpmresp[8], sizeof(length));
212✔
366
    length = htobe32(length);
212✔
367

368
    if (tpmresp_len < 12 + length)
212✔
369
        goto err_too_short;
×
370
    *result = g_strndup((gchar *)&tpmresp[12], length);
212✔
371

372
    return 0;
212✔
373

374
err_too_short:
×
375
    logerr(self->logfile, "Response from CMD_GET_INFO is too short!\n");
×
376

377
    return 1;
×
378
}
379

380
static int swtpm_ctrl_get_tpm_specs_and_attrs(struct swtpm *self, gchar **result)
95✔
381
{
382
    return do_cmd_get_info(self,
95✔
383
                           SWTPM_INFO_TPMSPECIFICATION | SWTPM_INFO_TPMATTRIBUTES,
384
                           result);
385
}
386

387
static const struct swtpm_cops swtpm_cops = {
388
    .start = swtpm_start,
389
    .stop = swtpm_stop,
390
    .destroy = swtpm_destroy,
391
    .ctrl_shutdown = swtpm_ctrl_shutdown,
392
    .ctrl_get_tpm_specs_and_attrs = swtpm_ctrl_get_tpm_specs_and_attrs,
393
};
394

395
/*
396
 * TPM 2 support
397
 */
398

399
#define TPM2_ST_NO_SESSIONS  0x8001
400
#define TPM2_ST_SESSIONS     0x8002
401

402
#define TPM2_CC_EVICTCONTROL   0x00000120
403
#define TPM2_CC_NV_DEFINESPACE 0x0000012a
404
#define TPM2_CC_PCR_ALLOCATE   0x0000012b
405
#define TPM2_CC_CREATEPRIMARY  0x00000131
406
#define TPM2_CC_NV_WRITE       0x00000137
407
#define TPM2_CC_NV_WRITELOCK   0x00000138
408
#define TPM2_CC_SHUTDOWN       0x00000145
409
#define TPM2_CC_FLUSHCONTEXT   0x00000165
410
#define TPM2_CC_GETCAPABILITY  0x0000017a
411

412
#define TPM2_SU_CLEAR        0x0000
413

414
#define TPM2_RH_OWNER        0x40000001
415
#define TPM2_RS_PW           0x40000009
416
#define TPM2_RH_ENDORSEMENT  0x4000000b
417
#define TPM2_RH_PLATFORM     0x4000000c
418

419
#define TPM2_ALG_RSA      0x0001
420
#define TPM2_ALG_SHA1     0x0004
421
#define TPM2_ALG_AES      0x0006
422
#define TPM2_ALG_SHA256   0x000b
423
#define TPM2_ALG_SHA384   0x000c
424
#define TPM2_ALG_SHA512   0x000d
425
#define TPM2_ALG_SHA3_256 0x0027
426
#define TPM2_ALG_SHA3_384 0x0028
427
#define TPM2_ALG_SHA3_512 0x0029
428
#define TPM2_ALG_NULL     0x0010
429
#define TPM2_ALG_SM3      0x0012
430
#define TPM2_ALG_ECC      0x0023
431
#define TPM2_ALG_CFB      0x0043
432

433
#define TPM2_CAP_PCRS     0x00000005
434

435
#define TPMA_NV_PLATFORMCREATE 0x40000000
436
#define TPMA_NV_AUTHREAD       0x40000
437
#define TPMA_NV_NO_DA          0x2000000
438
#define TPMA_NV_PPWRITE        0x1
439
#define TPMA_NV_PPREAD         0x10000
440
#define TPMA_NV_OWNERREAD      0x20000
441
#define TPMA_NV_WRITEDEFINE    0x2000
442

443
// Use standard EK Cert NVRAM, EK and SRK handles per IWG spec.
444
// "TCG TPM v2.0 Provisioning Guide"; Version 1.0, Rev 1.0, March 15, 2017
445
// Table 2
446
#define TPM2_NV_INDEX_RSA2048_EKCERT         0x01c00002
447
#define TPM2_NV_INDEX_RSA2048_EKTEMPLATE     0x01c00004
448
#define TPM2_NV_INDEX_RSA3072_HI_EKCERT      0x01c0001c
449
#define TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE  0x01c0001d
450
#define TPM2_NV_INDEX_RSA4096_HI_EKCERT      0x01c0001e
451
#define TPM2_NV_INDEX_RSA4096_HI_EKTEMPLATE  0x01c0001f
452
// For ECC follow "TCG EK Credential Profile For TPM Family 2.0; Level 0"
453
// Specification Version 2.1; Revision 13; 10 December 2018
454
#define TPM2_NV_INDEX_PLATFORMCERT           0x01c08000
455

456
#define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT     0x01c00016
457
#define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE 0x01c00017
458

459
#define TPM2_EK_RSA_HANDLE           0x81010001
460
#define TPM2_EK_RSA3072_HANDLE       0x8101001c
461
#define TPM2_EK_RSA4096_HANDLE       0x8101001e
462
#define TPM2_EK_ECC_SECP384R1_HANDLE 0x81010016
463
#define TPM2_SPK_HANDLE              0x81000001
464

465
#define TPM2_DURATION_SHORT      ( 2000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
466
#define TPM2_DURATION_MEDIUM     ( 7500 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
467
#define TPM2_DURATION_LONG       (15000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
468
#define TPM2_DURATION_EXTRA_LONG (30000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
469

470
#define TPM_REQ_HEADER_INITIALIZER(TAG, SIZE, ORD) \
471
    { \
472
        .tag = htobe16(TAG), \
473
        .size = htobe32(SIZE), \
474
        .ordinal = htobe32(ORD), \
475
    }
476

477
struct tpm2_authblock {
478
    uint32_t auth;
479
    uint16_t nonceSize; // currently always 0
480
    uint8_t continueSession;
481
    uint16_t pwdSize; // currently always 0
482
} __attribute__((packed));
483

484
#define TPM2_AUTHBLOCK_INITIALIZER(AUTH) \
485
    { \
486
        .auth = htobe32(AUTH), \
487
        .nonceSize = htobe16(0), \
488
        .continueSession = 0, \
489
        .pwdSize = htobe16(0), \
490
    }
491

492
static const unsigned char NONCE_EMPTY[2] = {AS2BE(0)};
493
static const unsigned char NONCE_RSA2048[2+0x100] = {AS2BE(0x100), 0, };
494
static const unsigned char NONCE_RSA3072[2+0x180] = {AS2BE(0x180), 0, };
495
static const unsigned char NONCE_RSA4096[2+0x200] = {AS2BE(0x200), 0, };
496
static const unsigned char NONCE_ECC_384[2+0x30] = {AS2BE(0x30), 0, };
497

498
static const unsigned char PolicyA_SHA256[32] = {
499
    0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d,
500
    0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64,
501
    0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa
502
};
503

504
static const unsigned char PolicyB_SHA384[48] = {
505
    0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC,
506
    0x53, 0xD8, 0x82, 0xBC, 0xF5, 0xFD, 0x3A, 0x1A,
507
    0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4,
508
    0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA,
509
    0xCB, 0x47, 0xBA, 0x09, 0x69, 0x96, 0x46, 0x15,
510
    0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12
511
};
512

513
static const struct bank_to_name {
514
    uint16_t hashAlg;
515
    const char *name;
516
} banks_to_names[] = {
517
    {TPM2_ALG_SHA1, "sha1"},
518
    {TPM2_ALG_SHA256, "sha256"},
519
    {TPM2_ALG_SHA384, "sha384"},
520
    {TPM2_ALG_SHA512, "sha512"},
521
    {TPM2_ALG_SM3, "sm3-256"},
522
    {TPM2_ALG_SHA3_256, "sha3-256"},
523
    {TPM2_ALG_SHA3_384, "sha3-384"},
524
    {TPM2_ALG_SHA3_512, "sha3-512"},
525
    {0, NULL},
526
};
527

528
struct pk_params {
529
    enum keyalgo keyalgo;
530
    uint16_t keyalgo_param; // RSA key size or ECC curve Id
531
    const char *keydescription;
532
    const unsigned char *nonce;
533
    size_t nonce_len;
534
    uint16_t hashalg;
535
    const unsigned char *authpolicy;
536
    size_t authpolicy_len;
537
    unsigned int symkey_len;
538
    int duration;
539
    unsigned keysize;
540
};
541

542
static const struct ek_params {
543
    struct pk_params pk;
544
    uint32_t ek_handle;
545
    const char *keytype;
546
    uint32_t nvindex_ekcert;
547
    uint32_t nvindex_template;
548
} ek_params[] = {
549
    {
550
        .pk = {
551
            .keyalgo = KEYALGO_ECC,
552
            .keyalgo_param = TPM2_ECC_NIST_P384,
553
            .keydescription = "secp384r1",
554
            .nonce = NONCE_EMPTY,
555
            .nonce_len = sizeof(NONCE_EMPTY),
556
            .hashalg = TPM2_ALG_SHA384,
557
            .authpolicy = PolicyB_SHA384,
558
            .authpolicy_len = sizeof(PolicyB_SHA384),
559
            .symkey_len = 256,
560
            .duration = TPM2_DURATION_LONG,
561
            .keysize = 48,
562
        },
563
        .ek_handle = TPM2_EK_ECC_SECP384R1_HANDLE,
564
        .keytype = "ECC",
565
        .nvindex_ekcert = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT,
566
        .nvindex_template = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE,
567
    }, {
568
        .pk = {
569
            .keyalgo = KEYALGO_RSA,
570
            .keyalgo_param = 2048,
571
            .keydescription = "rsa2048",
572
            .nonce = NONCE_RSA2048,
573
            .nonce_len = sizeof(NONCE_RSA2048),
574
            .hashalg = TPM2_ALG_SHA256,
575
            .authpolicy = PolicyA_SHA256,
576
            .authpolicy_len = sizeof(PolicyA_SHA256),
577
            .symkey_len = 128,
578
            .duration = TPM2_DURATION_LONG,
579
            .keysize = 2048 / 8,
580
        },
581
        .ek_handle = TPM2_EK_RSA_HANDLE,
582
        .keytype = "RSA 2048",
583
        .nvindex_ekcert = TPM2_NV_INDEX_RSA2048_EKCERT,
584
        .nvindex_template = TPM2_NV_INDEX_RSA2048_EKTEMPLATE,
585
    }, {
586
        .pk = {
587
            .keyalgo = KEYALGO_RSA,
588
            .keyalgo_param = 3072,
589
            .keydescription = "rsa3072",
590
            .nonce = NONCE_EMPTY,
591
            .nonce_len = sizeof(NONCE_EMPTY),
592
            .hashalg = TPM2_ALG_SHA384,
593
            .authpolicy = PolicyB_SHA384,
594
            .authpolicy_len = sizeof(PolicyB_SHA384),
595
            .symkey_len = 256,
596
            .duration = TPM2_DURATION_LONG,
597
            .keysize = 3072 / 8,
598
        },
599
        .ek_handle = TPM2_EK_RSA3072_HANDLE,
600
        .keytype = "RSA 3072",
601
        .nvindex_ekcert = TPM2_NV_INDEX_RSA3072_HI_EKCERT,
602
        .nvindex_template = TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE,
603
    }, {
604
        .pk = {
605
            .keyalgo = KEYALGO_RSA,
606
            .keyalgo_param = 4096,
607
            .keydescription = "rsa4096",
608
            .nonce = NONCE_EMPTY,
609
            .nonce_len = sizeof(NONCE_EMPTY),
610
            .hashalg = TPM2_ALG_SHA384,
611
            .authpolicy = PolicyB_SHA384,
612
            .authpolicy_len = sizeof(PolicyB_SHA384),
613
            .symkey_len = 256,
614
            .duration = TPM2_DURATION_EXTRA_LONG,
615
            .keysize = 4096 / 8,
616
        },
617
        .ek_handle = TPM2_EK_RSA4096_HANDLE,
618
        .keytype = "RSA 4096",
619
        .nvindex_ekcert = TPM2_NV_INDEX_RSA4096_HI_EKCERT,
620
        .nvindex_template = TPM2_NV_INDEX_RSA4096_HI_EKTEMPLATE,
621
    }
622
};
623

624
static const struct ek_params *get_ek_params(struct swtpm *self,
289✔
625
                                             enum keyalgo keyalgo,
626
                                             unsigned int keyalgo_param)
627
{
628
    size_t i;
289✔
629

630
    for (i = 0; i < ARRAY_LEN(ek_params); i++) {
527✔
631
        if (ek_params[i].pk.keyalgo == keyalgo &&
527✔
632
            ek_params[i].pk.keyalgo_param == keyalgo_param) {
375✔
633
            return &ek_params[i];
289✔
634
        }
635
    }
NEW
636
    logerr(self->logfile, "Internal error: Unsupported keyalgo and keyalgo_param: %u/%u\n",
×
637
           keyalgo, keyalgo_param);
NEW
638
    return NULL;
×
639
}
640

641
/* function prototypes */
642
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
643
                                        const struct pk_params *pk_params,
644
                                        size_t off, uint32_t *curr_handle,
645
                                        unsigned char *ektemplate, size_t *ektemplate_len,
646
                                        gchar **ekparam, const gchar **key_description);
647

648
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
649
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
650
                                  const char *purpose);
651

652
/* Given a hash algo identifier, return the name of the hash bank */
653
static const char *get_name_for_bank(uint16_t hashAlg) {
442✔
654
    size_t i;
442✔
655

656
    for (i = 0; banks_to_names[i].name; i++) {
1,108✔
657
        if (banks_to_names[i].hashAlg == hashAlg)
1,108✔
658
            return banks_to_names[i].name;
659
    }
660
    return NULL;
661
}
662

663
/* Give the name of a hash bank, return its algo identifier */
664
static uint16_t get_hashalg_by_bankname(const char *name) {
440✔
665
    size_t i;
440✔
666

667
    for (i = 0; banks_to_names[i].name; i++) {
1,103✔
668
        if (strcmp(banks_to_names[i].name, name) == 0)
1,103✔
669
            return banks_to_names[i].hashAlg;
440✔
670
    }
671
    return 0;
672
}
673

674
/* Do an SU_CLEAR shutdown of the TPM 2 */
675
static int swtpm_tpm2_shutdown(struct swtpm *self)
122✔
676
{
677
    struct tpm2_shutdown_req {
122✔
678
        struct tpm_req_header hdr;
679
        uint16_t shutdownType;
680
    } __attribute__((packed)) req = {
122✔
681
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_SHUTDOWN),
122✔
682
        .shutdownType = htobe16(TPM2_SU_CLEAR)
122✔
683
    };
684

685
    return transfer(self, &req, sizeof(req), "TPM2_Shutdown", FALSE,
122✔
686
                    NULL, NULL, TPM2_DURATION_SHORT);
687
}
688

689
/* Get all available PCR banks */
690
static int swtpm_tpm2_get_all_pcr_banks(struct swtpm *self, gchar ***all_pcr_banks)
123✔
691
{
692
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, 0, TPM2_CC_GETCAPABILITY);
123✔
693
    g_autofree unsigned char *req = NULL;
246✔
694
    ssize_t req_len;
123✔
695
    unsigned char tpmresp[256];
123✔
696
    size_t tpmresp_len = sizeof(tpmresp);
123✔
697
    uint16_t count, bank;
123✔
698
    const char *name;
123✔
699
    uint8_t length;
123✔
700
    size_t offset;
123✔
701
    size_t i;
123✔
702
    int ret;
123✔
703

704
    req_len = memconcat(&req,
246✔
705
                        &hdr, sizeof(hdr),
706
                        (unsigned char[]){AS4BE(TPM2_CAP_PCRS), AS4BE(0), AS4BE(64)}, (size_t)12,
123✔
707
                        NULL);
708
    if (req_len < 0) {
123✔
UNCOV
709
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
UNCOV
710
        return 1;
×
711
    }
712
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
123✔
713

714
    ret = transfer(self, req, req_len, "TPM2_GetCapability", FALSE,
123✔
715
                   tpmresp, &tpmresp_len, TPM2_DURATION_MEDIUM);
716
    if (ret != 0)
123✔
717
        return 1;
718

719
    *all_pcr_banks = NULL;
123✔
720

721
    if (tpmresp_len < 17 + sizeof(count))
123✔
UNCOV
722
        goto err_too_short;
×
723
    memcpy(&count, &tpmresp[17], sizeof(count));
123✔
724
    count = be16toh(count);
123✔
725

726
    /* unreasonable number of PCR banks ? */
727
    if (count > 20)
123✔
UNCOV
728
        goto err_num_pcrbanks;
×
729

730
    *all_pcr_banks = g_malloc0(sizeof(char *) * (count + 1));
123✔
731

732
    offset = 19;
123✔
733

734
    for (i = 0; i < count; i++) {
565✔
735
        gchar *n;
442✔
736

737
        if (tpmresp_len < offset + sizeof(bank))
442✔
UNCOV
738
            goto err_too_short;
×
739
        memcpy(&bank, &tpmresp[offset], sizeof(bank));
442✔
740
        bank = be16toh(bank);
442✔
741

742
        if (tpmresp_len < offset + 2 + sizeof(length))
442✔
UNCOV
743
            goto err_too_short;
×
744
        length = tpmresp[offset + 2];
442✔
745

746
        name = get_name_for_bank(bank);
442✔
747
        if (name != NULL)
442✔
748
            n = g_strdup(name);
442✔
749
        else
UNCOV
750
            n = g_strdup_printf("%02x", bank);
×
751

752
        (*all_pcr_banks)[i] = n;
442✔
753

754
        offset += 2 + 1 + length;
442✔
755
    }
756
    return 0;
757

UNCOV
758
err_num_pcrbanks:
×
UNCOV
759
    logerr(self->logfile, "Unreasonable number of PCR banks (%u) returned.\n", count);
×
760
    goto err_exit;
×
761

762
err_too_short:
×
UNCOV
763
    logerr(self->logfile, "Response from TPM2_GetCapability is too short!\n");
×
764

UNCOV
765
err_exit:
×
UNCOV
766
    g_strfreev(*all_pcr_banks);
×
UNCOV
767
    *all_pcr_banks = NULL;
×
768

UNCOV
769
    return 1;
×
770
}
771

772
/* Activate all user-chosen PCR banks and deactivate all others */
773
static int swtpm_tpm2_set_active_pcr_banks(struct swtpm *self, gchar **pcr_banks,
123✔
774
                                           gchar **all_pcr_banks, gchar ***active)
775
{
776
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_PCR_ALLOCATE);
123✔
777
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
123✔
778
    unsigned char pcrselects[6 * 10]; // supports up to 10 PCR banks
123✔
779
    ssize_t pcrselects_len = 0;
123✔
780
    size_t count = 0;
123✔
781
    size_t idx, j;
123✔
782
    uint16_t hashAlg;
123✔
783
    g_autofree unsigned char *req = NULL;
246✔
784
    ssize_t req_len, len;
123✔
785
    int ret;
123✔
786
    uint64_t activated_mask = 0;
123✔
787

788
    for (idx = 0; pcr_banks[idx] != NULL; idx++)
252✔
789
        ;
790
    *active = g_malloc0(sizeof(char *) * (idx + 1));
123✔
791

792
    for (idx = 0; pcr_banks[idx] != NULL; idx++) {
252✔
793
        hashAlg = 0;
242✔
794
        // Is user-chosen pcr_banks[idx] available?
795
        for (j = 0; all_pcr_banks[j] != NULL; j++) {
242✔
796
            if (strcmp(pcr_banks[idx], all_pcr_banks[j]) == 0) {
241✔
797
                hashAlg = get_hashalg_by_bankname(pcr_banks[idx]);
128✔
798
                break;
128✔
799
            }
800
        }
801
        if (hashAlg != 0 && (activated_mask & ((uint64_t)1 << j)) == 0) {
129✔
802
            (*active)[count] = g_strdup(pcr_banks[idx]);
128✔
803
            len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
256✔
804
                         (unsigned char[]){AS2BE(hashAlg), 3, 0xff, 0xff, 0xff} , (size_t)6,
128✔
805
                         NULL);
806
            if (len < 0) {
128✔
UNCOV
807
                logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
UNCOV
808
                return 1;
×
809
            }
810
            pcrselects_len += len;
128✔
811
            count++;
128✔
812
            activated_mask |= ((uint64_t)1 << j);
128✔
813
        }
814
    }
815

816
    if (count == 0) {
123✔
817
        logerr(self->logfile,
1✔
818
               "No PCR banks could be allocated. None of the selected algorithms are supported.\n");
819
        goto error;
1✔
820
    }
821

822
    // disable all the other ones not chosen by the user
823
    for (idx = 0; all_pcr_banks[idx] != NULL; idx++) {
562✔
824
        gboolean found = FALSE;
768✔
825

826
        for (j = 0; pcr_banks[j] != NULL; j++) {
768✔
827
            if (strcmp(pcr_banks[j], all_pcr_banks[idx]) == 0) {
456✔
828
                found = TRUE;
829
                break;
830
            }
831
        }
832
        if (found)
440✔
833
            continue;
128✔
834

835
        /* not found, so not chosen by user */
836
        hashAlg = get_hashalg_by_bankname(all_pcr_banks[idx]);
312✔
837

838
        len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
624✔
839
                     (unsigned char[]){AS2BE(hashAlg), 3, 0, 0, 0}, (size_t)6,
312✔
840
                     NULL);
841
        if (len < 0) {
312✔
UNCOV
842
            logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
UNCOV
843
            goto error;
×
844
        }
845
        pcrselects_len += len;
312✔
846
        count++;
312✔
847
    }
848

849
    req_len = memconcat(&req,
244✔
850
                        &hdr, sizeof(hdr),
851
                        (unsigned char[]){
122✔
852
                             AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))
853
                        }, (size_t)8,
854
                        &authblock, sizeof(authblock),
855
                        (unsigned char[]){AS4BE(count)}, (size_t)4,
122✔
856
                        pcrselects, pcrselects_len,
857
                        NULL);
858
    if (req_len < 0) {
122✔
UNCOV
859
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
UNCOV
860
        goto error;
×
861
    }
862
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
122✔
863

864
    ret = transfer(self, req, req_len, "TPM2_PCR_Allocate", FALSE,
122✔
865
                   NULL, NULL, TPM2_DURATION_SHORT);
866
    if (ret != 0)
122✔
867
        goto error;
×
868

869
    return 0;
870

871
error:
1✔
872
    g_strfreev(*active);
1✔
873
    *active = NULL;
1✔
874

875
    return 1;
1✔
876
}
877

878
static int swtpm_tpm2_flushcontext(struct swtpm *self, uint32_t handle)
9✔
879
{
880
    struct tpm2_flushcontext_req {
9✔
881
        struct tpm_req_header hdr;
882
        uint32_t flushHandle;
883
    } __attribute__((packed)) req = {
9✔
884
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_FLUSHCONTEXT),
9✔
885
        .flushHandle = htobe32(handle),
9✔
886
    };
887

888
    return transfer(self, &req, sizeof(req), "TPM2_FlushContext", FALSE,
9✔
889
                    NULL, NULL, TPM2_DURATION_SHORT);
890
}
891

892
/* Make object at the curr_handler permanent with the perm_handle */
893
static int swtpm_tpm2_evictcontrol(struct swtpm *self, uint32_t curr_handle, uint32_t perm_handle)
110✔
894
{
895
    struct tpm2_evictcontrol_req {
110✔
896
        struct tpm_req_header hdr;
897
        uint32_t auth;
898
        uint32_t objectHandle;
899
        uint32_t authblockLen;
900
        struct tpm2_authblock authblock;
901
        uint32_t persistentHandle;
902
    } __attribute__((packed)) req = {
110✔
903
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, sizeof(req), TPM2_CC_EVICTCONTROL),
110✔
904
        .auth = htobe32(TPM2_RH_OWNER),
110✔
905
        .objectHandle = htobe32(curr_handle),
110✔
906
        .authblockLen = htobe32(sizeof(req.authblock)),
110✔
907
        .authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW),
110✔
908
        .persistentHandle = htobe32(perm_handle),
110✔
909
    };
910

911
    return transfer(self, &req, sizeof(req), "TPM2_EvictControl", FALSE,
110✔
912
                    NULL, NULL, TPM2_DURATION_SHORT);
913
}
914

915
static size_t create_symkeydata(const struct pk_params *pk_params,
110✔
916
                                unsigned char symkeydata[6])
917
{
918
    size_t symkeydata_len;
110✔
919

920
    if (pk_params->symkey_len) {
110✔
921
        symkeydata_len = 6;
62✔
922
        memcpy(symkeydata,
62✔
923
               ((unsigned char[]){
62✔
924
                   AS2BE(TPM2_ALG_AES),
925
                   AS2BE(pk_params->symkey_len),
62✔
926
                   AS2BE(TPM2_ALG_CFB)
927
               }),
928
               symkeydata_len);
929
    } else {
930
        symkeydata_len = 2;
48✔
931
        memcpy(symkeydata,
48✔
932
               ((unsigned char[]){AS2BE(TPM2_ALG_NULL)}),
48✔
933
               symkeydata_len);
934
    }
935
    return symkeydata_len;
110✔
936
}
937

938
/* Common function to create a TPM 2 primary key.
939
 *
940
 * Returns 1 on error with errors having been reported.
941
 * If tpmresp is != 0 on return then a TPM2 response was received.
942
 */
943
static int swtpm_tpm2_createprimary(struct swtpm *self, uint32_t primaryhandle,
110✔
944
                                    unsigned char *ektemplate, size_t *ektemplate_len,
945
                                    const unsigned char *public, size_t public_len,
946
                                    const char *tpm2_function, int duration,
947
                                    unsigned char *tpmresp, size_t *tpmresp_len,
948
                                    uint32_t *curr_handle)
949
{
950
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY);
110✔
951
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
110✔
952
    g_autofree unsigned char *createprimary = NULL;
220✔
953
    ssize_t createprimary_len;
110✔
954
    int ret;
110✔
955

956
    if (ektemplate) {
110✔
957
        if (*ektemplate_len < (size_t)public_len) {
101✔
NEW
958
            logerr(self->logfile, "Internal error in %s: Need %zu bytes for ektemplate (rsa) but got only %zu\n",
×
959
                   __func__, public_len, *ektemplate_len);
NEW
960
            *tpmresp_len = 0;
×
NEW
961
            return 1;
×
962
        }
963
        memcpy(ektemplate, public, public_len);
101✔
964
        *ektemplate_len = public_len;
101✔
965
    }
966

967
    createprimary_len =
110✔
968
        memconcat(&createprimary,
220✔
969
                  &hdr, sizeof(hdr),
970
                  (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8,
110✔
971
                  &authblock, sizeof(authblock),
972
                  (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8,
110✔
973
                  public, public_len,
974
                  (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
110✔
975
                  NULL);
976
    if (createprimary_len < 0) {
110✔
NEW
977
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
NEW
978
        *tpmresp_len = 0;
×
NEW
979
        return 1;
×
980
    }
981
    ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len);
110✔
982

983
    ret = transfer(self, createprimary, createprimary_len, tpm2_function, FALSE,
110✔
984
                   tpmresp, tpmresp_len, duration);
985
    if (ret != 0)
110✔
986
        return 1;
987

988
    if (curr_handle) {
110✔
989
        if (*tpmresp_len < 10 + sizeof(*curr_handle))
110✔
NEW
990
            goto err_too_short;
×
991
        memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle));
110✔
992
        *curr_handle = be32toh(*curr_handle);
110✔
993
    }
994
    return 0;
995

NEW
996
err_too_short:
×
NEW
997
    logerr(self->logfile, "Response from %s is too short!\n", tpm2_function);
×
NEW
998
    return 1;
×
999
}
1000

1001
/* Create an RSA EK */
1002
static int swtpm_tpm2_createprimary_ek_rsa(struct swtpm *self, unsigned int rsa_keysize,
53✔
1003
                                           gboolean allowsigning, gboolean decryption,
1004
                                           uint32_t *curr_handle,
1005
                                           unsigned char *ektemplate, size_t *ektemplate_len,
1006
                                           gchar **ekparam, const gchar **key_description)
1007
{
1008
    const struct ek_params *ekps;
53✔
1009
    struct pk_params pkps;
53✔
1010
    unsigned int keyflags;
53✔
1011
    size_t addlen, off;
53✔
1012

1013
    ekps = get_ek_params(self, KEYALGO_RSA, rsa_keysize);
53✔
1014
    if (!ekps)
53✔
1015
        return 1;
1016
    pkps = ekps->pk;
53✔
1017

1018
    switch (rsa_keysize) {
53✔
1019
    case 2048:
1020
        keyflags = 0;
1021
        addlen = 0;
1022
        break;
1023
    case 3072:
22✔
1024
    case 4096:
1025
        keyflags = 0x40; // userWithAuth
22✔
1026
        addlen = 16;
22✔
1027
        break;
22✔
1028
    default:
1029
        return 1;
1030
    }
1031

1032
    if (allowsigning && decryption) {
53✔
1033
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1034
        // adminWithPolicy, sign, decrypt; restricted CANNOT be set
1035
        keyflags |= 0x000600b2;
7✔
1036
        // symmetric: TPM_ALG_NULL
1037
        pkps.symkey_len = 0;
7✔
1038
        off = 72 + addlen;
7✔
1039
    } else if (allowsigning) {
46✔
1040
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1041
        // adminWithPolicy, sign; restricted CANNOT be set
1042
        keyflags |= 0x000400b2;
17✔
1043
        // symmetric: TPM_ALG_NULL
1044
        pkps.symkey_len = 0;
17✔
1045
        off = 72 + addlen;
17✔
1046
    } else {
1047
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1048
        // adminWithPolicy, restricted, decrypt
1049
        keyflags |= 0x000300b2;
29✔
1050
        // symmetric: TPM_ALG_AES, 128bit or 256bit, TPM_ALG_CFB
1051
        off = 76 + addlen;
29✔
1052
    }
1053

1054
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_ENDORSEMENT, keyflags,
53✔
1055
                                        &pkps, off, curr_handle,
1056
                                        ektemplate, ektemplate_len, ekparam,
1057
                                        key_description);
1058
}
1059

1060
/* Create an RSA key with the given parameters */
1061
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
60✔
1062
                                        const struct pk_params *pk_params,
1063
                                        size_t off, uint32_t *curr_handle,
1064
                                        unsigned char *ektemplate, size_t *ektemplate_len,
1065
                                        gchar **ekparam, const gchar **key_description)
1066
{
1067
    const char *tpm2_function = "TPM2_CreatePrimary(RSA)";
60✔
1068
    g_autofree unsigned char *public = NULL;
120✔
1069
    unsigned char tpmresp[2048];
60✔
1070
    unsigned char symkeydata[6];
60✔
1071
    size_t tpmresp_len = sizeof(tpmresp);
60✔
1072
    size_t symkeydata_len;
60✔
1073
    ssize_t public_len;
60✔
1074
    uint16_t modlen;
60✔
1075
    int ret;
60✔
1076

1077
    if (key_description)
60✔
1078
        *key_description = pk_params->keydescription;
53✔
1079

1080
    symkeydata_len = create_symkeydata(pk_params, symkeydata);
60✔
1081

1082
    public_len =
60✔
1083
        memconcat(&public,
120✔
1084
                  (unsigned char[]) {
60✔
1085
                      AS2BE(TPM2_ALG_RSA), AS2BE(pk_params->hashalg),
60✔
1086
                      AS4BE(keyflags), AS2BE(pk_params->authpolicy_len)
60✔
1087
                  }, (size_t)10,
1088
                  pk_params->authpolicy, pk_params->authpolicy_len,
60✔
1089
                  symkeydata, symkeydata_len,
1090
                  (unsigned char[]) {
60✔
1091
                      AS2BE(TPM2_ALG_NULL), AS2BE(pk_params->keysize * 8), AS4BE(0)
60✔
1092
                  }, (size_t)8,
1093
                  pk_params->nonce, pk_params->nonce_len,
60✔
1094
                  NULL);
1095
    if (public_len < 0) {
60✔
UNCOV
1096
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
UNCOV
1097
        return 1;
×
1098
    }
1099
    ret = swtpm_tpm2_createprimary(self, primaryhandle,
120✔
1100
                                   ektemplate, ektemplate_len,
1101
                                   public, public_len,
1102
                                   tpm2_function, pk_params->duration,
60✔
1103
                                   tpmresp, &tpmresp_len, curr_handle);
1104
    if (ret != 0) {
60✔
UNCOV
1105
        if (tpmresp_len >= sizeof(struct tpm_resp_header) &&
×
UNCOV
1106
            be32toh(((struct tpm_resp_header *)tpmresp)->errcode) == 0x2c4) {
×
1107
            /*
1108
             * Error may appear when key size is not supported by profile:
1109
             * value is out of range or is not correct for the context Parameter number 2
1110
             */
UNCOV
1111
            logerr(self->logfile,
×
1112
                   ">> Is RSA-%u supported by the profile? RSA-%u needs 'default-v2'.<<\n",
1113
                   pk_params->keysize * 8,
NEW
1114
                   pk_params->keysize * 8);
×
1115
        }
UNCOV
1116
        return 1;
×
1117
    }
1118

1119
    if (tpmresp_len < off + sizeof(modlen))
60✔
UNCOV
1120
         goto err_too_short;
×
1121
    memcpy(&modlen, &tpmresp[off], sizeof(modlen));
60✔
1122
    modlen = be16toh(modlen);
60✔
1123
    if (modlen != pk_params->keysize) {
60✔
UNCOV
1124
        logerr(self->logfile, "Internal error in %s: Getting modulus from wrong offset %zu\n",
×
1125
               __func__, off);
UNCOV
1126
        return 1;
×
1127
    }
1128
    if (ekparam) {
60✔
1129
        if (tpmresp_len < off + 2 + modlen)
53✔
UNCOV
1130
            goto err_too_short;
×
1131
        *ekparam = print_as_hex(&tpmresp[off + 2], modlen);
53✔
1132
    }
1133

1134
    return 0;
1135

UNCOV
1136
err_too_short:
×
NEW
1137
    logerr(self->logfile, "Response from %s is too short!\n", tpm2_function);
×
UNCOV
1138
    return 1;
×
1139
}
1140

1141
/* Create an ECC key with the given parameters */
1142
static int swtpm_tpm2_createprimary_ecc(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
50✔
1143
                                        const unsigned char *schemedata, size_t schemedata_len,
1144
                                        const struct pk_params *pk_params,
1145
                                        size_t off, uint32_t *curr_handle,
1146
                                        unsigned char *ektemplate, size_t *ektemplate_len,
1147
                                        gchar **ekparam, const gchar **key_description)
1148
{
1149
    const char *tpm2_function = "TPM2_CreatePrimary(ECC)";
50✔
1150
    g_autofree unsigned char *public = NULL;
100✔
1151
    unsigned char tpmresp[2048];
50✔
1152
    size_t tpmresp_len = sizeof(tpmresp);
50✔
1153
    unsigned char symkeydata[6];
50✔
1154
    uint16_t ksize1, ksize2;
50✔
1155
    size_t symkeydata_len;
50✔
1156
    ssize_t public_len;
50✔
1157
    size_t off2;
50✔
1158
    int ret;
50✔
1159

1160
    if (key_description)
50✔
1161
        *key_description = pk_params->keydescription;
48✔
1162

1163
    symkeydata_len = create_symkeydata(pk_params, symkeydata);
50✔
1164

1165
    public_len =
50✔
1166
        memconcat(&public,
100✔
1167
                  (unsigned char[]){
50✔
1168
                      AS2BE(TPM2_ALG_ECC),
1169
                      AS2BE(pk_params->hashalg),
50✔
1170
                      AS4BE(keyflags),
50✔
1171
                      AS2BE(pk_params->authpolicy_len)
50✔
1172
                  }, (size_t)10,
1173
                  pk_params->authpolicy, pk_params->authpolicy_len,
50✔
1174
                  symkeydata, symkeydata_len,
1175
                  schemedata, schemedata_len,
1176
                  pk_params->nonce, pk_params->nonce_len,
1177
                  pk_params->nonce, pk_params->nonce_len,
50✔
1178
                  NULL);
1179
    if (public_len < 0) {
50✔
UNCOV
1180
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
UNCOV
1181
        return 1;
×
1182
    }
1183
    ret = swtpm_tpm2_createprimary(self, primaryhandle,
100✔
1184
                                   ektemplate, ektemplate_len,
1185
                                   public, public_len,
1186
                                   tpm2_function, pk_params->duration,
50✔
1187
                                   tpmresp, &tpmresp_len, curr_handle);
1188
    if (ret != 0)
50✔
1189
        return 1;
1190

1191
    if (tpmresp_len < off + sizeof(ksize1))
50✔
UNCOV
1192
        goto err_too_short;
×
1193
    memcpy(&ksize1, &tpmresp[off], sizeof(ksize1));
50✔
1194
    ksize1 = be16toh(ksize1);
50✔
1195
    off2 = off + 2 + ksize1;
50✔
1196

1197
    if (tpmresp_len < off2 + sizeof(ksize2))
50✔
UNCOV
1198
        goto err_too_short;
×
1199
    memcpy(&ksize2, &tpmresp[off2], sizeof(ksize2));
50✔
1200
    ksize2 = be16toh(ksize2);
50✔
1201

1202
    if (ksize1 != pk_params->keysize || ksize2 != pk_params->keysize) {
50✔
1203
        logerr(self->logfile, "ECC: Getting key parameters from wrong offset\n");
×
UNCOV
1204
        return 1;
×
1205
    }
1206

1207
    if (ekparam) {
50✔
1208
        unsigned char *xparam = &tpmresp[off + 2];
48✔
1209
        unsigned char *yparam = &tpmresp[off2 + 2];
48✔
1210
        if (tpmresp_len < off + 2 + ksize1 || tpmresp_len < off2 + 2 + ksize2)
48✔
UNCOV
1211
            goto err_too_short;
×
1212
        g_autofree gchar *xparam_str = print_as_hex(xparam, ksize1);
96✔
1213
        g_autofree gchar *yparam_str = print_as_hex(yparam, ksize2);
96✔
1214

1215
        *ekparam = g_strdup_printf("x=%s,y=%s,id=%s", xparam_str, yparam_str,
48✔
1216
                                   pk_params->keydescription);
48✔
1217
    }
1218

1219
    return 0;
1220

UNCOV
1221
err_too_short:
×
NEW
1222
    logerr(self->logfile, "Response from %s is too short!\n", tpm2_function);
×
UNCOV
1223
    return 1;
×
1224
}
1225

1226
static int swtpm_tpm2_createprimary_spk_ecc_nist_p384(struct swtpm *self,
2✔
1227
                                                      uint32_t *curr_handle)
1228
{
1229
    // keyflags: fixedTPM, fixedParent, sensitiveDataOrigin, userWithAuth
1230
    //           noDA, restricted, decrypt
1231
    unsigned int keyflags = 0x00030472;
2✔
1232
    const unsigned char authpolicy[0] = { };
2✔
1233
    size_t authpolicy_len = sizeof(authpolicy);
2✔
1234
    const unsigned char schemedata[] = {
2✔
1235
        AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P384), AS2BE(TPM2_ALG_NULL)
1236
    };
1237
    struct pk_params pk_params = {
2✔
1238
        .authpolicy = authpolicy,
1239
        .authpolicy_len = authpolicy_len,
1240
        .nonce = NONCE_ECC_384,
1241
        .nonce_len = sizeof(NONCE_ECC_384),
1242
        .hashalg = TPM2_ALG_SHA384,
1243
        .keysize = 48,
1244
        .symkey_len = 256,
1245
        .duration = TPM2_DURATION_LONG,
1246
    };
1247
    size_t schemedata_len = sizeof(schemedata);
2✔
1248
    size_t off = 42;
2✔
1249

1250
    /* per "TCG TPM v2.0 Provisioning Guidance v1.0" page 37
1251
     * -> "Ek Credential Profile 2.0" rev.14 section 2.1.5.2:
1252
     * template for NIST P256 uses 2 identical 32-byte all-zero nonces
1253
     * -> Use two 48-byte all-zero nonces for NIST P384.
1254
     */
1255

1256
    return swtpm_tpm2_createprimary_ecc(self, TPM2_RH_OWNER, keyflags,
2✔
1257
                                        schemedata, schemedata_len,
1258
                                        &pk_params, off, curr_handle,
1259
                                        NULL, 0, NULL, NULL);
1260
}
1261

1262
static int swtpm_tpm2_createprimary_spk_rsa(struct swtpm *self, unsigned int rsa_keysize,
7✔
1263
                                            uint32_t *curr_handle)
1264
{
1265
    // keyflags: fixedTPM, fixedParent, sensitiveDataOrigin, userWithAuth
1266
    //           noDA, restricted, decrypt
1267
    unsigned int keyflags = 0x00030472;
7✔
1268
    const unsigned char authpolicy[0] = { };
7✔
1269
    size_t authpolicy_len = sizeof(authpolicy);
7✔
1270
    struct pk_params pk_params = {
7✔
1271
        .authpolicy = authpolicy,
1272
        .authpolicy_len = authpolicy_len,
1273
        .keysize = rsa_keysize / 8,
7✔
1274
        .duration = TPM2_DURATION_LONG,
1275
    };
1276
    size_t off = 44;
7✔
1277

1278
    switch (rsa_keysize) {
7✔
NEW
1279
    case 2048:
×
NEW
1280
        pk_params.nonce = NONCE_RSA2048;
×
NEW
1281
        pk_params.nonce_len = sizeof(NONCE_RSA2048);
×
NEW
1282
        pk_params.hashalg = TPM2_ALG_SHA256;
×
NEW
1283
        pk_params.symkey_len = 128;
×
NEW
1284
        break;
×
1285
    case 3072:
7✔
1286
        pk_params.nonce = NONCE_RSA3072;
7✔
1287
        pk_params.nonce_len = sizeof(NONCE_RSA3072);
7✔
1288
        pk_params.hashalg = TPM2_ALG_SHA384;
7✔
1289
        pk_params.symkey_len = 256;
7✔
1290
        break;
7✔
NEW
1291
    case 4096:
×
NEW
1292
        pk_params.nonce = NONCE_RSA4096;
×
NEW
1293
        pk_params.nonce_len = sizeof(NONCE_RSA4096);
×
NEW
1294
        pk_params.hashalg = TPM2_ALG_SHA384;
×
NEW
1295
        pk_params.symkey_len = 256;
×
NEW
1296
        break;
×
1297
    default:
1298
        return 1;
1299
    }
1300

1301
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_OWNER, keyflags,
7✔
1302
                                        &pk_params, off, curr_handle,
1303
                                        NULL, 0, NULL, NULL);
1304
}
1305

1306
/* Create either an ECC or RSA storage primary key (deprecated) */
1307
static int swtpm_tpm2_create_spk(struct swtpm *self, enum keyalgo keyalgo,
9✔
1308
                                 unsigned int keyalgo_param)
1309
{
1310
    int ret;
9✔
1311
    uint32_t curr_handle;
9✔
1312

1313
    switch (keyalgo) {
9✔
1314
    case KEYALGO_ECC:
2✔
1315
        ret = swtpm_tpm2_createprimary_spk_ecc_nist_p384(self, &curr_handle);
2✔
1316
        break;
2✔
1317
    case KEYALGO_RSA:
7✔
1318
        ret = swtpm_tpm2_createprimary_spk_rsa(self, keyalgo_param, &curr_handle);
7✔
1319
        break;
7✔
1320
    default:
1321
        ret = 1;
1322
    }
1323

1324
    if (ret != 0)
9✔
UNCOV
1325
        return 1;
×
1326

1327
    ret = swtpm_tpm2_evictcontrol(self, curr_handle, TPM2_SPK_HANDLE);
9✔
1328
    if (ret == 0)
9✔
1329
        logit(self->logfile,
9✔
1330
              "Successfully created storage primary key with handle 0x%x.\n", TPM2_SPK_HANDLE);
1331

1332
    ret = swtpm_tpm2_flushcontext(self, curr_handle);
9✔
1333
    if (ret != 0) {
9✔
UNCOV
1334
        logerr(self->logfile, "Could not flush storage primary key.\n");
×
UNCOV
1335
        ret = 1;
×
1336
    }
1337

1338
    return ret;
1339
}
1340

1341
/* Create an ECC EK key that may be allowed to sign and/or decrypt */
1342
static int swtpm_tpm2_createprimary_ek_ecc_nist_p384(struct swtpm *self, gboolean allowsigning,
48✔
1343
                                                     gboolean decryption, uint32_t *curr_handle,
1344
                                                     unsigned char *ektemplate, size_t *ektemplate_len,
1345
                                                     gchar **ekparam, const char **key_description)
1346
{
1347
    const unsigned char schemedata[] = {
48✔
1348
        AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P384), AS2BE(TPM2_ALG_NULL)
1349
    };
1350
    size_t schemedata_len = sizeof(schemedata);
48✔
1351
    const struct ek_params *ekps;
48✔
1352
    struct pk_params pkps;
48✔
1353
    unsigned int keyflags;
48✔
1354
    size_t off;
48✔
1355
    int ret;
48✔
1356

1357
    ekps = get_ek_params(self, KEYALGO_ECC, TPM2_ECC_NIST_P384);
48✔
1358
    if (!ekps)
48✔
1359
        return 1;
1360
    pkps = ekps->pk;
48✔
1361

1362
    if (allowsigning && decryption) {
48✔
1363
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1364
        // userWithAuth, adminWithPolicy, sign, decrypt; restricted CANNOT be set
1365
        keyflags = 0x000600f2;
7✔
1366
        // symmetric: TPM_ALG_NULL
1367
        pkps.symkey_len = 0;
7✔
1368
        off = 86;
7✔
1369
    } else if (allowsigning) {
41✔
1370
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1371
        // userWithAuth, adminWithPolicy, sign; restricted CANNOT be set
1372
        keyflags = 0x000400f2;
17✔
1373
        // symmetric: TPM_ALG_NULL
1374
        pkps.symkey_len = 0;
17✔
1375
        off = 86;
17✔
1376
    } else {
1377
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1378
        // userWithAuth, adminWithPolicy, restricted, decrypt
1379
        keyflags = 0x000300f2;
1380
        // symmetric: TPM_ALG_AES, 256bit, TPM_ALG_CFB
1381
        off = 90;
1382
    }
1383

1384
    ret = swtpm_tpm2_createprimary_ecc(self, TPM2_RH_ENDORSEMENT, keyflags,
48✔
1385
                                       schemedata, schemedata_len,
1386
                                       &pkps, off, curr_handle,
1387
                                       ektemplate, ektemplate_len, ekparam,
1388
                                       key_description);
1389
    if (ret != 0)
48✔
1390
       logerr(self->logfile, "%s failed\n", __func__);
×
1391

1392
    return ret;
1393
}
1394

1395
/* Create an ECC or RSA EK */
1396
static int swtpm_tpm2_create_ek(struct swtpm *self, enum keyalgo keyalgo, unsigned int keyalgo_param,
101✔
1397
                                gboolean allowsigning, gboolean decryption, gboolean lock_nvram,
1398
                                gchar **ekparam, const  gchar **key_description)
1399
{
1400
    unsigned char ektemplate[512];
101✔
1401
    size_t ektemplate_len = sizeof(ektemplate);
101✔
1402
    const struct ek_params *ekps;
101✔
1403
    uint32_t curr_handle;
101✔
1404
    int ret;
101✔
1405

1406
    ekps = get_ek_params(self, keyalgo, keyalgo_param);
101✔
1407
    if (!ekps)
101✔
1408
        return 1;
1409

1410
    switch (keyalgo) {
101✔
1411
    case KEYALGO_ECC:
48✔
1412
        ret = swtpm_tpm2_createprimary_ek_ecc_nist_p384(self, allowsigning, decryption, &curr_handle,
48✔
1413
                                                        ektemplate, &ektemplate_len, ekparam,
1414
                                                        key_description);
1415
        break;
48✔
1416
    case KEYALGO_RSA:
53✔
1417
        ret = swtpm_tpm2_createprimary_ek_rsa(self, keyalgo_param, allowsigning,
53✔
1418
                                              decryption, &curr_handle,
1419
                                              ektemplate, &ektemplate_len, ekparam,
1420
                                              key_description);
1421
        break;
53✔
1422
    default:
1423
        ret = 1;
1424
    }
1425

1426
    if (ret == 0)
101✔
1427
        ret = swtpm_tpm2_evictcontrol(self, curr_handle, ekps->ek_handle);
101✔
1428
    if (ret != 0) {
101✔
UNCOV
1429
        logerr(self->logfile, "create_ek failed: 0x%x\n", ret);
×
UNCOV
1430
        return 1;
×
1431
    }
1432

1433
    logit(self->logfile, "Successfully created %s EK with handle 0x%x.\n",
101✔
1434
          ekps->keytype, ekps->ek_handle);
101✔
1435

1436
    if (allowsigning) {
101✔
1437
        uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE | \
48✔
1438
                TPMA_NV_AUTHREAD | \
1439
                TPMA_NV_OWNERREAD | \
1440
                TPMA_NV_PPREAD | \
1441
                TPMA_NV_PPWRITE | \
1442
                TPMA_NV_NO_DA | \
1443
                TPMA_NV_WRITEDEFINE;
1444
        ret = swtpm_tpm2_write_nvram(self, ekps->nvindex_template, nvindexattrs,
48✔
1445
                                     ektemplate, ektemplate_len,
1446
                                     lock_nvram, "EK template");
1447
        if (ret == 0)
48✔
1448
            logit(self->logfile,
48✔
1449
                  "Successfully created NVRAM area 0x%x for %s EK template.\n",
1450
                  ekps->nvindex_template, ekps->keytype);
48✔
1451
    }
1452

1453
    return ret;
1454
}
1455

1456
static int swtpm_tpm2_nvdefinespace(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
179✔
1457
                                    uint16_t data_len)
1458
{
1459
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_DEFINESPACE);
179✔
1460
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
179✔
1461
    g_autofree unsigned char *nvpublic = NULL;
358✔
1462
    ssize_t nvpublic_len;
179✔
1463
    g_autofree unsigned char *req = NULL;
179✔
1464
    ssize_t req_len;
179✔
1465

1466
    nvpublic_len = memconcat(&nvpublic,
358✔
1467
                             (unsigned char[]){
179✔
1468
                                 AS4BE(nvindex), AS2BE(TPM2_ALG_SHA256), AS4BE(nvindexattrs),
179✔
1469
                                 AS2BE(0), AS2BE(data_len)}, (size_t)14,
1470
                             NULL);
1471
    if (nvpublic_len < 0) {
179✔
UNCOV
1472
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
UNCOV
1473
        return 1;
×
1474
    }
1475

1476
    req_len = memconcat(&req,
358✔
1477
                        &hdr, sizeof(hdr),
1478
                        (unsigned char[]){AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))}, (size_t)8,
179✔
1479
                        &authblock, sizeof(authblock),
1480
                        (unsigned char[]){AS2BE(0), AS2BE(nvpublic_len)}, (size_t)4,
179✔
1481
                        nvpublic, nvpublic_len,
1482
                        NULL);
1483
    if (req_len < 0) {
179✔
UNCOV
1484
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
UNCOV
1485
        return 1;
×
1486
    }
1487

1488
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
179✔
1489

1490
    return transfer(self, req, req_len, "TPM2_NV_DefineSpace", FALSE,
179✔
1491
                    NULL, NULL, TPM2_DURATION_SHORT);
1492
}
1493

1494
/* Write the data into the given NVIndex */
1495
static int swtpm_tpm2_nv_write(struct swtpm *self, uint32_t nvindex,
179✔
1496
                               const unsigned char *data, size_t data_len)
1497
{
1498
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITE);
179✔
1499
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
179✔
1500
    g_autofree unsigned char *req = NULL;
358✔
1501
    ssize_t req_len;
179✔
1502
    size_t offset = 0, txlen;
179✔
1503
    int ret;
179✔
1504

1505
    while (offset < data_len) {
362✔
1506
        txlen = min(data_len - offset, 1024);
183✔
1507

1508
        g_free(req);
183✔
1509
        req_len = memconcat(&req,
366✔
1510
                            &hdr, sizeof(hdr),
1511
                            (unsigned char[]){
183✔
1512
                                AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
183✔
1513
                            }, (size_t)12,
1514
                            &authblock, sizeof(authblock),
1515
                            (unsigned char[]){AS2BE(txlen)}, (size_t)2,
183✔
1516
                            &data[offset], txlen,
1517
                            (unsigned char[]){AS2BE(offset)}, (size_t)2,
183✔
1518
                            NULL);
1519
        if (req_len < 0) {
183✔
UNCOV
1520
            logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
UNCOV
1521
            return 1;
×
1522
        }
1523
        ((struct tpm_req_header *)req)->size = htobe32(req_len);
183✔
1524

1525
        ret = transfer(self, req, req_len, "TPM2_NV_Write", FALSE,
183✔
1526
                       NULL, NULL, TPM2_DURATION_SHORT);
1527
        if (ret != 0)
183✔
1528
            return 1;
1529

1530
        offset += txlen;
183✔
1531
    }
1532
    return 0;
1533
}
1534

1535
static int swtpm_tpm2_nv_writelock(struct swtpm *self, uint32_t nvindex)
12✔
1536
{
1537
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITELOCK);
12✔
1538
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
12✔
1539
    g_autofree unsigned char *req;
24✔
1540
    ssize_t req_len;
12✔
1541

1542
    req_len = memconcat(&req,
24✔
1543
                        &hdr, sizeof(hdr),
1544
                        (unsigned char[]){
12✔
1545
                           AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
12✔
1546
                        }, (size_t)12,
1547
                        &authblock, sizeof(authblock),
1548
                        NULL);
1549
    if (req_len < 0) {
12✔
UNCOV
1550
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
UNCOV
1551
        return 1;
×
1552
    }
1553

1554
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
12✔
1555

1556
    return transfer(self, req, req_len, "TPM2_NV_WriteLock", FALSE,
12✔
1557
                    NULL, NULL, TPM2_DURATION_SHORT);
1558
}
1559

1560
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
179✔
1561
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
1562
                                  const char *certtype)
1563
{
1564
    int ret = swtpm_tpm2_nvdefinespace(self, nvindex, nvindexattrs, data_len);
179✔
1565
    if (ret != 0) {
179✔
UNCOV
1566
        logerr(self->logfile, "Could not create NVRAM area 0x%x for %s.\n", nvindex, certtype);
×
UNCOV
1567
        return 1;
×
1568
    }
1569

1570
    ret = swtpm_tpm2_nv_write(self, nvindex, data, data_len);
179✔
1571
    if (ret != 0) {
179✔
1572
        logerr(self->logfile,
×
1573
               "Could not write %s into NVRAM area 0x%x.\n", certtype, nvindex);
UNCOV
1574
        return 1;
×
1575
    }
1576

1577
    if (lock_nvram) {
179✔
1578
        ret = swtpm_tpm2_nv_writelock(self, nvindex);
12✔
1579
        if (ret != 0) {
12✔
UNCOV
1580
            logerr(self->logfile, "Could not lock EK template NVRAM area 0x%x.\n", nvindex);
×
UNCOV
1581
            return 1;
×
1582
        }
1583
    }
1584

1585
    return 0;
1586
}
1587

1588
static int swtpm_tpm2_write_cert_nvram(struct swtpm *self, uint32_t nvindex,
131✔
1589
                                       uint32_t nvindexattrs,
1590
                                       const unsigned char *data, size_t data_len,
1591
                                       gboolean lock_nvram, const char *keytype,
1592
                                       const char *certtype)
1593
{
1594
    int ret;
131✔
1595

1596
    ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, data, data_len, lock_nvram,
131✔
1597
                                 certtype);
1598
    if (ret == 0)
131✔
1599
        logit(self->logfile,
131✔
1600
              "Successfully created NVRAM area 0x%x for %s%s.\n",
1601
              nvindex, keytype, certtype);
1602

1603
    return ret;
131✔
1604
}
1605

1606
/* Write the platform certificate into an NVRAM area */
1607
static int swtpm_tpm2_write_ek_cert_nvram(struct swtpm *self, enum keyalgo keyalgo,
87✔
1608
                                           unsigned int keyalgo_param, gboolean lock_nvram,
1609
                                           const unsigned char *data, size_t data_len)
1610
{
1611
    g_autofree gchar *keytype = NULL;
174✔
1612
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
87✔
1613
            TPMA_NV_AUTHREAD |
1614
            TPMA_NV_OWNERREAD |
1615
            TPMA_NV_PPREAD |
1616
            TPMA_NV_PPWRITE |
1617
            TPMA_NV_NO_DA |
1618
            TPMA_NV_WRITEDEFINE;
1619
    const struct ek_params *ekps;
87✔
1620

1621
    ekps = get_ek_params(self, keyalgo, keyalgo_param);
87✔
1622
    if (!ekps)
87✔
1623
        return 1;
1624

1625
    keytype = g_strdup_printf("%s ", ekps->keytype);
87✔
1626

1627
    return swtpm_tpm2_write_cert_nvram(self, ekps->nvindex_ekcert,
87✔
1628
                                       nvindexattrs, data, data_len,
1629
                                       lock_nvram, keytype, "EK certificate");
1630
}
1631

1632
static int swtpm_tpm2_write_platform_cert_nvram(struct swtpm *self, gboolean lock_nvram,
44✔
1633
                                                const unsigned char *data, size_t data_len)
1634
{
1635
    uint32_t nvindex = TPM2_NV_INDEX_PLATFORMCERT;
44✔
1636
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
44✔
1637
            TPMA_NV_AUTHREAD |
1638
            TPMA_NV_OWNERREAD |
1639
            TPMA_NV_PPREAD |
1640
            TPMA_NV_PPWRITE |
1641
            TPMA_NV_NO_DA |
1642
            TPMA_NV_WRITEDEFINE;
1643

1644
    return swtpm_tpm2_write_cert_nvram(self, nvindex, nvindexattrs, data, data_len,
44✔
1645
                                       lock_nvram, "", "platform certificate");
1646
}
1647

1648
static char *swtpm_tpm2_get_active_profile(struct swtpm *self)
123✔
1649
{
1650
    gchar *result = NULL;
123✔
1651

1652
    if (do_cmd_get_info(self, SWTPM_INFO_ACTIVE_PROFILE, &result))
123✔
1653
        return NULL;
1654
    return result;
117✔
1655
}
1656

1657
static const struct swtpm2_ops swtpm_tpm2_ops = {
1658
    .shutdown = swtpm_tpm2_shutdown,
1659
    .create_spk = swtpm_tpm2_create_spk,
1660
    .create_ek = swtpm_tpm2_create_ek,
1661
    .get_all_pcr_banks = swtpm_tpm2_get_all_pcr_banks,
1662
    .set_active_pcr_banks = swtpm_tpm2_set_active_pcr_banks,
1663
    .write_ek_cert_nvram = swtpm_tpm2_write_ek_cert_nvram,
1664
    .write_platform_cert_nvram = swtpm_tpm2_write_platform_cert_nvram,
1665
    .get_active_profile = swtpm_tpm2_get_active_profile,
1666
};
1667

1668
/*
1669
 * TPM 1.2 support
1670
 */
1671
#define TPM_TAG_RQU_COMMAND       0x00c1
1672
#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
1673

1674
#define TPM_ORD_OIAP                     0x0000000A
1675
#define TPM_ORD_TAKE_OWNERSHIP           0x0000000D
1676
#define TPM_ORD_PHYSICAL_ENABLE          0x0000006F
1677
#define TPM_ORD_PHYSICAL_SET_DEACTIVATED 0x00000072
1678
#define TPM_ORD_NV_DEFINE_SPACE          0x000000CC
1679
#define TPM_ORD_NV_WRITE_VALUE           0x000000CD
1680
#define TSC_ORD_PHYSICAL_PRESENCE        0x4000000A
1681

1682
#define TPM_ST_CLEAR 0x0001
1683

1684
#define TPM_PHYSICAL_PRESENCE_CMD_ENABLE  0x0020
1685
#define TPM_PHYSICAL_PRESENCE_PRESENT     0x0008
1686

1687
#define TPM_ALG_RSA 0x00000001
1688

1689
#define TPM_KEY_STORAGE 0x0011
1690

1691
#define TPM_AUTH_ALWAYS 0x01
1692

1693
#define TPM_PID_OWNER  0x0005
1694

1695
#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003
1696
#define TPM_SS_NONE 0x0001
1697

1698
#define TPM_TAG_PCR_INFO_LONG   0x0006
1699
#define TPM_TAG_NV_ATTRIBUTES   0x0017
1700
#define TPM_TAG_NV_DATA_PUBLIC  0x0018
1701
#define TPM_TAG_KEY12           0x0028
1702

1703
#define TPM_LOC_ZERO   0x01
1704
#define TPM_LOC_ALL    0x1f
1705

1706
#define TPM_NV_INDEX_D_BIT        0x10000000
1707
#define TPM_NV_INDEX_EKCERT       0xF000
1708
#define TPM_NV_INDEX_PLATFORMCERT 0xF002
1709

1710
#define TPM_NV_INDEX_LOCK 0xFFFFFFFF
1711

1712
#define TPM_NV_PER_OWNERREAD   0x00020000
1713
#define TPM_NV_PER_OWNERWRITE  0x00000002
1714

1715
#define TPM_ET_OWNER 0x02
1716
#define TPM_ET_NV    0x0b
1717

1718
#define TPM_KH_EK    0x40000006
1719

1720
#define TPM_DURATION_SHORT  ( 2000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
1721
#define TPM_DURATION_MEDIUM ( 7500 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
1722
#define TPM_DURATION_LONG   (15000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
1723

1724
static int swtpm_tpm12_tsc_physicalpresence(struct swtpm *self, uint16_t physicalpresence)
52✔
1725
{
1726
    struct tpm12_tsc_physicalpresence {
52✔
1727
        struct tpm_req_header hdr;
1728
        uint16_t pp;
1729
    } req = {
52✔
1730
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TSC_ORD_PHYSICAL_PRESENCE),
52✔
1731
        .pp = htobe16(physicalpresence),
52✔
1732
    };
1733

1734
    /* use medium duration to avoid t/o on busy system */
1735
    return transfer(self, &req, sizeof(req), "TSC_PhysicalPresence", FALSE,
52✔
1736
                    NULL, NULL, TPM_DURATION_MEDIUM);
1737
}
1738

1739
static int swtpm_tpm12_physical_enable(struct swtpm *self)
26✔
1740
{
1741
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_ENABLE);
26✔
1742

1743
    return transfer(self, &req, sizeof(req), "TPM_PhysicalEnable", FALSE,
26✔
1744
                    NULL, NULL, TPM_DURATION_SHORT);
1745
}
1746

1747
static int swtpm_tpm12_physical_set_deactivated(struct swtpm *self, uint8_t state)
26✔
1748
{
1749
    struct tpm12_tsc_physical_set_deactivated {
26✔
1750
        struct tpm_req_header hdr;
1751
        uint8_t state;
1752
    } req = {
26✔
1753
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_SET_DEACTIVATED),
26✔
1754
        .state = state,
1755
    };
1756

1757
    return transfer(self, &req, sizeof(req), "TSC_PhysicalSetDeactivated", FALSE,
26✔
1758
                    NULL, NULL, TPM_DURATION_SHORT);
1759
}
1760

1761
/* Initialize the TPM1.2 */
1762
static int swtpm_tpm12_run_swtpm_bios(struct swtpm *self)
26✔
1763
{
1764
    if (swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_CMD_ENABLE) ||
52✔
1765
        swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_PRESENT) ||
52✔
1766
        swtpm_tpm12_physical_enable(self) ||
52✔
1767
        swtpm_tpm12_physical_set_deactivated(self, 0))
26✔
UNCOV
1768
        return 1;
×
1769

1770
    return 0;
1771
}
1772

1773
static int swptm_tpm12_create_endorsement_keypair(struct swtpm *self,
19✔
1774
                                                  gchar **pubek, size_t *pubek_len)
1775
{
1776
    unsigned char req[] = {
19✔
1777
        0x00, 0xc1, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x78, 0x38, 0xf0, 0x30, 0x81, 0x07, 0x2b,
1778
        0x0c, 0xa9, 0x10, 0x98, 0x08, 0xc0, 0x4B, 0x05, 0x11, 0xc9, 0x50, 0x23, 0x52, 0xc4, 0x00, 0x00,
1779
        0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1780
        0x00, 0x02, 0x00, 0x00, 0x00, 0x00
1781
    };
1782
    unsigned char tpmresp[512];
19✔
1783
    size_t tpmresp_len = sizeof(tpmresp);
19✔
1784
    uint32_t length;
19✔
1785
    int ret;
19✔
1786

1787
    ret = transfer(self, &req, sizeof(req), "TPM_CreateEndorsementKeyPair", FALSE,
19✔
1788
                   &tpmresp, &tpmresp_len, TPM_DURATION_LONG);
1789
    if (ret != 0)
19✔
1790
        return 1;
1791

1792
    if (tpmresp_len < 34 + sizeof(length))
19✔
UNCOV
1793
        goto err_too_short;
×
1794
    memcpy(&length, &tpmresp[34], sizeof(length));
19✔
1795
    length = be32toh(length);
19✔
1796
    if (length != 256) {
19✔
UNCOV
1797
        logerr(self->logfile, "Offset to EK Public key is wrong.\n");
×
UNCOV
1798
        return 1;
×
1799
    }
1800

1801
    *pubek_len = 256;
19✔
1802
    if (tpmresp_len < 38 + *pubek_len)
19✔
UNCOV
1803
        goto err_too_short;
×
1804
    *pubek = g_malloc(256);
19✔
1805
    memcpy(*pubek, &tpmresp[38], *pubek_len);
19✔
1806

1807
    return 0;
19✔
1808

UNCOV
1809
err_too_short:
×
UNCOV
1810
    logerr(self->logfile, "Response from TPM_CreateEndorsementKeyPair is too short!\n");
×
UNCOV
1811
    return 1;
×
1812
}
1813

1814
/* Create an OIAP session */
1815
static int swtpm_tpm12_oiap(struct swtpm *self, uint32_t *authhandle, unsigned char nonce_even[SHA_DIGEST_LENGTH])
9✔
1816
{
1817
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_OIAP);
9✔
1818
    unsigned char tpmresp[64];
9✔
1819
    size_t tpmresp_len = sizeof(tpmresp);
9✔
1820
    int ret;
9✔
1821

1822
    ret = transfer(self, &req, sizeof(req), "TPM_OIAP", FALSE,
9✔
1823
                   &tpmresp, &tpmresp_len, TPM_DURATION_SHORT);
1824
    if (ret != 0)
9✔
1825
        return ret;
1826

1827
    if (tpmresp_len < 10 + sizeof(*authhandle) || tpmresp_len < 14 + SHA_DIGEST_LENGTH)
9✔
UNCOV
1828
        goto err_too_short;
×
1829
    memcpy(authhandle, &tpmresp[10], sizeof(*authhandle));
9✔
1830
    *authhandle = be32toh(*authhandle);
9✔
1831
    memcpy(nonce_even, &tpmresp[14], SHA_DIGEST_LENGTH);
9✔
1832

1833
    return 0;
9✔
1834

UNCOV
1835
err_too_short:
×
UNCOV
1836
    logerr(self->logfile, "Response from TPM_OIAP is too short!\n");
×
UNCOV
1837
    return 1;
×
1838
}
1839

1840
static int swtpm_tpm12_take_ownership(struct swtpm *self, const unsigned char ownerpass_digest[SHA_DIGEST_LENGTH],
9✔
1841
                                      const unsigned char srkpass_digest[SHA_DIGEST_LENGTH],
1842
                                      const unsigned char *pubek, size_t pubek_len)
1843
{
1844
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_AUTH1_COMMAND, 0, TPM_ORD_TAKE_OWNERSHIP);
9✔
1845
    EVP_PKEY *pkey = NULL;
9✔
1846
    EVP_PKEY_CTX *ctx = NULL;
9✔
1847
    BIGNUM *exp = BN_new();
9✔
1848
    BIGNUM *mod = NULL;
9✔
1849
#if OPENSSL_VERSION_NUMBER < 0x30000000L
1850
    RSA *rsakey = RSA_new();
1851
#endif
1852
    int ret = 1;
9✔
1853
    const EVP_MD *sha1 = EVP_sha1();
9✔
1854
    g_autofree unsigned char *enc_owner_auth = g_malloc(pubek_len);
9✔
1855
    size_t enc_owner_auth_len = pubek_len;
9✔
1856
    g_autofree unsigned char *enc_srk_auth = g_malloc(pubek_len);
18✔
1857
    size_t enc_srk_auth_len = pubek_len;
9✔
1858
    uint32_t auth_handle;
9✔
1859
    unsigned char nonce_even[SHA_DIGEST_LENGTH];
9✔
1860
    unsigned char nonce_odd[SHA_DIGEST_LENGTH] = {1, 2, 3, 4, 5, 6, };
9✔
1861
    g_autofree unsigned char *tpm_rsa_key_parms = NULL;
9✔
1862
    ssize_t tpm_rsa_key_parms_len;
9✔
1863
    g_autofree unsigned char *tpm_key_parms = NULL;
9✔
1864
    ssize_t tpm_key_parms_len;
9✔
1865
    g_autofree unsigned char *tpm_key12 = NULL;
9✔
1866
    ssize_t tpm_key12_len;
9✔
1867
    g_autofree unsigned char *in_auth_setup_params = NULL;
9✔
1868
    ssize_t in_auth_setup_params_len;
9✔
1869
    g_autofree unsigned char *macinput = NULL;
9✔
1870
    ssize_t macinput_len;
9✔
1871
    unsigned char in_param_digest[SHA_DIGEST_LENGTH];
9✔
1872
    unsigned char owner_auth[SHA_DIGEST_LENGTH];
9✔
1873
    unsigned int owner_auth_len = sizeof(owner_auth);
9✔
1874
    uint8_t continue_auth_session = 0;
9✔
1875
    unsigned char req[1024];
9✔
1876
    ssize_t req_len, len;
9✔
1877
    struct tpm_req_header *trh;
9✔
1878

1879
    mod = BN_bin2bn((const unsigned char *)pubek, pubek_len, NULL);
9✔
1880
    if (exp == NULL || mod == NULL ||
18✔
1881
        BN_hex2bn(&exp, "10001") == 0) {
9✔
UNCOV
1882
        logerr(self->logfile, "Could not create public RSA key!\n");
×
UNCOV
1883
        goto error_free_bn;
×
1884
    }
1885

1886
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1887
    ctx = EVP_PKEY_CTX_new_from_name(NULL, "rsa", NULL);
9✔
1888
    if (ctx != NULL) {
9✔
1889
        OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
9✔
1890
        OSSL_PARAM *params;
9✔
1891

1892
        if (bld == NULL ||
18✔
1893
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, exp) != 1 ||
18✔
1894
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, mod) != 1 ||
9✔
1895
            (params = OSSL_PARAM_BLD_to_param(bld)) == NULL) {
9✔
UNCOV
1896
            OSSL_PARAM_BLD_free(bld);
×
1897
            goto error_free_bn;
×
1898
        }
1899
        OSSL_PARAM_BLD_free(bld);
9✔
1900

1901
        if (EVP_PKEY_fromdata_init(ctx) != 1 ||
18✔
1902
            EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) != 1) {
9✔
1903
            logerr(self->logfile, "Could not set pkey parameters!\n");
×
1904
            OSSL_PARAM_free(params);
×
1905
            goto error_free_bn;
×
1906
        }
1907
        OSSL_PARAM_free(params);
9✔
1908

1909
        EVP_PKEY_CTX_free(ctx);
9✔
1910
    } else {
UNCOV
1911
        logerr(self->logfile, "Could not create key creation context!\n");
×
UNCOV
1912
        goto error_free_bn;
×
1913
    }
1914
    ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
9✔
1915
    if (ctx == NULL)
9✔
UNCOV
1916
        goto error_free_bn;
×
1917
#else
1918
    pkey = EVP_PKEY_new();
1919
    if (pkey == NULL) {
1920
        logerr(self->logfile, "Could not allocate pkey!\n");
1921
        goto error_free_bn;
1922
    }
1923

1924
# if OPENSSL_VERSION_NUMBER < 0x10100000
1925
    rsakey->n = mod;
1926
    rsakey->e = exp;
1927
# else
1928
    if (RSA_set0_key(rsakey, mod, exp, NULL) != 1) {
1929
        logerr(self->logfile, "Could not create public RSA key!\n");
1930
        goto error_free_bn;
1931
    }
1932
# endif
1933
    if (EVP_PKEY_assign_RSA(pkey, rsakey) != 1) {
1934
        logerr(self->logfile, "Could not create public RSA key!\n");
1935
        goto error_free_pkey_and_rsa;
1936
    }
1937

1938
    ctx = EVP_PKEY_CTX_new(pkey, NULL);
1939
    if (ctx == NULL)
1940
        goto error_free_pkey;
1941
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
1942

1943
    if (EVP_PKEY_encrypt_init(ctx) < 1 ||
18✔
1944
        EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) < 1 ||
18✔
1945
        EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sha1) < 1 ||
18✔
1946
        EVP_PKEY_CTX_set_rsa_oaep_md(ctx, sha1) < 1 ||
18✔
1947
        EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, g_strdup("TCPA"), 4) < 1 ||
18✔
1948
        EVP_PKEY_encrypt(ctx, enc_owner_auth, &enc_owner_auth_len,
9✔
1949
                         ownerpass_digest, SHA_DIGEST_LENGTH) < 1||
9✔
1950
        EVP_PKEY_encrypt(ctx, enc_srk_auth, &enc_srk_auth_len,
9✔
1951
                         srkpass_digest, SHA_DIGEST_LENGTH) < 1) {
UNCOV
1952
        logerr(self->logfile, "Internal error in %s: encryption failed\n", __func__);
×
UNCOV
1953
        goto error;
×
1954
    }
1955
    ret = swtpm_tpm12_oiap(self, &auth_handle, nonce_even);
9✔
1956
    if (ret != 0)
9✔
UNCOV
1957
        goto error;
×
1958

1959
    tpm_rsa_key_parms_len = memconcat(&tpm_rsa_key_parms,
18✔
1960
                                      (unsigned char[]){
9✔
1961
                                          AS4BE(2048), AS4BE(2), AS4BE(0)
1962
                                      }, (size_t)12,
1963
                                      NULL);
1964
    if (tpm_rsa_key_parms_len < 0) {
9✔
UNCOV
1965
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
UNCOV
1966
        goto error;
×
1967
    }
1968

1969
    tpm_key_parms_len = memconcat(&tpm_key_parms,
18✔
1970
                                  (unsigned char[]){
9✔
1971
                                      AS4BE(TPM_ALG_RSA),
1972
                                      AS2BE(TPM_ES_RSAESOAEP_SHA1_MGF1),
1973
                                      AS2BE(TPM_SS_NONE),
1974
                                      AS4BE(tpm_rsa_key_parms_len)}, (size_t)12,
9✔
1975
                                  tpm_rsa_key_parms, tpm_rsa_key_parms_len,
1976
                                  NULL);
1977
    if (tpm_key_parms_len < 0) {
9✔
UNCOV
1978
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
UNCOV
1979
        goto error;
×
1980
    }
1981

1982
    tpm_key12_len = memconcat(&tpm_key12,
18✔
1983
                              (unsigned char[]){
9✔
1984
                                  AS2BE(TPM_TAG_KEY12), AS2BE(0),
1985
                                  AS2BE(TPM_KEY_STORAGE), AS4BE(0), TPM_AUTH_ALWAYS
1986
                              }, (size_t)11,
1987
                              tpm_key_parms, tpm_key_parms_len,
1988
                              (unsigned char[]){AS4BE(0), AS4BE(0), AS4BE(0)}, (size_t)12,
9✔
1989
                              NULL);
1990
    if (tpm_key12_len < 0) {
9✔
1991
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
UNCOV
1992
        goto error;
×
1993
    }
1994

1995
    req_len = concat(req, sizeof(req),
18✔
1996
                     &hdr, sizeof(hdr),
1997
                     (unsigned char[]){AS2BE(TPM_PID_OWNER), AS4BE(enc_owner_auth_len)}, (size_t)6,
9✔
1998
                     enc_owner_auth, enc_owner_auth_len,
1999
                     (unsigned char[]){AS4BE(enc_srk_auth_len)}, (size_t)4,
9✔
2000
                     enc_srk_auth, enc_srk_auth_len,
2001
                     tpm_key12, tpm_key12_len,
2002
                     NULL);
2003
    if (req_len < 0) {
9✔
UNCOV
2004
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
2005
        goto error;
×
2006
    }
2007
    SHA1(&req[6], req_len - 6, in_param_digest);
9✔
2008

2009
    in_auth_setup_params_len = memconcat(&in_auth_setup_params,
9✔
2010
                                         nonce_even, sizeof(nonce_even),
2011
                                         nonce_odd, sizeof(nonce_odd),
2012
                                         &continue_auth_session, (size_t)1,
2013
                                         NULL);
2014
    if (in_auth_setup_params_len < 0) {
9✔
UNCOV
2015
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
UNCOV
2016
        goto error;
×
2017
    }
2018

2019
    macinput_len = memconcat(&macinput,
9✔
2020
                             in_param_digest, sizeof(in_param_digest),
2021
                             in_auth_setup_params, in_auth_setup_params_len,
2022
                             NULL);
2023
    if (macinput_len < 0) {
9✔
UNCOV
2024
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
UNCOV
2025
        goto error;
×
2026
    }
2027

2028
    HMAC(sha1, ownerpass_digest, SHA_DIGEST_LENGTH, macinput, macinput_len,
9✔
2029
         owner_auth, &owner_auth_len);
2030

2031
    len = concat(&req[req_len], sizeof(req) - req_len,
18✔
2032
                 (unsigned char[]){AS4BE(auth_handle)}, (size_t)4,
9✔
2033
                 nonce_odd, sizeof(nonce_odd),
2034
                 &continue_auth_session, (size_t)1,
2035
                 owner_auth, owner_auth_len,
2036
                 NULL);
2037
    if (len < 0) {
9✔
UNCOV
2038
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
UNCOV
2039
        goto error;
×
2040
    }
2041
    req_len += len;
9✔
2042

2043
    trh = (struct tpm_req_header *)req; /* old gcc type-punned pointer */
9✔
2044
    trh->size = htobe32(req_len);
9✔
2045

2046
    ret = transfer(self, req, req_len, "TPM_TakeOwnership", FALSE,
9✔
2047
                   NULL, NULL, TPM_DURATION_LONG);
2048

2049
error:
9✔
2050
    EVP_PKEY_free(pkey);
9✔
2051
    EVP_PKEY_CTX_free(ctx);
9✔
2052
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
2053
    BN_free(exp);
9✔
2054
    BN_free(mod);
9✔
2055
#endif
2056
    return ret;
9✔
2057

UNCOV
2058
error_free_bn:
×
2059
    BN_free(exp);
×
2060
    BN_free(mod);
×
2061

2062
#if OPENSSL_VERSION_NUMBER < 0x30000000L
2063
error_free_pkey_and_rsa:
2064
    RSA_free(rsakey);
2065
error_free_pkey:
2066
#else
UNCOV
2067
    EVP_PKEY_CTX_free(ctx);
×
2068
#endif
UNCOV
2069
    EVP_PKEY_free(pkey);
×
2070

UNCOV
2071
    return 1;
×
2072
}
2073

2074
static int swtpm_tpm12_nv_define_space(struct swtpm *self, uint32_t nvindex,
27✔
2075
                                       uint32_t nvindexattrs, size_t size)
2076
{
2077
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_DEFINE_SPACE);
27✔
2078
    g_autofree unsigned char *pcr_info_short = NULL;
54✔
2079
    ssize_t pcr_info_short_len;
27✔
2080
    g_autofree unsigned char *nv_data_public = NULL;
27✔
2081
    ssize_t nv_data_public_len;
27✔
2082
    g_autofree unsigned char *req = NULL;
27✔
2083
    ssize_t req_len;
27✔
2084
    unsigned char zeroes[SHA_DIGEST_LENGTH] = {0, };
27✔
2085

2086
    pcr_info_short_len = memconcat(&pcr_info_short,
54✔
2087
                                   (unsigned char[]){AS2BE(3), 0, 0, 0, TPM_LOC_ALL}, (size_t)6,
27✔
2088
                                   zeroes, sizeof(zeroes),
2089
                                   NULL);
2090
    if (pcr_info_short_len < 0) {
27✔
UNCOV
2091
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
UNCOV
2092
        return 1;
×
2093
    }
2094

2095
    nv_data_public_len = memconcat(&nv_data_public,
54✔
2096
                                   (unsigned char[]){
27✔
2097
                                       AS2BE(TPM_TAG_NV_DATA_PUBLIC), AS4BE(nvindex)
27✔
2098
                                   }, (size_t)6,
2099
                                   pcr_info_short, pcr_info_short_len,
2100
                                   pcr_info_short, pcr_info_short_len,
2101
                                   (unsigned char[]){
27✔
2102
                                       AS2BE(TPM_TAG_NV_ATTRIBUTES), AS4BE(nvindexattrs),
27✔
2103
                                       0, 0, 0, AS4BE(size)
27✔
2104
                                   }, (size_t)13,
2105
                                   NULL);
2106
    if (nv_data_public_len < 0) {
27✔
UNCOV
2107
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
UNCOV
2108
        return 1;
×
2109
    }
2110

2111
    req_len = memconcat(&req,
27✔
2112
                        &hdr, sizeof(hdr),
2113
                        nv_data_public, nv_data_public_len,
2114
                        zeroes, sizeof(zeroes),
2115
                        NULL);
2116
    if (req_len < 0) {
27✔
UNCOV
2117
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2118
        return 1;
×
2119
    }
2120

2121
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
27✔
2122

2123
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE,
27✔
2124
                    NULL, NULL, TPM_DURATION_SHORT);
2125
}
2126

2127
static int swtpm_tpm12_nv_write_value(struct swtpm *self, uint32_t nvindex,
15✔
2128
                                      const unsigned char *data, size_t data_len)
2129
{
2130
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_WRITE_VALUE);
15✔
2131
    g_autofree unsigned char *req = NULL;
30✔
2132
    ssize_t req_len;
15✔
2133

2134
    req_len = memconcat(&req,
30✔
2135
                        &hdr, sizeof(hdr),
2136
                        (unsigned char[]){AS4BE(nvindex), AS4BE(0), AS4BE(data_len)}, (size_t)12,
15✔
2137
                        data, data_len,
2138
                        NULL);
2139
    if (req_len < 0) {
15✔
UNCOV
2140
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
UNCOV
2141
        return 1;
×
2142
    }
2143

2144
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
15✔
2145

2146
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE,
15✔
2147
                    NULL, NULL, TPM_DURATION_SHORT);
2148
}
2149

2150
/* Write the EK Certificate into NVRAM */
2151
static int swtpm_tpm12_write_ek_cert_nvram(struct swtpm *self,
8✔
2152
                                           const unsigned char *data, size_t data_len)
2153
{
2154
    uint32_t nvindex = TPM_NV_INDEX_EKCERT | TPM_NV_INDEX_D_BIT;
8✔
2155
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
8✔
2156
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
2157
    if (ret != 0)
8✔
2158
        return 1;
2159

2160
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
8✔
2161
    if (ret != 0)
8✔
2162
        return 1;
2163

2164
    return 0;
2165
}
2166

2167
/* Write the Platform Certificate into NVRAM */
2168
static int swtpm_tpm12_write_platform_cert_nvram(struct swtpm *self,
7✔
2169
                                                 const unsigned char *data, size_t data_len)
2170
{
2171
    uint32_t nvindex = TPM_NV_INDEX_PLATFORMCERT | TPM_NV_INDEX_D_BIT;
7✔
2172
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
7✔
2173
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
2174
    if (ret != 0)
7✔
2175
        return 1;
2176

2177
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
7✔
2178
    if (ret != 0)
7✔
2179
        return 1;
2180

2181
    return 0;
2182
}
2183

2184
static int swtpm_tpm12_nv_lock(struct swtpm *self)
12✔
2185
{
2186
    return swtpm_tpm12_nv_define_space(self, TPM_NV_INDEX_LOCK, 0, 0);
12✔
2187
}
2188

2189
static const struct swtpm12_ops swtpm_tpm12_ops = {
2190
    .run_swtpm_bios = swtpm_tpm12_run_swtpm_bios,
2191
    .create_endorsement_key_pair = swptm_tpm12_create_endorsement_keypair,
2192
    .take_ownership = swtpm_tpm12_take_ownership,
2193
    .write_ek_cert_nvram = swtpm_tpm12_write_ek_cert_nvram,
2194
    .write_platform_cert_nvram = swtpm_tpm12_write_platform_cert_nvram,
2195
    .nv_lock = swtpm_tpm12_nv_lock,
2196
};
2197

2198
static void swtpm_init(struct swtpm *swtpm,
156✔
2199
                       gchar **swtpm_exec_l, const gchar *state_path,
2200
                       const gchar *keyopts, const gchar *logfile,
2201
                       int *fds_to_pass, size_t n_fds_to_pass,
2202
                       gboolean is_tpm2, const gchar *json_profile,
2203
                       int json_profile_fd,
2204
                       const gchar *profile_remove_disabled_param)
2205
{
2206
    swtpm->cops = &swtpm_cops;
156✔
2207
    swtpm->swtpm_exec_l = swtpm_exec_l;
156✔
2208
    swtpm->state_path = state_path;
156✔
2209
    swtpm->keyopts = keyopts;
156✔
2210
    swtpm->logfile = logfile;
156✔
2211
    swtpm->fds_to_pass = fds_to_pass;
156✔
2212
    swtpm->n_fds_to_pass = n_fds_to_pass;
156✔
2213
    swtpm->is_tpm2 = is_tpm2;
156✔
2214
    swtpm->json_profile = json_profile;
156✔
2215
    swtpm->json_profile_fd = json_profile_fd;
156✔
2216
    swtpm->profile_remove_disabled_param = profile_remove_disabled_param;
156✔
2217

2218
    swtpm->pid = -1;
156✔
2219
    swtpm->ctrl_fds[0] = swtpm->ctrl_fds[1] = -1;
156✔
2220
    swtpm->data_fds[0] = swtpm->data_fds[1] = -1;
156✔
2221
}
2222

2223
struct swtpm12 *swtpm12_new(gchar **swtpm_exec_l, const gchar *state_path,
26✔
2224
                            const gchar *keyopts, const gchar *logfile,
2225
                            int *fds_to_pass, size_t n_fds_to_pass)
2226
{
2227
    struct swtpm12 *swtpm12 = g_malloc0(sizeof(struct swtpm12));
26✔
2228

2229
    swtpm_init(&swtpm12->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
26✔
2230
               fds_to_pass, n_fds_to_pass, FALSE, NULL, 0, NULL);
2231
    swtpm12->ops = &swtpm_tpm12_ops;
26✔
2232

2233
    return swtpm12;
26✔
2234
}
2235

2236
struct swtpm2 *swtpm2_new(gchar **swtpm_exec_l, const gchar *state_path,
130✔
2237
                         const gchar *keyopts, const gchar *logfile,
2238
                         int *fds_to_pass, size_t n_fds_to_pass,
2239
                         const gchar *json_profile, int json_profile_fd,
2240
                         const gchar *profile_remove_disabled_param)
2241
{
2242
    struct swtpm2 *swtpm2 = g_malloc0(sizeof(struct swtpm2));
130✔
2243

2244
    swtpm_init(&swtpm2->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
130✔
2245
               fds_to_pass, n_fds_to_pass, TRUE, json_profile, json_profile_fd,
2246
               profile_remove_disabled_param);
2247
    swtpm2->ops = &swtpm_tpm2_ops;
130✔
2248

2249
    return swtpm2;
130✔
2250
}
2251

2252
void swtpm_free(struct swtpm *swtpm) {
156✔
2253
    if (!swtpm)
156✔
2254
        return;
2255
    g_free(swtpm);
156✔
2256
}
2257

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc