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

stefanberger / swtpm / #2953

22 Apr 2026 06:29PM UTC coverage: 73.266% (+0.3%) from 72.992%
#2953

push

travis-ci

web-flow
Merge 499351731 into c239abc46

74 of 83 new or added lines in 1 file covered. (89.16%)

3 existing lines in 1 file now uncovered.

7827 of 10683 relevant lines covered (73.27%)

10063.23 hits per line

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

81.95
/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)
317✔
67
{
68
    if (all)
317✔
69
        SWTPM_CLOSE(self->data_fds[0]);
158✔
70
    SWTPM_CLOSE(self->data_fds[1]);
317✔
71

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

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

98
    pidfile_fd = g_mkstemp_full(pidfile, O_EXCL|O_CREAT, 0600);
161✔
99
    if (pidfile_fd < 0) {
161✔
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);
161✔
105

106
    argv = concat_arrays((const char **)self->swtpm_exec_l,
322✔
107
                         (const gchar*[]){
161✔
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)
161✔
118
        argv = concat_arrays(argv, (const gchar*[]){"--tpm2", NULL}, TRUE);
135✔
119

120
    if (self->keyopts != NULL) {
161✔
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) {
161✔
126
        json_profile = g_strdup_printf("fd=%u", self->json_profile_fd);
31✔
127
    } else if (self->json_profile != NULL) {
130✔
128
        json_profile = g_strdup_printf("profile=%s", self->json_profile);
94✔
129
        logit(self->logfile, "Apply profile: %s\n", self->json_profile);
94✔
130
    }
131
    if (json_profile && self->profile_remove_disabled_param) {
125✔
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)
161✔
139
        argv = concat_arrays(argv, (const gchar*[]){
125✔
140
                                 "--profile",
141
                                 json_profile,
142
                                 json_profile_params,
143
                                 NULL
144
                             }, TRUE);
145

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

151
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, self->ctrl_fds) != 0) {
161✔
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]);
161✔
156

157
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, self->data_fds) != 0) {
161✔
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]);
161✔
162

163
    argv = concat_arrays(argv, (const gchar*[]){
161✔
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;
161✔
177
    if (gl_LOGFILE) {
161✔
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;
71✔
182
#endif
183
    }
184

185
    success = spawn_async(NULL, argv, NULL, flags,
161✔
186
                          NULL, NULL, &self->pid, &error);
187
    if (!success) {
161✔
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++) {
941✔
195
        if (kill(self->pid, 0) < 0) {
941✔
196
            /* swtpm terminated */
197
            self->pid = 0;
2✔
198
            logerr(self->logfile, "swtpm process terminated unexpectedly.\n");
2✔
199
            self->cops->stop(self);
2✔
200
            goto error;
2✔
201
        }
202
        if (fstat(pidfile_fd, &statbuf) == 0 && statbuf.st_size > 0) {
939✔
203
            printf("TPM is listening on Unix socket.\n");
159✔
204
            ret = 0;
159✔
205
            break;
159✔
206
        }
207
        usleep(5000);
780✔
208
    }
209

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

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

216
error_no_pidfile:
161✔
217
    return ret;
161✔
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)
156✔
222
{
223
    unsigned c;
156✔
224
    gboolean ended = FALSE;
156✔
225

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

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

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

245
/* Destroy a running swtpm instance */
246
static void swtpm_destroy(struct swtpm *self)
154✔
247
{
248
    self->cops->stop(self);
154✔
249
}
154✔
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,607✔
253
                    const char *cmdname, gboolean use_ctrl,
254
                    void *respbuffer, size_t *respbuffer_len, int timeout_ms)
255
{
256
    size_t offset;
1,607✔
257
    int sockfd;
1,607✔
258
    ssize_t n;
1,607✔
259
    unsigned char resp[4096];
1,607✔
260
    ssize_t resplen;
1,607✔
261
    uint32_t returncode;
1,607✔
262
    struct pollfd fds = {
1,607✔
263
        .events = POLLIN | POLLERR | POLLHUP,
264
    };
265
    size_t respbuffer_size = 0;
1,607✔
266

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

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

280
    n = write(sockfd, buffer, buffer_len);
1,607✔
281
    if (n < 0) {
1,607✔
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,602✔
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,602✔
293
    n = poll(&fds, 1, timeout_ms);
1,602✔
294
    if (n != 1 || (fds.revents & POLLIN) == 0) {
1,602✔
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,602✔
302
    if (resplen < 0) {
1,602✔
UNCOV
303
        logerr(self->logfile, "Could not receive response to %s from swtpm: %s\n",
×
UNCOV
304
               cmdname, strerror(errno));
×
UNCOV
305
        return 1;
×
306
    }
307

308
    if (!use_ctrl) {
1,602✔
309
        if ((size_t)resplen < sizeof(struct tpm_resp_header)) {
1,222✔
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) {
380✔
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,602✔
321
        /* give caller response even if command failed */
322
        *respbuffer_len = min((size_t)resplen, respbuffer_size);
503✔
323
        memcpy(respbuffer, resp, *respbuffer_len);
503✔
324
    }
325

326
    memcpy(&returncode, &resp[offset], sizeof(returncode));
1,602✔
327
    returncode = be32toh(returncode);
1,602✔
328
    if (returncode != 0) {
1,602✔
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)
154✔
339
{
340
    uint32_t cmd = htobe32(CMD_SHUTDOWN);
154✔
341

342
    return transfer(self, &cmd, sizeof(cmd), "CMD_SHUTDOWN", TRUE,
154✔
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,
231✔
348
                           gchar **result)
349
{
350
    unsigned char req[] = {AS4BE(CMD_GET_INFO),
231✔
351
                           AS8BE(swtpm_info_flags),
231✔
352
                           AS4BE(0), AS4BE(0)};
353
    unsigned char tpmresp[16 * 1024];
231✔
354
    size_t tpmresp_len = sizeof(tpmresp);
231✔
355
    int ret;
231✔
356
    uint32_t length;
231✔
357

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

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

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

372
    return 0;
226✔
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)
104✔
381
{
382
    return do_cmd_get_info(self,
104✔
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_SECP256R1_EKCERT        0x01c0000a
457
#define TPM2_NV_INDEX_ECC_SECP256R1_EKTEMPLATE    0x01c0000b
458
#define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT     0x01c00016
459
#define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE 0x01c00017
460
#define TPM2_NV_INDEX_ECC_SECP521R1_HI_EKCERT     0x01c00018
461
#define TPM2_NV_INDEX_ECC_SECP521R1_HI_EKTEMPLATE 0x01c00019
462

463
#define TPM2_EK_RSA_HANDLE           0x81010001
464
#define TPM2_EK_RSA3072_HANDLE       0x8101001c
465
#define TPM2_EK_RSA4096_HANDLE       0x8101001e
466
#define TPM2_EK_ECC_SECP256R1_HANDLE 0x8101000a
467
#define TPM2_EK_ECC_SECP384R1_HANDLE 0x81010016
468
#define TPM2_EK_ECC_SECP521R1_HANDLE 0x81010018
469
#define TPM2_SPK_HANDLE              0x81000001
470

471
#define TPM2_DURATION_SHORT      ( 2000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
472
#define TPM2_DURATION_MEDIUM     ( 7500 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
473
#define TPM2_DURATION_LONG       (15000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
474
#define TPM2_DURATION_EXTRA_LONG (30000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
475

476
#define TPM_REQ_HEADER_INITIALIZER(TAG, SIZE, ORD) \
477
    { \
478
        .tag = htobe16(TAG), \
479
        .size = htobe32(SIZE), \
480
        .ordinal = htobe32(ORD), \
481
    }
482

483
struct tpm2_authblock {
484
    uint32_t auth;
485
    uint16_t nonceSize; // currently always 0
486
    uint8_t continueSession;
487
    uint16_t pwdSize; // currently always 0
488
} __attribute__((packed));
489

490
#define TPM2_AUTHBLOCK_INITIALIZER(AUTH) \
491
    { \
492
        .auth = htobe32(AUTH), \
493
        .nonceSize = htobe16(0), \
494
        .continueSession = 0, \
495
        .pwdSize = htobe16(0), \
496
    }
497

498
static const unsigned char NONCE_EMPTY[2] = {AS2BE(0)};
499
static const unsigned char NONCE_RSA2048[2+0x100] = {AS2BE(0x100), 0, };
500
static const unsigned char NONCE_RSA3072[2+0x180] = {AS2BE(0x180), 0, };
501
static const unsigned char NONCE_RSA4096[2+0x200] = {AS2BE(0x200), 0, };
502
static const unsigned char NONCE_ECC_256[2+0x20] = {AS2BE(0x20), 0, };
503
static const unsigned char NONCE_ECC_384[2+0x30] = {AS2BE(0x30), 0, };
504
static const unsigned char NONCE_ECC_521[2+0x42] = {AS2BE(0x42), 0, };
505

506
static const unsigned char PolicyA_SHA256[32] = {
507
    0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d,
508
    0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64,
509
    0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa
510
};
511

512
static const unsigned char PolicyB_SHA384[48] = {
513
    0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC,
514
    0x53, 0xD8, 0x82, 0xBC, 0xF5, 0xFD, 0x3A, 0x1A,
515
    0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4,
516
    0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA,
517
    0xCB, 0x47, 0xBA, 0x09, 0x69, 0x96, 0x46, 0x15,
518
    0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12
519
};
520

521
static const unsigned char PolicyB_SHA512[64] = {
522
    0xB8, 0x22, 0x1C, 0xA6, 0x9E, 0x85, 0x50, 0xA4,
523
    0x91, 0x4D, 0xE3, 0xFA, 0xA6, 0xA1, 0x8C, 0x07,
524
    0x2C, 0xC0, 0x12, 0x08, 0x07, 0x3A, 0x92, 0x8D,
525
    0x5D, 0x66, 0xD5, 0x9E, 0xF7, 0x9E, 0x49, 0xA4,
526
    0x29, 0xC4, 0x1A, 0x6B, 0x26, 0x95, 0x71, 0xD5,
527
    0x7E, 0xDB, 0x25, 0xFB, 0xDB, 0x18, 0x38, 0x42,
528
    0x56, 0x08, 0xB4, 0x13, 0xCD, 0x61, 0x6A, 0x5F,
529
    0x6D, 0xB5, 0xB6, 0x07, 0x1A, 0xF9, 0x9B, 0xEA
530
};
531

532
static const struct bank_to_name {
533
    uint16_t hashAlg;
534
    const char *name;
535
} banks_to_names[] = {
536
    {TPM2_ALG_SHA1, "sha1"},
537
    {TPM2_ALG_SHA256, "sha256"},
538
    {TPM2_ALG_SHA384, "sha384"},
539
    {TPM2_ALG_SHA512, "sha512"},
540
    {TPM2_ALG_SM3, "sm3-256"},
541
    {TPM2_ALG_SHA3_256, "sha3-256"},
542
    {TPM2_ALG_SHA3_384, "sha3-384"},
543
    {TPM2_ALG_SHA3_512, "sha3-512"},
544
    {0, NULL},
545
};
546

547
struct pk_params {
548
    enum keyalgo keyalgo;
549
    uint16_t keyalgo_param; // RSA key size or ECC curve Id
550
    const char *keydescription;
551
    const unsigned char *nonce;
552
    size_t nonce_len;
553
    uint16_t hashalg;
554
    const unsigned char *authpolicy;
555
    size_t authpolicy_len;
556
    unsigned int symkey_len;
557
    int duration;
558
    unsigned keysize;
559
};
560

561
static const struct ek_params {
562
    struct pk_params pk;
563
    uint32_t ek_handle;
564
    const char *keytype;
565
    uint32_t nvindex_ekcert;
566
    uint32_t nvindex_template;
567
} ek_params[] = {
568
    {
569
        .pk = {
570
            .keyalgo = KEYALGO_ECC,
571
            .keyalgo_param = TPM2_ECC_NIST_P256,
572
            .keydescription = "secp256r1",
573
            .nonce = NONCE_ECC_256,
574
            .nonce_len = sizeof(NONCE_ECC_256),
575
            .hashalg = TPM2_ALG_SHA256,
576
            .authpolicy = PolicyA_SHA256,
577
            .authpolicy_len = sizeof(PolicyA_SHA256),
578
            .symkey_len = 128,
579
            .duration = TPM2_DURATION_LONG,
580
            .keysize = 32,
581
        },
582
        .ek_handle = TPM2_EK_ECC_SECP256R1_HANDLE,
583
        .keytype = "secp256r1",
584
        .nvindex_ekcert = TPM2_NV_INDEX_ECC_SECP256R1_EKCERT,
585
        .nvindex_template = TPM2_NV_INDEX_ECC_SECP256R1_EKTEMPLATE,
586
    }, {
587
        .pk = {
588
            .keyalgo = KEYALGO_ECC,
589
            .keyalgo_param = TPM2_ECC_NIST_P384,
590
            .keydescription = "secp384r1",
591
            .nonce = NONCE_EMPTY,
592
            .nonce_len = sizeof(NONCE_EMPTY),
593
            .hashalg = TPM2_ALG_SHA384,
594
            .authpolicy = PolicyB_SHA384,
595
            .authpolicy_len = sizeof(PolicyB_SHA384),
596
            .symkey_len = 256,
597
            .duration = TPM2_DURATION_LONG,
598
            .keysize = 48,
599
        },
600
        .ek_handle = TPM2_EK_ECC_SECP384R1_HANDLE,
601
        .keytype = "ECC",
602
        .nvindex_ekcert = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT,
603
        .nvindex_template = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE,
604
    }, {
605
        .pk = {
606
            .keyalgo = KEYALGO_ECC,
607
            .keyalgo_param = TPM2_ECC_NIST_P521,
608
            .keydescription = "secp521r1",
609
            .nonce = NONCE_EMPTY,
610
            .nonce_len = sizeof(NONCE_EMPTY),
611
            .hashalg = TPM2_ALG_SHA512,
612
            .authpolicy = PolicyB_SHA512,
613
            .authpolicy_len = sizeof(PolicyB_SHA512),
614
            .symkey_len = 256,
615
            .duration = TPM2_DURATION_LONG,
616
            .keysize = 66,
617
        },
618
        .ek_handle = TPM2_EK_ECC_SECP521R1_HANDLE,
619
        .keytype = "ECC",
620
        .nvindex_ekcert = TPM2_NV_INDEX_ECC_SECP521R1_HI_EKCERT,
621
        .nvindex_template = TPM2_NV_INDEX_ECC_SECP521R1_HI_EKTEMPLATE,
622
    }, {
623
        .pk = {
624
            .keyalgo = KEYALGO_RSA,
625
            .keyalgo_param = 2048,
626
            .keydescription = "rsa2048",
627
            .nonce = NONCE_RSA2048,
628
            .nonce_len = sizeof(NONCE_RSA2048),
629
            .hashalg = TPM2_ALG_SHA256,
630
            .authpolicy = PolicyA_SHA256,
631
            .authpolicy_len = sizeof(PolicyA_SHA256),
632
            .symkey_len = 128,
633
            .duration = TPM2_DURATION_LONG,
634
            .keysize = 2048 / 8,
635
        },
636
        .ek_handle = TPM2_EK_RSA_HANDLE,
637
        .keytype = "RSA 2048",
638
        .nvindex_ekcert = TPM2_NV_INDEX_RSA2048_EKCERT,
639
        .nvindex_template = TPM2_NV_INDEX_RSA2048_EKTEMPLATE,
640
    }, {
641
        .pk = {
642
            .keyalgo = KEYALGO_RSA,
643
            .keyalgo_param = 3072,
644
            .keydescription = "rsa3072",
645
            .nonce = NONCE_EMPTY,
646
            .nonce_len = sizeof(NONCE_EMPTY),
647
            .hashalg = TPM2_ALG_SHA384,
648
            .authpolicy = PolicyB_SHA384,
649
            .authpolicy_len = sizeof(PolicyB_SHA384),
650
            .symkey_len = 256,
651
            .duration = TPM2_DURATION_LONG,
652
            .keysize = 3072 / 8,
653
        },
654
        .ek_handle = TPM2_EK_RSA3072_HANDLE,
655
        .keytype = "RSA 3072",
656
        .nvindex_ekcert = TPM2_NV_INDEX_RSA3072_HI_EKCERT,
657
        .nvindex_template = TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE,
658
    }, {
659
        .pk = {
660
            .keyalgo = KEYALGO_RSA,
661
            .keyalgo_param = 4096,
662
            .keydescription = "rsa4096",
663
            .nonce = NONCE_EMPTY,
664
            .nonce_len = sizeof(NONCE_EMPTY),
665
            .hashalg = TPM2_ALG_SHA384,
666
            .authpolicy = PolicyB_SHA384,
667
            .authpolicy_len = sizeof(PolicyB_SHA384),
668
            .symkey_len = 256,
669
            .duration = TPM2_DURATION_EXTRA_LONG,
670
            .keysize = 4096 / 8,
671
        },
672
        .ek_handle = TPM2_EK_RSA4096_HANDLE,
673
        .keytype = "RSA 4096",
674
        .nvindex_ekcert = TPM2_NV_INDEX_RSA4096_HI_EKCERT,
675
        .nvindex_template = TPM2_NV_INDEX_RSA4096_HI_EKTEMPLATE,
676
    }
677
};
678

679
static const unsigned char null_authpolicy[] = {};
680

681
static const struct spk_params {
682
    struct pk_params pk;
683
} spk_params[] = {
684
    {
685
        .pk = {
686
            .keyalgo = KEYALGO_ECC,
687
            .keyalgo_param = TPM2_ECC_NIST_P256,
688
            .nonce = NONCE_ECC_256,
689
            .nonce_len = sizeof(NONCE_ECC_256),
690
            .hashalg = TPM2_ALG_SHA256,
691
            .authpolicy = null_authpolicy,
692
            .authpolicy_len = 0,
693
            .keysize = 32,
694
            .symkey_len = 128,
695
            .duration = TPM2_DURATION_LONG,
696
        }
697
   }, {
698
        .pk = {
699
            .keyalgo = KEYALGO_ECC,
700
            .keyalgo_param = TPM2_ECC_NIST_P384,
701
            /* per "TCG TPM v2.0 Provisioning Guidance v1.0" page 37
702
             * -> "Ek Credential Profile 2.0" rev.14 section 2.1.5.2:
703
             * template for NIST P256 uses 2 identical 32-byte all-zero nonces
704
             * -> Use two 48-byte all-zero nonces for NIST P384.
705
             */
706
            .nonce = NONCE_ECC_384,
707
            .nonce_len = sizeof(NONCE_ECC_384),
708
            .hashalg = TPM2_ALG_SHA384,
709
            .authpolicy = null_authpolicy,
710
            .authpolicy_len = 0,
711
            .keysize = 48,
712
            .symkey_len = 256,
713
            .duration = TPM2_DURATION_LONG,
714
        },
715
    }, {
716
        .pk = {
717
            .keyalgo = KEYALGO_ECC,
718
            .keyalgo_param = TPM2_ECC_NIST_P521,
719
            .nonce = NONCE_ECC_521,
720
            .nonce_len = sizeof(NONCE_ECC_521),
721
            .hashalg = TPM2_ALG_SHA512,
722
            .authpolicy = null_authpolicy,
723
            .authpolicy_len = 0,
724
            .keysize = 66,
725
            .symkey_len = 256,
726
            .duration = TPM2_DURATION_LONG,
727
       },
728
    }
729
};
730

731
static const struct ek_params *get_ek_params(struct swtpm *self,
262✔
732
                                             enum keyalgo keyalgo,
733
                                             unsigned int keyalgo_param)
734
{
735
    size_t i;
262✔
736

737
    for (i = 0; i < ARRAY_LEN(ek_params); i++) {
933✔
738
        if (ek_params[i].pk.keyalgo == keyalgo &&
933✔
739
            ek_params[i].pk.keyalgo_param == keyalgo_param) {
450✔
740
            return &ek_params[i];
262✔
741
        }
742
    }
743
    logerr(self->logfile, "Internal error: Unsupported keyalgo and keyalgo_param: %u/%u\n",
×
744
           keyalgo, keyalgo_param);
745
    return NULL;
×
746
}
747

748
static const struct spk_params *get_spk_params(struct swtpm *self,
2✔
749
                                               enum keyalgo keyalgo,
750
                                               unsigned int keyalgo_param)
751
{
752
    size_t i;
2✔
753

754
    for (i = 0; i < ARRAY_LEN(spk_params); i++) {
4✔
755
        if (spk_params[i].pk.keyalgo == keyalgo &&
4✔
756
            spk_params[i].pk.keyalgo_param == keyalgo_param) {
4✔
757
            return &spk_params[i];
2✔
758
        }
759
    }
760
    logerr(self->logfile, "Internal error: Unsupported SRK keyalgo and keyalgo_param: %u/%u\n",
×
761
           keyalgo, keyalgo_param);
762
    return NULL;
×
763
}
764

765

766
/* function prototypes */
767
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
768
                                        const struct pk_params *pk_params,
769
                                        size_t off, uint32_t *curr_handle,
770
                                        unsigned char *ektemplate, size_t *ektemplate_len,
771
                                        gchar **ekparam, const gchar **key_description);
772

773
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
774
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
775
                                  const char *purpose);
776

777
/* Given a hash algo identifier, return the name of the hash bank */
778
static const char *get_name_for_bank(uint16_t hashAlg) {
462✔
779
    size_t i;
462✔
780

781
    for (i = 0; banks_to_names[i].name; i++) {
1,158✔
782
        if (banks_to_names[i].hashAlg == hashAlg)
1,158✔
783
            return banks_to_names[i].name;
784
    }
785
    return NULL;
786
}
787

788
/* Give the name of a hash bank, return its algo identifier */
789
static uint16_t get_hashalg_by_bankname(const char *name) {
460✔
790
    size_t i;
460✔
791

792
    for (i = 0; banks_to_names[i].name; i++) {
1,153✔
793
        if (strcmp(banks_to_names[i].name, name) == 0)
1,153✔
794
            return banks_to_names[i].hashAlg;
460✔
795
    }
796
    return 0;
797
}
798

799
/* Do an SU_CLEAR shutdown of the TPM 2 */
800
static int swtpm_tpm2_shutdown(struct swtpm *self)
127✔
801
{
802
    struct tpm2_shutdown_req {
127✔
803
        struct tpm_req_header hdr;
804
        uint16_t shutdownType;
805
    } __attribute__((packed)) req = {
127✔
806
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_SHUTDOWN),
127✔
807
        .shutdownType = htobe16(TPM2_SU_CLEAR)
127✔
808
    };
809

810
    return transfer(self, &req, sizeof(req), "TPM2_Shutdown", FALSE,
127✔
811
                    NULL, NULL, TPM2_DURATION_SHORT);
812
}
813

814
/* Get all available PCR banks */
815
static int swtpm_tpm2_get_all_pcr_banks(struct swtpm *self, gchar ***all_pcr_banks)
128✔
816
{
817
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, 0, TPM2_CC_GETCAPABILITY);
128✔
818
    g_autofree unsigned char *req = NULL;
256✔
819
    ssize_t req_len;
128✔
820
    unsigned char tpmresp[256];
128✔
821
    size_t tpmresp_len = sizeof(tpmresp);
128✔
822
    uint16_t count, bank;
128✔
823
    const char *name;
128✔
824
    uint8_t length;
128✔
825
    size_t offset;
128✔
826
    size_t i;
128✔
827
    int ret;
128✔
828

829
    req_len = memconcat(&req,
256✔
830
                        &hdr, sizeof(hdr),
831
                        (unsigned char[]){AS4BE(TPM2_CAP_PCRS), AS4BE(0), AS4BE(64)}, (size_t)12,
128✔
832
                        NULL);
833
    if (req_len < 0) {
128✔
834
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
835
        return 1;
×
836
    }
837
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
128✔
838

839
    ret = transfer(self, req, req_len, "TPM2_GetCapability", FALSE,
128✔
840
                   tpmresp, &tpmresp_len, TPM2_DURATION_MEDIUM);
841
    if (ret != 0)
128✔
842
        return 1;
843

844
    *all_pcr_banks = NULL;
128✔
845

846
    if (tpmresp_len < 17 + sizeof(count))
128✔
847
        goto err_too_short;
×
848
    memcpy(&count, &tpmresp[17], sizeof(count));
128✔
849
    count = be16toh(count);
128✔
850

851
    /* unreasonable number of PCR banks ? */
852
    if (count > 20)
128✔
853
        goto err_num_pcrbanks;
×
854

855
    *all_pcr_banks = g_malloc0(sizeof(char *) * (count + 1));
128✔
856

857
    offset = 19;
128✔
858

859
    for (i = 0; i < count; i++) {
590✔
860
        gchar *n;
462✔
861

862
        if (tpmresp_len < offset + sizeof(bank))
462✔
863
            goto err_too_short;
×
864
        memcpy(&bank, &tpmresp[offset], sizeof(bank));
462✔
865
        bank = be16toh(bank);
462✔
866

867
        if (tpmresp_len < offset + 2 + sizeof(length))
462✔
868
            goto err_too_short;
×
869
        length = tpmresp[offset + 2];
462✔
870

871
        name = get_name_for_bank(bank);
462✔
872
        if (name != NULL)
462✔
873
            n = g_strdup(name);
462✔
874
        else
875
            n = g_strdup_printf("%02x", bank);
×
876

877
        (*all_pcr_banks)[i] = n;
462✔
878

879
        offset += 2 + 1 + length;
462✔
880
    }
881
    return 0;
882

883
err_num_pcrbanks:
×
884
    logerr(self->logfile, "Unreasonable number of PCR banks (%u) returned.\n", count);
×
885
    goto err_exit;
×
886

887
err_too_short:
×
888
    logerr(self->logfile, "Response from TPM2_GetCapability is too short!\n");
×
889

890
err_exit:
×
891
    g_strfreev(*all_pcr_banks);
×
892
    *all_pcr_banks = NULL;
×
893

894
    return 1;
×
895
}
896

897
/* Activate all user-chosen PCR banks and deactivate all others */
898
static int swtpm_tpm2_set_active_pcr_banks(struct swtpm *self, gchar **pcr_banks,
128✔
899
                                           gchar **all_pcr_banks, gchar ***active)
900
{
901
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_PCR_ALLOCATE);
128✔
902
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
128✔
903
    unsigned char pcrselects[6 * 10]; // supports up to 10 PCR banks
128✔
904
    ssize_t pcrselects_len = 0;
128✔
905
    size_t count = 0;
128✔
906
    size_t idx, j;
128✔
907
    uint16_t hashAlg;
128✔
908
    g_autofree unsigned char *req = NULL;
256✔
909
    ssize_t req_len, len;
128✔
910
    int ret;
128✔
911
    uint64_t activated_mask = 0;
128✔
912

913
    for (idx = 0; pcr_banks[idx] != NULL; idx++)
262✔
914
        ;
915
    *active = g_malloc0(sizeof(char *) * (idx + 1));
128✔
916

917
    for (idx = 0; pcr_banks[idx] != NULL; idx++) {
262✔
918
        hashAlg = 0;
252✔
919
        // Is user-chosen pcr_banks[idx] available?
920
        for (j = 0; all_pcr_banks[j] != NULL; j++) {
252✔
921
            if (strcmp(pcr_banks[idx], all_pcr_banks[j]) == 0) {
251✔
922
                hashAlg = get_hashalg_by_bankname(pcr_banks[idx]);
133✔
923
                break;
133✔
924
            }
925
        }
926
        if (hashAlg != 0 && (activated_mask & ((uint64_t)1 << j)) == 0) {
134✔
927
            (*active)[count] = g_strdup(pcr_banks[idx]);
133✔
928
            len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
266✔
929
                         (unsigned char[]){AS2BE(hashAlg), 3, 0xff, 0xff, 0xff} , (size_t)6,
133✔
930
                         NULL);
931
            if (len < 0) {
133✔
932
                logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
933
                return 1;
×
934
            }
935
            pcrselects_len += len;
133✔
936
            count++;
133✔
937
            activated_mask |= ((uint64_t)1 << j);
133✔
938
        }
939
    }
940

941
    if (count == 0) {
128✔
942
        logerr(self->logfile,
1✔
943
               "No PCR banks could be allocated. None of the selected algorithms are supported.\n");
944
        goto error;
1✔
945
    }
946

947
    // disable all the other ones not chosen by the user
948
    for (idx = 0; all_pcr_banks[idx] != NULL; idx++) {
587✔
949
        gboolean found = FALSE;
803✔
950

951
        for (j = 0; pcr_banks[j] != NULL; j++) {
803✔
952
            if (strcmp(pcr_banks[j], all_pcr_banks[idx]) == 0) {
476✔
953
                found = TRUE;
954
                break;
955
            }
956
        }
957
        if (found)
460✔
958
            continue;
133✔
959

960
        /* not found, so not chosen by user */
961
        hashAlg = get_hashalg_by_bankname(all_pcr_banks[idx]);
327✔
962

963
        len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
654✔
964
                     (unsigned char[]){AS2BE(hashAlg), 3, 0, 0, 0}, (size_t)6,
327✔
965
                     NULL);
966
        if (len < 0) {
327✔
967
            logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
968
            goto error;
×
969
        }
970
        pcrselects_len += len;
327✔
971
        count++;
327✔
972
    }
973

974
    req_len = memconcat(&req,
254✔
975
                        &hdr, sizeof(hdr),
976
                        (unsigned char[]){
127✔
977
                             AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))
978
                        }, (size_t)8,
979
                        &authblock, sizeof(authblock),
980
                        (unsigned char[]){AS4BE(count)}, (size_t)4,
127✔
981
                        pcrselects, pcrselects_len,
982
                        NULL);
983
    if (req_len < 0) {
127✔
984
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
985
        goto error;
×
986
    }
987
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
127✔
988

989
    ret = transfer(self, req, req_len, "TPM2_PCR_Allocate", FALSE,
127✔
990
                   NULL, NULL, TPM2_DURATION_SHORT);
991
    if (ret != 0)
127✔
992
        goto error;
×
993

994
    return 0;
995

996
error:
1✔
997
    g_strfreev(*active);
1✔
998
    *active = NULL;
1✔
999

1000
    return 1;
1✔
1001
}
1002

1003
static int swtpm_tpm2_flushcontext(struct swtpm *self, uint32_t handle)
11✔
1004
{
1005
    struct tpm2_flushcontext_req {
11✔
1006
        struct tpm_req_header hdr;
1007
        uint32_t flushHandle;
1008
    } __attribute__((packed)) req = {
11✔
1009
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_FLUSHCONTEXT),
11✔
1010
        .flushHandle = htobe32(handle),
11✔
1011
    };
1012

1013
    return transfer(self, &req, sizeof(req), "TPM2_FlushContext", FALSE,
11✔
1014
                    NULL, NULL, TPM2_DURATION_SHORT);
1015
}
1016

1017
/* Make object at the curr_handler permanent with the perm_handle */
1018
static int swtpm_tpm2_evictcontrol(struct swtpm *self, uint32_t curr_handle, uint32_t perm_handle)
121✔
1019
{
1020
    struct tpm2_evictcontrol_req {
121✔
1021
        struct tpm_req_header hdr;
1022
        uint32_t auth;
1023
        uint32_t objectHandle;
1024
        uint32_t authblockLen;
1025
        struct tpm2_authblock authblock;
1026
        uint32_t persistentHandle;
1027
    } __attribute__((packed)) req = {
121✔
1028
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, sizeof(req), TPM2_CC_EVICTCONTROL),
121✔
1029
        .auth = htobe32(TPM2_RH_OWNER),
121✔
1030
        .objectHandle = htobe32(curr_handle),
121✔
1031
        .authblockLen = htobe32(sizeof(req.authblock)),
121✔
1032
        .authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW),
121✔
1033
        .persistentHandle = htobe32(perm_handle),
121✔
1034
    };
1035

1036
    return transfer(self, &req, sizeof(req), "TPM2_EvictControl", FALSE,
121✔
1037
                    NULL, NULL, TPM2_DURATION_SHORT);
1038
}
1039

1040
static size_t create_symkeydata(const struct pk_params *pk_params,
121✔
1041
                                unsigned char symkeydata[6])
1042
{
1043
    size_t symkeydata_len;
121✔
1044

1045
    if (pk_params->symkey_len) {
121✔
1046
        symkeydata_len = 6;
73✔
1047
        memcpy(symkeydata,
73✔
1048
               ((unsigned char[]){
73✔
1049
                   AS2BE(TPM2_ALG_AES),
1050
                   AS2BE(pk_params->symkey_len),
73✔
1051
                   AS2BE(TPM2_ALG_CFB)
1052
               }),
1053
               symkeydata_len);
1054
    } else {
1055
        symkeydata_len = 2;
48✔
1056
        memcpy(symkeydata,
48✔
1057
               ((unsigned char[]){AS2BE(TPM2_ALG_NULL)}),
48✔
1058
               symkeydata_len);
1059
    }
1060
    return symkeydata_len;
121✔
1061
}
1062

1063
/* Common function to create a TPM 2 primary key.
1064
 *
1065
 * Returns 1 on error with errors having been reported.
1066
 * If tpmresp is != 0 on return then a TPM2 response was received.
1067
 */
1068
static int swtpm_tpm2_createprimary(struct swtpm *self, uint32_t primaryhandle,
121✔
1069
                                    unsigned char *ektemplate, size_t *ektemplate_len,
1070
                                    const unsigned char *public, size_t public_len,
1071
                                    const char *tpm2_function, int duration,
1072
                                    unsigned char *tpmresp, size_t *tpmresp_len,
1073
                                    uint32_t *curr_handle)
1074
{
1075
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY);
121✔
1076
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
121✔
1077
    g_autofree unsigned char *createprimary = NULL;
242✔
1078
    ssize_t createprimary_len;
121✔
1079
    int ret;
121✔
1080

1081
    if (ektemplate) {
121✔
1082
        if (*ektemplate_len < (size_t)public_len) {
110✔
1083
            logerr(self->logfile, "Internal error in %s: Need %zu bytes for ektemplate (rsa) but got only %zu\n",
×
1084
                   __func__, public_len, *ektemplate_len);
1085
            *tpmresp_len = 0;
×
1086
            return 1;
×
1087
        }
1088
        memcpy(ektemplate, public, public_len);
110✔
1089
        *ektemplate_len = public_len;
110✔
1090
    }
1091

1092
    createprimary_len =
121✔
1093
        memconcat(&createprimary,
242✔
1094
                  &hdr, sizeof(hdr),
1095
                  (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8,
121✔
1096
                  &authblock, sizeof(authblock),
1097
                  (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8,
121✔
1098
                  public, public_len,
1099
                  (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
121✔
1100
                  NULL);
1101
    if (createprimary_len < 0) {
121✔
1102
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1103
        *tpmresp_len = 0;
×
1104
        return 1;
×
1105
    }
1106
    ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len);
121✔
1107

1108
    ret = transfer(self, createprimary, createprimary_len, tpm2_function, FALSE,
121✔
1109
                   tpmresp, tpmresp_len, duration);
1110
    if (ret != 0)
121✔
1111
        return 1;
1112

1113
    if (curr_handle) {
121✔
1114
        if (*tpmresp_len < 10 + sizeof(*curr_handle))
121✔
1115
            goto err_too_short;
×
1116
        memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle));
121✔
1117
        *curr_handle = be32toh(*curr_handle);
121✔
1118
    }
1119
    return 0;
1120

1121
err_too_short:
×
1122
    logerr(self->logfile, "Response from %s is too short!\n", tpm2_function);
×
1123
    return 1;
×
1124
}
1125

1126
/* Create an RSA EK */
1127
static int swtpm_tpm2_createprimary_ek_rsa(struct swtpm *self, unsigned int rsa_keysize,
56✔
1128
                                           gboolean allowsigning, gboolean decryption,
1129
                                           uint32_t *curr_handle,
1130
                                           unsigned char *ektemplate, size_t *ektemplate_len,
1131
                                           gchar **ekparam, const gchar **key_description)
1132
{
1133
    const struct ek_params *ekps;
56✔
1134
    struct pk_params pkps;
56✔
1135
    unsigned int keyflags;
56✔
1136
    size_t addlen, off;
56✔
1137

1138
    ekps = get_ek_params(self, KEYALGO_RSA, rsa_keysize);
56✔
1139
    if (!ekps)
56✔
1140
        return 1;
1141
    pkps = ekps->pk;
56✔
1142

1143
    switch (rsa_keysize) {
56✔
1144
    case 2048:
1145
        keyflags = 0;
1146
        addlen = 0;
1147
        break;
1148
    case 3072:
23✔
1149
    case 4096:
1150
        keyflags = 0x40; // userWithAuth
23✔
1151
        addlen = 16;
23✔
1152
        break;
23✔
1153
    default:
1154
        return 1;
1155
    }
1156

1157
    if (allowsigning && decryption) {
56✔
1158
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1159
        // adminWithPolicy, sign, decrypt; restricted CANNOT be set
1160
        keyflags |= 0x000600b2;
7✔
1161
        // symmetric: TPM_ALG_NULL
1162
        pkps.symkey_len = 0;
7✔
1163
        off = 72 + addlen;
7✔
1164
    } else if (allowsigning) {
49✔
1165
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1166
        // adminWithPolicy, sign; restricted CANNOT be set
1167
        keyflags |= 0x000400b2;
17✔
1168
        // symmetric: TPM_ALG_NULL
1169
        pkps.symkey_len = 0;
17✔
1170
        off = 72 + addlen;
17✔
1171
    } else {
1172
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1173
        // adminWithPolicy, restricted, decrypt
1174
        keyflags |= 0x000300b2;
32✔
1175
        // symmetric: TPM_ALG_AES, 128bit or 256bit, TPM_ALG_CFB
1176
        off = 76 + addlen;
32✔
1177
    }
1178

1179
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_ENDORSEMENT, keyflags,
56✔
1180
                                        &pkps, off, curr_handle,
1181
                                        ektemplate, ektemplate_len, ekparam,
1182
                                        key_description);
1183
}
1184

1185
/* Create an RSA key with the given parameters */
1186
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
65✔
1187
                                        const struct pk_params *pk_params,
1188
                                        size_t off, uint32_t *curr_handle,
1189
                                        unsigned char *ektemplate, size_t *ektemplate_len,
1190
                                        gchar **ekparam, const gchar **key_description)
1191
{
1192
    const char *tpm2_function = "TPM2_CreatePrimary(RSA)";
65✔
1193
    g_autofree unsigned char *public = NULL;
130✔
1194
    unsigned char tpmresp[2048];
65✔
1195
    unsigned char symkeydata[6];
65✔
1196
    size_t tpmresp_len = sizeof(tpmresp);
65✔
1197
    size_t symkeydata_len;
65✔
1198
    ssize_t public_len;
65✔
1199
    uint16_t modlen;
65✔
1200
    int ret;
65✔
1201

1202
    if (key_description)
65✔
1203
        *key_description = pk_params->keydescription;
56✔
1204

1205
    symkeydata_len = create_symkeydata(pk_params, symkeydata);
65✔
1206

1207
    public_len =
65✔
1208
        memconcat(&public,
130✔
1209
                  (unsigned char[]) {
65✔
1210
                      AS2BE(TPM2_ALG_RSA), AS2BE(pk_params->hashalg),
65✔
1211
                      AS4BE(keyflags), AS2BE(pk_params->authpolicy_len)
65✔
1212
                  }, (size_t)10,
1213
                  pk_params->authpolicy, pk_params->authpolicy_len,
65✔
1214
                  symkeydata, symkeydata_len,
1215
                  (unsigned char[]) {
65✔
1216
                      AS2BE(TPM2_ALG_NULL), AS2BE(pk_params->keysize * 8), AS4BE(0)
65✔
1217
                  }, (size_t)8,
1218
                  pk_params->nonce, pk_params->nonce_len,
65✔
1219
                  NULL);
1220
    if (public_len < 0) {
65✔
1221
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1222
        return 1;
×
1223
    }
1224
    ret = swtpm_tpm2_createprimary(self, primaryhandle,
130✔
1225
                                   ektemplate, ektemplate_len,
1226
                                   public, public_len,
1227
                                   tpm2_function, pk_params->duration,
65✔
1228
                                   tpmresp, &tpmresp_len, curr_handle);
1229
    if (ret != 0) {
65✔
1230
        if (tpmresp_len >= sizeof(struct tpm_resp_header) &&
×
1231
            be32toh(((struct tpm_resp_header *)tpmresp)->errcode) == 0x2c4) {
×
1232
            /*
1233
             * Error may appear when key size is not supported by profile:
1234
             * value is out of range or is not correct for the context Parameter number 2
1235
             */
1236
            logerr(self->logfile,
×
1237
                   ">> Is RSA-%u supported by the profile? RSA-%u needs 'default-v2'.<<\n",
1238
                   pk_params->keysize * 8,
1239
                   pk_params->keysize * 8);
×
1240
        }
1241
        return 1;
×
1242
    }
1243

1244
    if (tpmresp_len < off + sizeof(modlen))
65✔
1245
         goto err_too_short;
×
1246
    memcpy(&modlen, &tpmresp[off], sizeof(modlen));
65✔
1247
    modlen = be16toh(modlen);
65✔
1248
    if (modlen != pk_params->keysize) {
65✔
1249
        logerr(self->logfile, "Internal error in %s: Getting modulus from wrong offset %zu\n",
×
1250
               __func__, off);
1251
        return 1;
×
1252
    }
1253
    if (ekparam) {
65✔
1254
        if (tpmresp_len < off + 2 + modlen)
56✔
1255
            goto err_too_short;
×
1256
        *ekparam = print_as_hex(&tpmresp[off + 2], modlen);
56✔
1257
    }
1258

1259
    return 0;
1260

1261
err_too_short:
×
1262
    logerr(self->logfile, "Response from %s is too short!\n", tpm2_function);
×
1263
    return 1;
×
1264
}
1265

1266
/* Create an ECC key with the given parameters */
1267
static int swtpm_tpm2_createprimary_ecc(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
56✔
1268
                                        const unsigned char *schemedata, size_t schemedata_len,
1269
                                        const struct pk_params *pk_params,
1270
                                        size_t off, uint32_t *curr_handle,
1271
                                        unsigned char *ektemplate, size_t *ektemplate_len,
1272
                                        gchar **ekparam, const gchar **key_description)
1273
{
1274
    const char *tpm2_function = "TPM2_CreatePrimary(ECC)";
56✔
1275
    g_autofree unsigned char *public = NULL;
112✔
1276
    unsigned char tpmresp[2048];
56✔
1277
    size_t tpmresp_len = sizeof(tpmresp);
56✔
1278
    unsigned char symkeydata[6];
56✔
1279
    uint16_t ksize1, ksize2;
56✔
1280
    size_t symkeydata_len;
56✔
1281
    ssize_t public_len;
56✔
1282
    size_t off2;
56✔
1283
    int ret;
56✔
1284

1285
    if (key_description)
56✔
1286
        *key_description = pk_params->keydescription;
54✔
1287

1288
    symkeydata_len = create_symkeydata(pk_params, symkeydata);
56✔
1289

1290
    public_len =
56✔
1291
        memconcat(&public,
112✔
1292
                  (unsigned char[]){
56✔
1293
                      AS2BE(TPM2_ALG_ECC),
1294
                      AS2BE(pk_params->hashalg),
56✔
1295
                      AS4BE(keyflags),
56✔
1296
                      AS2BE(pk_params->authpolicy_len)
56✔
1297
                  }, (size_t)10,
1298
                  pk_params->authpolicy, pk_params->authpolicy_len,
56✔
1299
                  symkeydata, symkeydata_len,
1300
                  schemedata, schemedata_len,
1301
                  pk_params->nonce, pk_params->nonce_len,
1302
                  pk_params->nonce, pk_params->nonce_len,
56✔
1303
                  NULL);
1304
    if (public_len < 0) {
56✔
1305
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1306
        return 1;
×
1307
    }
1308
    ret = swtpm_tpm2_createprimary(self, primaryhandle,
112✔
1309
                                   ektemplate, ektemplate_len,
1310
                                   public, public_len,
1311
                                   tpm2_function, pk_params->duration,
56✔
1312
                                   tpmresp, &tpmresp_len, curr_handle);
1313
    if (ret != 0)
56✔
1314
        return 1;
1315

1316
    if (tpmresp_len < off + sizeof(ksize1))
56✔
1317
        goto err_too_short;
×
1318
    memcpy(&ksize1, &tpmresp[off], sizeof(ksize1));
56✔
1319
    ksize1 = be16toh(ksize1);
56✔
1320
    off2 = off + 2 + ksize1;
56✔
1321

1322
    if (tpmresp_len < off2 + sizeof(ksize2))
56✔
1323
        goto err_too_short;
×
1324
    memcpy(&ksize2, &tpmresp[off2], sizeof(ksize2));
56✔
1325
    ksize2 = be16toh(ksize2);
56✔
1326

1327
    if (ksize1 != pk_params->keysize || ksize2 != pk_params->keysize) {
56✔
1328
        logerr(self->logfile, "ECC: Getting key parameters from wrong offset\n");
×
1329
        return 1;
×
1330
    }
1331

1332
    if (ekparam) {
56✔
1333
        unsigned char *xparam = &tpmresp[off + 2];
54✔
1334
        unsigned char *yparam = &tpmresp[off2 + 2];
54✔
1335
        if (tpmresp_len < off + 2 + ksize1 || tpmresp_len < off2 + 2 + ksize2)
54✔
1336
            goto err_too_short;
×
1337
        g_autofree gchar *xparam_str = print_as_hex(xparam, ksize1);
108✔
1338
        g_autofree gchar *yparam_str = print_as_hex(yparam, ksize2);
108✔
1339

1340
        *ekparam = g_strdup_printf("x=%s,y=%s,id=%s", xparam_str, yparam_str,
54✔
1341
                                   pk_params->keydescription);
54✔
1342
    }
1343

1344
    return 0;
1345

1346
err_too_short:
×
1347
    logerr(self->logfile, "Response from %s is too short!\n", tpm2_function);
×
1348
    return 1;
×
1349
}
1350

1351
static int swtpm_tpm2_createprimary_spk_ecc(struct swtpm *self,
2✔
1352
                                            unsigned int keyalgo_param,
1353
                                            uint32_t *curr_handle)
1354
{
1355
    uint16_t curveid = (uint16_t)keyalgo_param;
2✔
1356
    const unsigned char schemedata[] = {
2✔
1357
        AS2BE(TPM2_ALG_NULL), AS2BE(curveid), AS2BE(TPM2_ALG_NULL)
1358
    };
1359
    size_t schemedata_len = sizeof(schemedata);
2✔
1360
    // keyflags: fixedTPM, fixedParent, sensitiveDataOrigin, userWithAuth
1361
    //           noDA, restricted, decrypt
1362
    unsigned int keyflags = 0x00030472;
2✔
1363
    const struct spk_params *spks;
2✔
1364
    size_t off = 42;
2✔
1365

1366
    spks = get_spk_params(self, KEYALGO_ECC, keyalgo_param);
2✔
1367
    if (!spks)
2✔
1368
        return 1;
1369

1370
    return swtpm_tpm2_createprimary_ecc(self, TPM2_RH_OWNER, keyflags,
2✔
1371
                                        schemedata, schemedata_len,
1372
                                        &spks->pk, off, curr_handle,
1373
                                        NULL, 0, NULL, NULL);
1374
}
1375

1376
static int swtpm_tpm2_createprimary_spk_rsa(struct swtpm *self, unsigned int rsa_keysize,
9✔
1377
                                            uint32_t *curr_handle)
1378
{
1379
    // keyflags: fixedTPM, fixedParent, sensitiveDataOrigin, userWithAuth
1380
    //           noDA, restricted, decrypt
1381
    unsigned int keyflags = 0x00030472;
9✔
1382
    const unsigned char authpolicy[0] = { };
9✔
1383
    size_t authpolicy_len = sizeof(authpolicy);
9✔
1384
    struct pk_params pk_params = {
9✔
1385
        .authpolicy = authpolicy,
1386
        .authpolicy_len = authpolicy_len,
1387
        .keysize = rsa_keysize / 8,
9✔
1388
        .duration = TPM2_DURATION_LONG,
1389
    };
1390
    size_t off = 44;
9✔
1391

1392
    switch (rsa_keysize) {
9✔
1393
    case 2048:
×
1394
        pk_params.nonce = NONCE_RSA2048;
×
1395
        pk_params.nonce_len = sizeof(NONCE_RSA2048);
×
1396
        pk_params.hashalg = TPM2_ALG_SHA256;
×
1397
        pk_params.symkey_len = 128;
×
1398
        break;
×
1399
    case 3072:
9✔
1400
        pk_params.nonce = NONCE_RSA3072;
9✔
1401
        pk_params.nonce_len = sizeof(NONCE_RSA3072);
9✔
1402
        pk_params.hashalg = TPM2_ALG_SHA384;
9✔
1403
        pk_params.symkey_len = 256;
9✔
1404
        break;
9✔
1405
    case 4096:
×
1406
        pk_params.nonce = NONCE_RSA4096;
×
1407
        pk_params.nonce_len = sizeof(NONCE_RSA4096);
×
1408
        pk_params.hashalg = TPM2_ALG_SHA384;
×
1409
        pk_params.symkey_len = 256;
×
1410
        break;
×
1411
    default:
1412
        return 1;
1413
    }
1414

1415
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_OWNER, keyflags,
9✔
1416
                                        &pk_params, off, curr_handle,
1417
                                        NULL, 0, NULL, NULL);
1418
}
1419

1420
/* Create either an ECC or RSA storage primary key (deprecated) */
1421
static int swtpm_tpm2_create_spk(struct swtpm *self, enum keyalgo keyalgo,
11✔
1422
                                 unsigned int keyalgo_param)
1423
{
1424
    int ret;
11✔
1425
    uint32_t curr_handle;
11✔
1426

1427
    switch (keyalgo) {
11✔
1428
    case KEYALGO_ECC:
2✔
1429
        ret = swtpm_tpm2_createprimary_spk_ecc(self, keyalgo_param, &curr_handle);
2✔
1430
        break;
2✔
1431
    case KEYALGO_RSA:
9✔
1432
        ret = swtpm_tpm2_createprimary_spk_rsa(self, keyalgo_param, &curr_handle);
9✔
1433
        break;
9✔
1434
    default:
1435
        ret = 1;
1436
    }
1437

1438
    if (ret != 0)
11✔
1439
        return 1;
×
1440

1441
    ret = swtpm_tpm2_evictcontrol(self, curr_handle, TPM2_SPK_HANDLE);
11✔
1442
    if (ret == 0)
11✔
1443
        logit(self->logfile,
11✔
1444
              "Successfully created storage primary key with handle 0x%x.\n", TPM2_SPK_HANDLE);
1445

1446
    ret = swtpm_tpm2_flushcontext(self, curr_handle);
11✔
1447
    if (ret != 0) {
11✔
1448
        logerr(self->logfile, "Could not flush storage primary key.\n");
×
1449
        ret = 1;
×
1450
    }
1451

1452
    return ret;
1453
}
1454

1455
/* Create an ECC EK key that may be allowed to sign and/or decrypt */
1456
static int swtpm_tpm2_createprimary_ek_ecc(struct swtpm *self, const struct ek_params *ekps,
54✔
1457
                                           gboolean allowsigning, gboolean decryption,
1458
                                           uint32_t *curr_handle,
1459
                                           unsigned char *ektemplate, size_t *ektemplate_len,
1460
                                           gchar **ekparam, const char **key_description)
1461
{
1462
    const unsigned char schemedata[] = {
54✔
1463
        AS2BE(TPM2_ALG_NULL), AS2BE(ekps->pk.keyalgo_param), AS2BE(TPM2_ALG_NULL)
54✔
1464
    };
1465
    size_t schemedata_len = sizeof(schemedata);
54✔
1466
    struct pk_params pkps;
54✔
1467
    unsigned int keyflags;
54✔
1468
    size_t off;
54✔
1469
    int ret;
54✔
1470

1471
    pkps = ekps->pk;
54✔
1472

1473
    switch (pkps.keyalgo_param) {
54✔
1474
    case TPM2_ECC_NIST_P256:
1475
        off = 0x4a;
1476
        keyflags = 0;
1477
        break;
1478
    case TPM2_ECC_NIST_P384:
1479
        off = 0x5a;
1480
        keyflags = 0x40; // userWithAuth (high range)
1481
        break;
1482
    case TPM2_ECC_NIST_P521:
1483
        off = 0x6a;
1484
        keyflags = 0x40; // userWithAuth (high range)
1485
        break;
1486
    default:
1487
        return 1;
1488
    }
1489

1490
    if (allowsigning && decryption) {
54✔
1491
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1492
        // userWithAuth, adminWithPolicy, sign, decrypt; restricted CANNOT be set
1493
        keyflags |= 0x000600b2;
7✔
1494
        // symmetric: TPM_ALG_NULL
1495
        pkps.symkey_len = 0;
7✔
1496
        off -= 4;
7✔
1497
    } else if (allowsigning) {
47✔
1498
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1499
        // userWithAuth, adminWithPolicy, sign; restricted CANNOT be set
1500
        keyflags |= 0x000400b2;
17✔
1501
        // symmetric: TPM_ALG_NULL
1502
        pkps.symkey_len = 0;
17✔
1503
        off -= 4;
17✔
1504
    } else {
1505
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1506
        // userWithAuth, adminWithPolicy, restricted, decrypt
1507
        keyflags |= 0x000300b2;
30✔
1508
        // symmetric: TPM_ALG_AES, 256bit, TPM_ALG_CFB
1509
    }
1510

1511
    ret = swtpm_tpm2_createprimary_ecc(self, TPM2_RH_ENDORSEMENT, keyflags,
54✔
1512
                                       schemedata, schemedata_len,
1513
                                       &pkps, off, curr_handle,
1514
                                       ektemplate, ektemplate_len, ekparam,
1515
                                       key_description);
1516
    if (ret != 0)
54✔
1517
       logerr(self->logfile, "%s failed\n", __func__);
×
1518

1519
    return ret;
1520
}
1521

1522
/* Create an ECC or RSA EK */
1523
static int swtpm_tpm2_create_ek(struct swtpm *self, enum keyalgo keyalgo, unsigned int keyalgo_param,
110✔
1524
                                gboolean allowsigning, gboolean decryption, gboolean lock_nvram,
1525
                                gchar **ekparam, const  gchar **key_description)
1526
{
1527
    unsigned char ektemplate[512];
110✔
1528
    size_t ektemplate_len = sizeof(ektemplate);
110✔
1529
    const struct ek_params *ekps;
110✔
1530
    uint32_t curr_handle;
110✔
1531
    int ret;
110✔
1532

1533
    ekps = get_ek_params(self, keyalgo, keyalgo_param);
110✔
1534
    if (!ekps)
110✔
1535
        return 1;
1536

1537
    switch (keyalgo) {
110✔
1538
    case KEYALGO_ECC:
54✔
1539
        ret = swtpm_tpm2_createprimary_ek_ecc(self, ekps,
54✔
1540
                                              allowsigning, decryption,
1541
                                              &curr_handle,
1542
                                              ektemplate, &ektemplate_len,
1543
                                              ekparam, key_description);
1544
        break;
54✔
1545
    case KEYALGO_RSA:
56✔
1546
        ret = swtpm_tpm2_createprimary_ek_rsa(self, keyalgo_param, allowsigning,
56✔
1547
                                              decryption, &curr_handle,
1548
                                              ektemplate, &ektemplate_len, ekparam,
1549
                                              key_description);
1550
        break;
56✔
1551
    default:
1552
        ret = 1;
1553
    }
1554

1555
    if (ret == 0)
110✔
1556
        ret = swtpm_tpm2_evictcontrol(self, curr_handle, ekps->ek_handle);
110✔
1557
    if (ret != 0) {
110✔
1558
        logerr(self->logfile, "create_ek failed: 0x%x\n", ret);
×
1559
        return 1;
×
1560
    }
1561

1562
    logit(self->logfile, "Successfully created %s EK with handle 0x%x.\n",
110✔
1563
          ekps->keytype, ekps->ek_handle);
110✔
1564

1565
    if (allowsigning) {
110✔
1566
        uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE | \
48✔
1567
                TPMA_NV_AUTHREAD | \
1568
                TPMA_NV_OWNERREAD | \
1569
                TPMA_NV_PPREAD | \
1570
                TPMA_NV_PPWRITE | \
1571
                TPMA_NV_NO_DA | \
1572
                TPMA_NV_WRITEDEFINE;
1573
        ret = swtpm_tpm2_write_nvram(self, ekps->nvindex_template, nvindexattrs,
48✔
1574
                                     ektemplate, ektemplate_len,
1575
                                     lock_nvram, "EK template");
1576
        if (ret == 0)
48✔
1577
            logit(self->logfile,
48✔
1578
                  "Successfully created NVRAM area 0x%x for %s EK template.\n",
1579
                  ekps->nvindex_template, ekps->keytype);
48✔
1580
    }
1581

1582
    return ret;
1583
}
1584

1585
static int swtpm_tpm2_nvdefinespace(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
193✔
1586
                                    uint16_t data_len)
1587
{
1588
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_DEFINESPACE);
193✔
1589
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
193✔
1590
    g_autofree unsigned char *nvpublic = NULL;
386✔
1591
    ssize_t nvpublic_len;
193✔
1592
    g_autofree unsigned char *req = NULL;
193✔
1593
    ssize_t req_len;
193✔
1594

1595
    nvpublic_len = memconcat(&nvpublic,
386✔
1596
                             (unsigned char[]){
193✔
1597
                                 AS4BE(nvindex), AS2BE(TPM2_ALG_SHA256), AS4BE(nvindexattrs),
193✔
1598
                                 AS2BE(0), AS2BE(data_len)}, (size_t)14,
1599
                             NULL);
1600
    if (nvpublic_len < 0) {
193✔
1601
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1602
        return 1;
×
1603
    }
1604

1605
    req_len = memconcat(&req,
386✔
1606
                        &hdr, sizeof(hdr),
1607
                        (unsigned char[]){AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))}, (size_t)8,
193✔
1608
                        &authblock, sizeof(authblock),
1609
                        (unsigned char[]){AS2BE(0), AS2BE(nvpublic_len)}, (size_t)4,
193✔
1610
                        nvpublic, nvpublic_len,
1611
                        NULL);
1612
    if (req_len < 0) {
193✔
1613
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1614
        return 1;
×
1615
    }
1616

1617
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
193✔
1618

1619
    return transfer(self, req, req_len, "TPM2_NV_DefineSpace", FALSE,
193✔
1620
                    NULL, NULL, TPM2_DURATION_SHORT);
1621
}
1622

1623
/* Write the data into the given NVIndex */
1624
static int swtpm_tpm2_nv_write(struct swtpm *self, uint32_t nvindex,
193✔
1625
                               const unsigned char *data, size_t data_len)
1626
{
1627
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITE);
193✔
1628
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
193✔
1629
    g_autofree unsigned char *req = NULL;
386✔
1630
    ssize_t req_len;
193✔
1631
    size_t offset = 0, txlen;
193✔
1632
    int ret;
193✔
1633

1634
    while (offset < data_len) {
392✔
1635
        txlen = min(data_len - offset, 1024);
199✔
1636

1637
        g_free(req);
199✔
1638
        req_len = memconcat(&req,
398✔
1639
                            &hdr, sizeof(hdr),
1640
                            (unsigned char[]){
199✔
1641
                                AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
199✔
1642
                            }, (size_t)12,
1643
                            &authblock, sizeof(authblock),
1644
                            (unsigned char[]){AS2BE(txlen)}, (size_t)2,
199✔
1645
                            &data[offset], txlen,
1646
                            (unsigned char[]){AS2BE(offset)}, (size_t)2,
199✔
1647
                            NULL);
1648
        if (req_len < 0) {
199✔
1649
            logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1650
            return 1;
×
1651
        }
1652
        ((struct tpm_req_header *)req)->size = htobe32(req_len);
199✔
1653

1654
        ret = transfer(self, req, req_len, "TPM2_NV_Write", FALSE,
199✔
1655
                       NULL, NULL, TPM2_DURATION_SHORT);
1656
        if (ret != 0)
199✔
1657
            return 1;
1658

1659
        offset += txlen;
199✔
1660
    }
1661
    return 0;
1662
}
1663

1664
static int swtpm_tpm2_nv_writelock(struct swtpm *self, uint32_t nvindex)
12✔
1665
{
1666
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITELOCK);
12✔
1667
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
12✔
1668
    g_autofree unsigned char *req;
24✔
1669
    ssize_t req_len;
12✔
1670

1671
    req_len = memconcat(&req,
24✔
1672
                        &hdr, sizeof(hdr),
1673
                        (unsigned char[]){
12✔
1674
                           AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
12✔
1675
                        }, (size_t)12,
1676
                        &authblock, sizeof(authblock),
1677
                        NULL);
1678
    if (req_len < 0) {
12✔
1679
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1680
        return 1;
×
1681
    }
1682

1683
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
12✔
1684

1685
    return transfer(self, req, req_len, "TPM2_NV_WriteLock", FALSE,
12✔
1686
                    NULL, NULL, TPM2_DURATION_SHORT);
1687
}
1688

1689
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
193✔
1690
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
1691
                                  const char *certtype)
1692
{
1693
    int ret = swtpm_tpm2_nvdefinespace(self, nvindex, nvindexattrs, data_len);
193✔
1694
    if (ret != 0) {
193✔
1695
        logerr(self->logfile, "Could not create NVRAM area 0x%x for %s.\n", nvindex, certtype);
×
1696
        return 1;
×
1697
    }
1698

1699
    ret = swtpm_tpm2_nv_write(self, nvindex, data, data_len);
193✔
1700
    if (ret != 0) {
193✔
1701
        logerr(self->logfile,
×
1702
               "Could not write %s into NVRAM area 0x%x.\n", certtype, nvindex);
1703
        return 1;
×
1704
    }
1705

1706
    if (lock_nvram) {
193✔
1707
        ret = swtpm_tpm2_nv_writelock(self, nvindex);
12✔
1708
        if (ret != 0) {
12✔
1709
            logerr(self->logfile, "Could not lock EK template NVRAM area 0x%x.\n", nvindex);
×
1710
            return 1;
×
1711
        }
1712
    }
1713

1714
    return 0;
1715
}
1716

1717
static int swtpm_tpm2_write_cert_nvram(struct swtpm *self, uint32_t nvindex,
145✔
1718
                                       uint32_t nvindexattrs,
1719
                                       const unsigned char *data, size_t data_len,
1720
                                       gboolean lock_nvram, const char *keytype,
1721
                                       const char *certtype)
1722
{
1723
    int ret;
145✔
1724

1725
    ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, data, data_len, lock_nvram,
145✔
1726
                                 certtype);
1727
    if (ret == 0)
145✔
1728
        logit(self->logfile,
145✔
1729
              "Successfully created NVRAM area 0x%x for %s%s.\n",
1730
              nvindex, keytype, certtype);
1731

1732
    return ret;
145✔
1733
}
1734

1735
/* Write the platform certificate into an NVRAM area */
1736
static int swtpm_tpm2_write_ek_cert_nvram(struct swtpm *self, enum keyalgo keyalgo,
96✔
1737
                                           unsigned int keyalgo_param, gboolean lock_nvram,
1738
                                           const unsigned char *data, size_t data_len)
1739
{
1740
    g_autofree gchar *keytype = NULL;
192✔
1741
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
96✔
1742
            TPMA_NV_AUTHREAD |
1743
            TPMA_NV_OWNERREAD |
1744
            TPMA_NV_PPREAD |
1745
            TPMA_NV_PPWRITE |
1746
            TPMA_NV_NO_DA |
1747
            TPMA_NV_WRITEDEFINE;
1748
    const struct ek_params *ekps;
96✔
1749

1750
    ekps = get_ek_params(self, keyalgo, keyalgo_param);
96✔
1751
    if (!ekps)
96✔
1752
        return 1;
1753

1754
    keytype = g_strdup_printf("%s ", ekps->keytype);
96✔
1755

1756
    return swtpm_tpm2_write_cert_nvram(self, ekps->nvindex_ekcert,
96✔
1757
                                       nvindexattrs, data, data_len,
1758
                                       lock_nvram, keytype, "EK certificate");
1759
}
1760

1761
static int swtpm_tpm2_write_platform_cert_nvram(struct swtpm *self, gboolean lock_nvram,
49✔
1762
                                                const unsigned char *data, size_t data_len)
1763
{
1764
    uint32_t nvindex = TPM2_NV_INDEX_PLATFORMCERT;
49✔
1765
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
49✔
1766
            TPMA_NV_AUTHREAD |
1767
            TPMA_NV_OWNERREAD |
1768
            TPMA_NV_PPREAD |
1769
            TPMA_NV_PPWRITE |
1770
            TPMA_NV_NO_DA |
1771
            TPMA_NV_WRITEDEFINE;
1772

1773
    return swtpm_tpm2_write_cert_nvram(self, nvindex, nvindexattrs, data, data_len,
49✔
1774
                                       lock_nvram, "", "platform certificate");
1775
}
1776

1777
static char *swtpm_tpm2_get_active_profile(struct swtpm *self)
127✔
1778
{
1779
    gchar *result = NULL;
127✔
1780

1781
    if (do_cmd_get_info(self, SWTPM_INFO_ACTIVE_PROFILE, &result))
127✔
1782
        return NULL;
1783
    return result;
122✔
1784
}
1785

1786
static const struct swtpm2_ops swtpm_tpm2_ops = {
1787
    .shutdown = swtpm_tpm2_shutdown,
1788
    .create_spk = swtpm_tpm2_create_spk,
1789
    .create_ek = swtpm_tpm2_create_ek,
1790
    .get_all_pcr_banks = swtpm_tpm2_get_all_pcr_banks,
1791
    .set_active_pcr_banks = swtpm_tpm2_set_active_pcr_banks,
1792
    .write_ek_cert_nvram = swtpm_tpm2_write_ek_cert_nvram,
1793
    .write_platform_cert_nvram = swtpm_tpm2_write_platform_cert_nvram,
1794
    .get_active_profile = swtpm_tpm2_get_active_profile,
1795
};
1796

1797
/*
1798
 * TPM 1.2 support
1799
 */
1800
#define TPM_TAG_RQU_COMMAND       0x00c1
1801
#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
1802

1803
#define TPM_ORD_OIAP                     0x0000000A
1804
#define TPM_ORD_TAKE_OWNERSHIP           0x0000000D
1805
#define TPM_ORD_PHYSICAL_ENABLE          0x0000006F
1806
#define TPM_ORD_PHYSICAL_SET_DEACTIVATED 0x00000072
1807
#define TPM_ORD_NV_DEFINE_SPACE          0x000000CC
1808
#define TPM_ORD_NV_WRITE_VALUE           0x000000CD
1809
#define TSC_ORD_PHYSICAL_PRESENCE        0x4000000A
1810

1811
#define TPM_ST_CLEAR 0x0001
1812

1813
#define TPM_PHYSICAL_PRESENCE_CMD_ENABLE  0x0020
1814
#define TPM_PHYSICAL_PRESENCE_PRESENT     0x0008
1815

1816
#define TPM_ALG_RSA 0x00000001
1817

1818
#define TPM_KEY_STORAGE 0x0011
1819

1820
#define TPM_AUTH_ALWAYS 0x01
1821

1822
#define TPM_PID_OWNER  0x0005
1823

1824
#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003
1825
#define TPM_SS_NONE 0x0001
1826

1827
#define TPM_TAG_PCR_INFO_LONG   0x0006
1828
#define TPM_TAG_NV_ATTRIBUTES   0x0017
1829
#define TPM_TAG_NV_DATA_PUBLIC  0x0018
1830
#define TPM_TAG_KEY12           0x0028
1831

1832
#define TPM_LOC_ZERO   0x01
1833
#define TPM_LOC_ALL    0x1f
1834

1835
#define TPM_NV_INDEX_D_BIT        0x10000000
1836
#define TPM_NV_INDEX_EKCERT       0xF000
1837
#define TPM_NV_INDEX_PLATFORMCERT 0xF002
1838

1839
#define TPM_NV_INDEX_LOCK 0xFFFFFFFF
1840

1841
#define TPM_NV_PER_OWNERREAD   0x00020000
1842
#define TPM_NV_PER_OWNERWRITE  0x00000002
1843

1844
#define TPM_ET_OWNER 0x02
1845
#define TPM_ET_NV    0x0b
1846

1847
#define TPM_KH_EK    0x40000006
1848

1849
#define TPM_DURATION_SHORT  ( 2000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
1850
#define TPM_DURATION_MEDIUM ( 7500 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
1851
#define TPM_DURATION_LONG   (15000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
1852

1853
static int swtpm_tpm12_tsc_physicalpresence(struct swtpm *self, uint16_t physicalpresence)
52✔
1854
{
1855
    struct tpm12_tsc_physicalpresence {
52✔
1856
        struct tpm_req_header hdr;
1857
        uint16_t pp;
1858
    } req = {
52✔
1859
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TSC_ORD_PHYSICAL_PRESENCE),
52✔
1860
        .pp = htobe16(physicalpresence),
52✔
1861
    };
1862

1863
    /* use medium duration to avoid t/o on busy system */
1864
    return transfer(self, &req, sizeof(req), "TSC_PhysicalPresence", FALSE,
52✔
1865
                    NULL, NULL, TPM_DURATION_MEDIUM);
1866
}
1867

1868
static int swtpm_tpm12_physical_enable(struct swtpm *self)
26✔
1869
{
1870
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_ENABLE);
26✔
1871

1872
    return transfer(self, &req, sizeof(req), "TPM_PhysicalEnable", FALSE,
26✔
1873
                    NULL, NULL, TPM_DURATION_SHORT);
1874
}
1875

1876
static int swtpm_tpm12_physical_set_deactivated(struct swtpm *self, uint8_t state)
26✔
1877
{
1878
    struct tpm12_tsc_physical_set_deactivated {
26✔
1879
        struct tpm_req_header hdr;
1880
        uint8_t state;
1881
    } req = {
26✔
1882
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_SET_DEACTIVATED),
26✔
1883
        .state = state,
1884
    };
1885

1886
    return transfer(self, &req, sizeof(req), "TSC_PhysicalSetDeactivated", FALSE,
26✔
1887
                    NULL, NULL, TPM_DURATION_SHORT);
1888
}
1889

1890
/* Initialize the TPM1.2 */
1891
static int swtpm_tpm12_run_swtpm_bios(struct swtpm *self)
26✔
1892
{
1893
    if (swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_CMD_ENABLE) ||
52✔
1894
        swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_PRESENT) ||
52✔
1895
        swtpm_tpm12_physical_enable(self) ||
52✔
1896
        swtpm_tpm12_physical_set_deactivated(self, 0))
26✔
1897
        return 1;
×
1898

1899
    return 0;
1900
}
1901

1902
static int swptm_tpm12_create_endorsement_keypair(struct swtpm *self,
19✔
1903
                                                  gchar **pubek, size_t *pubek_len)
1904
{
1905
    unsigned char req[] = {
19✔
1906
        0x00, 0xc1, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x78, 0x38, 0xf0, 0x30, 0x81, 0x07, 0x2b,
1907
        0x0c, 0xa9, 0x10, 0x98, 0x08, 0xc0, 0x4B, 0x05, 0x11, 0xc9, 0x50, 0x23, 0x52, 0xc4, 0x00, 0x00,
1908
        0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1909
        0x00, 0x02, 0x00, 0x00, 0x00, 0x00
1910
    };
1911
    unsigned char tpmresp[512];
19✔
1912
    size_t tpmresp_len = sizeof(tpmresp);
19✔
1913
    uint32_t length;
19✔
1914
    int ret;
19✔
1915

1916
    ret = transfer(self, &req, sizeof(req), "TPM_CreateEndorsementKeyPair", FALSE,
19✔
1917
                   &tpmresp, &tpmresp_len, TPM_DURATION_LONG);
1918
    if (ret != 0)
19✔
1919
        return 1;
1920

1921
    if (tpmresp_len < 34 + sizeof(length))
19✔
1922
        goto err_too_short;
×
1923
    memcpy(&length, &tpmresp[34], sizeof(length));
19✔
1924
    length = be32toh(length);
19✔
1925
    if (length != 256) {
19✔
1926
        logerr(self->logfile, "Offset to EK Public key is wrong.\n");
×
1927
        return 1;
×
1928
    }
1929

1930
    *pubek_len = 256;
19✔
1931
    if (tpmresp_len < 38 + *pubek_len)
19✔
1932
        goto err_too_short;
×
1933
    *pubek = g_malloc(256);
19✔
1934
    memcpy(*pubek, &tpmresp[38], *pubek_len);
19✔
1935

1936
    return 0;
19✔
1937

1938
err_too_short:
×
1939
    logerr(self->logfile, "Response from TPM_CreateEndorsementKeyPair is too short!\n");
×
1940
    return 1;
×
1941
}
1942

1943
/* Create an OIAP session */
1944
static int swtpm_tpm12_oiap(struct swtpm *self, uint32_t *authhandle, unsigned char nonce_even[SHA_DIGEST_LENGTH])
9✔
1945
{
1946
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_OIAP);
9✔
1947
    unsigned char tpmresp[64];
9✔
1948
    size_t tpmresp_len = sizeof(tpmresp);
9✔
1949
    int ret;
9✔
1950

1951
    ret = transfer(self, &req, sizeof(req), "TPM_OIAP", FALSE,
9✔
1952
                   &tpmresp, &tpmresp_len, TPM_DURATION_SHORT);
1953
    if (ret != 0)
9✔
1954
        return ret;
1955

1956
    if (tpmresp_len < 10 + sizeof(*authhandle) || tpmresp_len < 14 + SHA_DIGEST_LENGTH)
9✔
1957
        goto err_too_short;
×
1958
    memcpy(authhandle, &tpmresp[10], sizeof(*authhandle));
9✔
1959
    *authhandle = be32toh(*authhandle);
9✔
1960
    memcpy(nonce_even, &tpmresp[14], SHA_DIGEST_LENGTH);
9✔
1961

1962
    return 0;
9✔
1963

1964
err_too_short:
×
1965
    logerr(self->logfile, "Response from TPM_OIAP is too short!\n");
×
1966
    return 1;
×
1967
}
1968

1969
static int swtpm_tpm12_take_ownership(struct swtpm *self, const unsigned char ownerpass_digest[SHA_DIGEST_LENGTH],
9✔
1970
                                      const unsigned char srkpass_digest[SHA_DIGEST_LENGTH],
1971
                                      const unsigned char *pubek, size_t pubek_len)
1972
{
1973
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_AUTH1_COMMAND, 0, TPM_ORD_TAKE_OWNERSHIP);
9✔
1974
    EVP_PKEY *pkey = NULL;
9✔
1975
    EVP_PKEY_CTX *ctx = NULL;
9✔
1976
    BIGNUM *exp = BN_new();
9✔
1977
    BIGNUM *mod = NULL;
9✔
1978
#if OPENSSL_VERSION_NUMBER < 0x30000000L
1979
    RSA *rsakey = RSA_new();
1980
#endif
1981
    int ret = 1;
9✔
1982
    const EVP_MD *sha1 = EVP_sha1();
9✔
1983
    g_autofree unsigned char *enc_owner_auth = g_malloc(pubek_len);
9✔
1984
    size_t enc_owner_auth_len = pubek_len;
9✔
1985
    g_autofree unsigned char *enc_srk_auth = g_malloc(pubek_len);
18✔
1986
    size_t enc_srk_auth_len = pubek_len;
9✔
1987
    uint32_t auth_handle;
9✔
1988
    unsigned char nonce_even[SHA_DIGEST_LENGTH];
9✔
1989
    unsigned char nonce_odd[SHA_DIGEST_LENGTH] = {1, 2, 3, 4, 5, 6, };
9✔
1990
    g_autofree unsigned char *tpm_rsa_key_parms = NULL;
9✔
1991
    ssize_t tpm_rsa_key_parms_len;
9✔
1992
    g_autofree unsigned char *tpm_key_parms = NULL;
9✔
1993
    ssize_t tpm_key_parms_len;
9✔
1994
    g_autofree unsigned char *tpm_key12 = NULL;
9✔
1995
    ssize_t tpm_key12_len;
9✔
1996
    g_autofree unsigned char *in_auth_setup_params = NULL;
9✔
1997
    ssize_t in_auth_setup_params_len;
9✔
1998
    g_autofree unsigned char *macinput = NULL;
9✔
1999
    ssize_t macinput_len;
9✔
2000
    unsigned char in_param_digest[SHA_DIGEST_LENGTH];
9✔
2001
    unsigned char owner_auth[SHA_DIGEST_LENGTH];
9✔
2002
    unsigned int owner_auth_len = sizeof(owner_auth);
9✔
2003
    uint8_t continue_auth_session = 0;
9✔
2004
    unsigned char req[1024];
9✔
2005
    ssize_t req_len, len;
9✔
2006
    struct tpm_req_header *trh;
9✔
2007

2008
    mod = BN_bin2bn((const unsigned char *)pubek, pubek_len, NULL);
9✔
2009
    if (exp == NULL || mod == NULL ||
18✔
2010
        BN_hex2bn(&exp, "10001") == 0) {
9✔
2011
        logerr(self->logfile, "Could not create public RSA key!\n");
×
2012
        goto error_free_bn;
×
2013
    }
2014

2015
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
2016
    ctx = EVP_PKEY_CTX_new_from_name(NULL, "rsa", NULL);
9✔
2017
    if (ctx != NULL) {
9✔
2018
        OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
9✔
2019
        OSSL_PARAM *params;
9✔
2020

2021
        if (bld == NULL ||
18✔
2022
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, exp) != 1 ||
18✔
2023
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, mod) != 1 ||
9✔
2024
            (params = OSSL_PARAM_BLD_to_param(bld)) == NULL) {
9✔
2025
            OSSL_PARAM_BLD_free(bld);
×
2026
            goto error_free_bn;
×
2027
        }
2028
        OSSL_PARAM_BLD_free(bld);
9✔
2029

2030
        if (EVP_PKEY_fromdata_init(ctx) != 1 ||
18✔
2031
            EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) != 1) {
9✔
2032
            logerr(self->logfile, "Could not set pkey parameters!\n");
×
2033
            OSSL_PARAM_free(params);
×
2034
            goto error_free_bn;
×
2035
        }
2036
        OSSL_PARAM_free(params);
9✔
2037

2038
        EVP_PKEY_CTX_free(ctx);
9✔
2039
    } else {
2040
        logerr(self->logfile, "Could not create key creation context!\n");
×
2041
        goto error_free_bn;
×
2042
    }
2043
    ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
9✔
2044
    if (ctx == NULL)
9✔
2045
        goto error_free_bn;
×
2046
#else
2047
    pkey = EVP_PKEY_new();
2048
    if (pkey == NULL) {
2049
        logerr(self->logfile, "Could not allocate pkey!\n");
2050
        goto error_free_bn;
2051
    }
2052

2053
# if OPENSSL_VERSION_NUMBER < 0x10100000
2054
    rsakey->n = mod;
2055
    rsakey->e = exp;
2056
# else
2057
    if (RSA_set0_key(rsakey, mod, exp, NULL) != 1) {
2058
        logerr(self->logfile, "Could not create public RSA key!\n");
2059
        goto error_free_bn;
2060
    }
2061
# endif
2062
    if (EVP_PKEY_assign_RSA(pkey, rsakey) != 1) {
2063
        logerr(self->logfile, "Could not create public RSA key!\n");
2064
        goto error_free_pkey_and_rsa;
2065
    }
2066

2067
    ctx = EVP_PKEY_CTX_new(pkey, NULL);
2068
    if (ctx == NULL)
2069
        goto error_free_pkey;
2070
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
2071

2072
    if (EVP_PKEY_encrypt_init(ctx) < 1 ||
18✔
2073
        EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) < 1 ||
18✔
2074
        EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sha1) < 1 ||
18✔
2075
        EVP_PKEY_CTX_set_rsa_oaep_md(ctx, sha1) < 1 ||
18✔
2076
        EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, g_strdup("TCPA"), 4) < 1 ||
18✔
2077
        EVP_PKEY_encrypt(ctx, enc_owner_auth, &enc_owner_auth_len,
9✔
2078
                         ownerpass_digest, SHA_DIGEST_LENGTH) < 1||
9✔
2079
        EVP_PKEY_encrypt(ctx, enc_srk_auth, &enc_srk_auth_len,
9✔
2080
                         srkpass_digest, SHA_DIGEST_LENGTH) < 1) {
2081
        logerr(self->logfile, "Internal error in %s: encryption failed\n", __func__);
×
2082
        goto error;
×
2083
    }
2084
    ret = swtpm_tpm12_oiap(self, &auth_handle, nonce_even);
9✔
2085
    if (ret != 0)
9✔
2086
        goto error;
×
2087

2088
    tpm_rsa_key_parms_len = memconcat(&tpm_rsa_key_parms,
18✔
2089
                                      (unsigned char[]){
9✔
2090
                                          AS4BE(2048), AS4BE(2), AS4BE(0)
2091
                                      }, (size_t)12,
2092
                                      NULL);
2093
    if (tpm_rsa_key_parms_len < 0) {
9✔
2094
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2095
        goto error;
×
2096
    }
2097

2098
    tpm_key_parms_len = memconcat(&tpm_key_parms,
18✔
2099
                                  (unsigned char[]){
9✔
2100
                                      AS4BE(TPM_ALG_RSA),
2101
                                      AS2BE(TPM_ES_RSAESOAEP_SHA1_MGF1),
2102
                                      AS2BE(TPM_SS_NONE),
2103
                                      AS4BE(tpm_rsa_key_parms_len)}, (size_t)12,
9✔
2104
                                  tpm_rsa_key_parms, tpm_rsa_key_parms_len,
2105
                                  NULL);
2106
    if (tpm_key_parms_len < 0) {
9✔
2107
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2108
        goto error;
×
2109
    }
2110

2111
    tpm_key12_len = memconcat(&tpm_key12,
18✔
2112
                              (unsigned char[]){
9✔
2113
                                  AS2BE(TPM_TAG_KEY12), AS2BE(0),
2114
                                  AS2BE(TPM_KEY_STORAGE), AS4BE(0), TPM_AUTH_ALWAYS
2115
                              }, (size_t)11,
2116
                              tpm_key_parms, tpm_key_parms_len,
2117
                              (unsigned char[]){AS4BE(0), AS4BE(0), AS4BE(0)}, (size_t)12,
9✔
2118
                              NULL);
2119
    if (tpm_key12_len < 0) {
9✔
2120
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2121
        goto error;
×
2122
    }
2123

2124
    req_len = concat(req, sizeof(req),
18✔
2125
                     &hdr, sizeof(hdr),
2126
                     (unsigned char[]){AS2BE(TPM_PID_OWNER), AS4BE(enc_owner_auth_len)}, (size_t)6,
9✔
2127
                     enc_owner_auth, enc_owner_auth_len,
2128
                     (unsigned char[]){AS4BE(enc_srk_auth_len)}, (size_t)4,
9✔
2129
                     enc_srk_auth, enc_srk_auth_len,
2130
                     tpm_key12, tpm_key12_len,
2131
                     NULL);
2132
    if (req_len < 0) {
9✔
2133
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
2134
        goto error;
×
2135
    }
2136
    SHA1(&req[6], req_len - 6, in_param_digest);
9✔
2137

2138
    in_auth_setup_params_len = memconcat(&in_auth_setup_params,
9✔
2139
                                         nonce_even, sizeof(nonce_even),
2140
                                         nonce_odd, sizeof(nonce_odd),
2141
                                         &continue_auth_session, (size_t)1,
2142
                                         NULL);
2143
    if (in_auth_setup_params_len < 0) {
9✔
2144
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2145
        goto error;
×
2146
    }
2147

2148
    macinput_len = memconcat(&macinput,
9✔
2149
                             in_param_digest, sizeof(in_param_digest),
2150
                             in_auth_setup_params, in_auth_setup_params_len,
2151
                             NULL);
2152
    if (macinput_len < 0) {
9✔
2153
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2154
        goto error;
×
2155
    }
2156

2157
    HMAC(sha1, ownerpass_digest, SHA_DIGEST_LENGTH, macinput, macinput_len,
9✔
2158
         owner_auth, &owner_auth_len);
2159

2160
    len = concat(&req[req_len], sizeof(req) - req_len,
18✔
2161
                 (unsigned char[]){AS4BE(auth_handle)}, (size_t)4,
9✔
2162
                 nonce_odd, sizeof(nonce_odd),
2163
                 &continue_auth_session, (size_t)1,
2164
                 owner_auth, owner_auth_len,
2165
                 NULL);
2166
    if (len < 0) {
9✔
2167
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
2168
        goto error;
×
2169
    }
2170
    req_len += len;
9✔
2171

2172
    trh = (struct tpm_req_header *)req; /* old gcc type-punned pointer */
9✔
2173
    trh->size = htobe32(req_len);
9✔
2174

2175
    ret = transfer(self, req, req_len, "TPM_TakeOwnership", FALSE,
9✔
2176
                   NULL, NULL, TPM_DURATION_LONG);
2177

2178
error:
9✔
2179
    EVP_PKEY_free(pkey);
9✔
2180
    EVP_PKEY_CTX_free(ctx);
9✔
2181
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
2182
    BN_free(exp);
9✔
2183
    BN_free(mod);
9✔
2184
#endif
2185
    return ret;
9✔
2186

2187
error_free_bn:
×
2188
    BN_free(exp);
×
2189
    BN_free(mod);
×
2190

2191
#if OPENSSL_VERSION_NUMBER < 0x30000000L
2192
error_free_pkey_and_rsa:
2193
    RSA_free(rsakey);
2194
error_free_pkey:
2195
#else
2196
    EVP_PKEY_CTX_free(ctx);
×
2197
#endif
2198
    EVP_PKEY_free(pkey);
×
2199

2200
    return 1;
×
2201
}
2202

2203
static int swtpm_tpm12_nv_define_space(struct swtpm *self, uint32_t nvindex,
27✔
2204
                                       uint32_t nvindexattrs, size_t size)
2205
{
2206
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_DEFINE_SPACE);
27✔
2207
    g_autofree unsigned char *pcr_info_short = NULL;
54✔
2208
    ssize_t pcr_info_short_len;
27✔
2209
    g_autofree unsigned char *nv_data_public = NULL;
27✔
2210
    ssize_t nv_data_public_len;
27✔
2211
    g_autofree unsigned char *req = NULL;
27✔
2212
    ssize_t req_len;
27✔
2213
    unsigned char zeroes[SHA_DIGEST_LENGTH] = {0, };
27✔
2214

2215
    pcr_info_short_len = memconcat(&pcr_info_short,
54✔
2216
                                   (unsigned char[]){AS2BE(3), 0, 0, 0, TPM_LOC_ALL}, (size_t)6,
27✔
2217
                                   zeroes, sizeof(zeroes),
2218
                                   NULL);
2219
    if (pcr_info_short_len < 0) {
27✔
2220
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2221
        return 1;
×
2222
    }
2223

2224
    nv_data_public_len = memconcat(&nv_data_public,
54✔
2225
                                   (unsigned char[]){
27✔
2226
                                       AS2BE(TPM_TAG_NV_DATA_PUBLIC), AS4BE(nvindex)
27✔
2227
                                   }, (size_t)6,
2228
                                   pcr_info_short, pcr_info_short_len,
2229
                                   pcr_info_short, pcr_info_short_len,
2230
                                   (unsigned char[]){
27✔
2231
                                       AS2BE(TPM_TAG_NV_ATTRIBUTES), AS4BE(nvindexattrs),
27✔
2232
                                       0, 0, 0, AS4BE(size)
27✔
2233
                                   }, (size_t)13,
2234
                                   NULL);
2235
    if (nv_data_public_len < 0) {
27✔
2236
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2237
        return 1;
×
2238
    }
2239

2240
    req_len = memconcat(&req,
27✔
2241
                        &hdr, sizeof(hdr),
2242
                        nv_data_public, nv_data_public_len,
2243
                        zeroes, sizeof(zeroes),
2244
                        NULL);
2245
    if (req_len < 0) {
27✔
2246
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2247
        return 1;
×
2248
    }
2249

2250
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
27✔
2251

2252
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE,
27✔
2253
                    NULL, NULL, TPM_DURATION_SHORT);
2254
}
2255

2256
static int swtpm_tpm12_nv_write_value(struct swtpm *self, uint32_t nvindex,
15✔
2257
                                      const unsigned char *data, size_t data_len)
2258
{
2259
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_WRITE_VALUE);
15✔
2260
    g_autofree unsigned char *req = NULL;
30✔
2261
    ssize_t req_len;
15✔
2262

2263
    req_len = memconcat(&req,
30✔
2264
                        &hdr, sizeof(hdr),
2265
                        (unsigned char[]){AS4BE(nvindex), AS4BE(0), AS4BE(data_len)}, (size_t)12,
15✔
2266
                        data, data_len,
2267
                        NULL);
2268
    if (req_len < 0) {
15✔
2269
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2270
        return 1;
×
2271
    }
2272

2273
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
15✔
2274

2275
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE,
15✔
2276
                    NULL, NULL, TPM_DURATION_SHORT);
2277
}
2278

2279
/* Write the EK Certificate into NVRAM */
2280
static int swtpm_tpm12_write_ek_cert_nvram(struct swtpm *self,
8✔
2281
                                           const unsigned char *data, size_t data_len)
2282
{
2283
    uint32_t nvindex = TPM_NV_INDEX_EKCERT | TPM_NV_INDEX_D_BIT;
8✔
2284
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
8✔
2285
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
2286
    if (ret != 0)
8✔
2287
        return 1;
2288

2289
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
8✔
2290
    if (ret != 0)
8✔
2291
        return 1;
2292

2293
    return 0;
2294
}
2295

2296
/* Write the Platform Certificate into NVRAM */
2297
static int swtpm_tpm12_write_platform_cert_nvram(struct swtpm *self,
7✔
2298
                                                 const unsigned char *data, size_t data_len)
2299
{
2300
    uint32_t nvindex = TPM_NV_INDEX_PLATFORMCERT | TPM_NV_INDEX_D_BIT;
7✔
2301
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
7✔
2302
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
2303
    if (ret != 0)
7✔
2304
        return 1;
2305

2306
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
7✔
2307
    if (ret != 0)
7✔
2308
        return 1;
2309

2310
    return 0;
2311
}
2312

2313
static int swtpm_tpm12_nv_lock(struct swtpm *self)
12✔
2314
{
2315
    return swtpm_tpm12_nv_define_space(self, TPM_NV_INDEX_LOCK, 0, 0);
12✔
2316
}
2317

2318
static const struct swtpm12_ops swtpm_tpm12_ops = {
2319
    .run_swtpm_bios = swtpm_tpm12_run_swtpm_bios,
2320
    .create_endorsement_key_pair = swptm_tpm12_create_endorsement_keypair,
2321
    .take_ownership = swtpm_tpm12_take_ownership,
2322
    .write_ek_cert_nvram = swtpm_tpm12_write_ek_cert_nvram,
2323
    .write_platform_cert_nvram = swtpm_tpm12_write_platform_cert_nvram,
2324
    .nv_lock = swtpm_tpm12_nv_lock,
2325
};
2326

2327
static void swtpm_init(struct swtpm *swtpm,
161✔
2328
                       gchar **swtpm_exec_l, const gchar *state_path,
2329
                       const gchar *keyopts, const gchar *logfile,
2330
                       int *fds_to_pass, size_t n_fds_to_pass,
2331
                       gboolean is_tpm2, const gchar *json_profile,
2332
                       int json_profile_fd,
2333
                       const gchar *profile_remove_disabled_param)
2334
{
2335
    swtpm->cops = &swtpm_cops;
161✔
2336
    swtpm->swtpm_exec_l = swtpm_exec_l;
161✔
2337
    swtpm->state_path = state_path;
161✔
2338
    swtpm->keyopts = keyopts;
161✔
2339
    swtpm->logfile = logfile;
161✔
2340
    swtpm->fds_to_pass = fds_to_pass;
161✔
2341
    swtpm->n_fds_to_pass = n_fds_to_pass;
161✔
2342
    swtpm->is_tpm2 = is_tpm2;
161✔
2343
    swtpm->json_profile = json_profile;
161✔
2344
    swtpm->json_profile_fd = json_profile_fd;
161✔
2345
    swtpm->profile_remove_disabled_param = profile_remove_disabled_param;
161✔
2346

2347
    swtpm->pid = -1;
161✔
2348
    swtpm->ctrl_fds[0] = swtpm->ctrl_fds[1] = -1;
161✔
2349
    swtpm->data_fds[0] = swtpm->data_fds[1] = -1;
161✔
2350
}
2351

2352
struct swtpm12 *swtpm12_new(gchar **swtpm_exec_l, const gchar *state_path,
26✔
2353
                            const gchar *keyopts, const gchar *logfile,
2354
                            int *fds_to_pass, size_t n_fds_to_pass)
2355
{
2356
    struct swtpm12 *swtpm12 = g_malloc0(sizeof(struct swtpm12));
26✔
2357

2358
    swtpm_init(&swtpm12->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
26✔
2359
               fds_to_pass, n_fds_to_pass, FALSE, NULL, 0, NULL);
2360
    swtpm12->ops = &swtpm_tpm12_ops;
26✔
2361

2362
    return swtpm12;
26✔
2363
}
2364

2365
struct swtpm2 *swtpm2_new(gchar **swtpm_exec_l, const gchar *state_path,
135✔
2366
                         const gchar *keyopts, const gchar *logfile,
2367
                         int *fds_to_pass, size_t n_fds_to_pass,
2368
                         const gchar *json_profile, int json_profile_fd,
2369
                         const gchar *profile_remove_disabled_param)
2370
{
2371
    struct swtpm2 *swtpm2 = g_malloc0(sizeof(struct swtpm2));
135✔
2372

2373
    swtpm_init(&swtpm2->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
135✔
2374
               fds_to_pass, n_fds_to_pass, TRUE, json_profile, json_profile_fd,
2375
               profile_remove_disabled_param);
2376
    swtpm2->ops = &swtpm_tpm2_ops;
135✔
2377

2378
    return swtpm2;
135✔
2379
}
2380

2381
void swtpm_free(struct swtpm *swtpm) {
161✔
2382
    if (!swtpm)
161✔
2383
        return;
2384
    g_free(swtpm);
161✔
2385
}
2386

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