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

stefanberger / swtpm / #2967

05 May 2026 08:32PM UTC coverage: 72.786% (-0.03%) from 72.813%
#2967

push

travis-ci

web-flow
Merge 449c888d7 into ec2fdc0e1

7906 of 10862 relevant lines covered (72.79%)

9879.77 hits per line

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

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

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

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

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

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

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

125
    if (self->json_profile_fd >= 0) {
155✔
126
        json_profile = g_strdup_printf("fd=%u", self->json_profile_fd);
31✔
127
    } else if (self->json_profile != NULL) {
124✔
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)
155✔
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) {
155✔
147
        logop = g_strdup_printf("file=%s", gl_LOGFILE);
79✔
148
        argv = concat_arrays(argv, (const gchar*[]){"--log", logop, NULL}, TRUE);
79✔
149
    }
150

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

372
    return 0;
234✔
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)
112✔
381
{
382
    return do_cmd_get_info(self,
112✔
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_NULL     0x0010
426
#define TPM2_ALG_SM3      0x0012
427
#define TPM2_ALG_RSAPSS   0x0016
428
#define TPM2_ALG_ECDSA    0x0018
429
#define TPM2_ALG_ECC      0x0023
430
#define TPM2_ALG_SHA3_256 0x0027
431
#define TPM2_ALG_SHA3_384 0x0028
432
#define TPM2_ALG_SHA3_512 0x0029
433
#define TPM2_ALG_CFB      0x0043
434

435
#define TPM2_CAP_PCRS     0x00000005
436

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

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

458
#define TPM2_NV_INDEX_ECC_SECP256R1_EKCERT        0x01c0000a
459
#define TPM2_NV_INDEX_ECC_SECP256R1_EKTEMPLATE    0x01c0000b
460
#define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT     0x01c00016
461
#define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE 0x01c00017
462
#define TPM2_NV_INDEX_ECC_SECP521R1_HI_EKCERT     0x01c00018
463
#define TPM2_NV_INDEX_ECC_SECP521R1_HI_EKTEMPLATE 0x01c00019
464

465
#define TPM2_NV_INDEX_IAK_CERT       0x01c90100
466
#define TPM2_NV_INDEX_IDEVID_CERT    0x01c90200
467

468
#define TPM2_EK_RSA_HANDLE           0x81010001
469
#define TPM2_EK_RSA3072_HANDLE       0x8101001c
470
#define TPM2_EK_RSA4096_HANDLE       0x8101001e
471
#define TPM2_EK_ECC_SECP256R1_HANDLE 0x8101000a
472
#define TPM2_EK_ECC_SECP384R1_HANDLE 0x81010016
473
#define TPM2_EK_ECC_SECP521R1_HANDLE 0x81010018
474

475
#define TPM2_SPK_HANDLE              0x81000001
476
#define TPM2_IDEVID_HANDLE           0x81020000
477
#define TPM2_IAK_HANDLE              0x81020001
478

479
#define TPM2_DURATION_SHORT      ( 2000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
480
#define TPM2_DURATION_MEDIUM     ( 7500 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
481
#define TPM2_DURATION_LONG       (15000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
482
#define TPM2_DURATION_EXTRA_LONG (30000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
483

484
#define TPM_REQ_HEADER_INITIALIZER(TAG, SIZE, ORD) \
485
    { \
486
        .tag = htobe16(TAG), \
487
        .size = htobe32(SIZE), \
488
        .ordinal = htobe32(ORD), \
489
    }
490

491
struct tpm2_authblock {
492
    uint32_t auth;
493
    uint16_t nonceSize; // currently always 0
494
    uint8_t continueSession;
495
    uint16_t pwdSize; // currently always 0
496
} __attribute__((packed));
497

498
#define TPM2_AUTHBLOCK_INITIALIZER(AUTH) \
499
    { \
500
        .auth = htobe32(AUTH), \
501
        .nonceSize = htobe16(0), \
502
        .continueSession = 0, \
503
        .pwdSize = htobe16(0), \
504
    }
505

506
static const unsigned char NONCE_EMPTY[2] = {AS2BE(0)};
507
static const unsigned char NONCE_RSA2048[2+0x100] = {AS2BE(0x100), 0, };
508
static const unsigned char NONCE_RSA3072[2+0x180] = {AS2BE(0x180), 0, };
509
static const unsigned char NONCE_RSA4096[2+0x200] = {AS2BE(0x200), 0, };
510
static const unsigned char NONCE_ECC_256[2+0x20] = {AS2BE(0x20), 0, };
511
static const unsigned char NONCE_ECC_384[2+0x30] = {AS2BE(0x30), 0, };
512
static const unsigned char NONCE_ECC_521[2+0x42] = {AS2BE(0x42), 0, };
513
static const unsigned char NONCE_IDEVID[2+6] = {AS2BE(6),
514
                                                0x49, 0x44, 0x45, 0x56, 0x49, 0x44 };
515
static const unsigned char NONCE_IAK[2+3] = {AS2BE(3), 0x49, 0x41, 0x4b };
516

517
static const unsigned char PolicyA_SHA256[32] = {
518
    0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d,
519
    0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64,
520
    0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa
521
};
522

523
static const unsigned char PolicyB_SHA384[48] = {
524
    0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC,
525
    0x53, 0xD8, 0x82, 0xBC, 0xF5, 0xFD, 0x3A, 0x1A,
526
    0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4,
527
    0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA,
528
    0xCB, 0x47, 0xBA, 0x09, 0x69, 0x96, 0x46, 0x15,
529
    0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12
530
};
531

532
static const unsigned char PolicyB_SHA512[64] = {
533
    0xB8, 0x22, 0x1C, 0xA6, 0x9E, 0x85, 0x50, 0xA4,
534
    0x91, 0x4D, 0xE3, 0xFA, 0xA6, 0xA1, 0x8C, 0x07,
535
    0x2C, 0xC0, 0x12, 0x08, 0x07, 0x3A, 0x92, 0x8D,
536
    0x5D, 0x66, 0xD5, 0x9E, 0xF7, 0x9E, 0x49, 0xA4,
537
    0x29, 0xC4, 0x1A, 0x6B, 0x26, 0x95, 0x71, 0xD5,
538
    0x7E, 0xDB, 0x25, 0xFB, 0xDB, 0x18, 0x38, 0x42,
539
    0x56, 0x08, 0xB4, 0x13, 0xCD, 0x61, 0x6A, 0x5F,
540
    0x6D, 0xB5, 0xB6, 0x07, 0x1A, 0xF9, 0x9B, 0xEA
541
};
542

543
/* SPK: fixedTPM, fixedParent, sensitiveDataOrigin, userWithAuth, noDA, restricted, decrypt */
544
#define KEYFLAGS_SPK ((1<<1) /* fixedTPM */ \
545
                    | (1<<4) /* fixedParent */ \
546
                    | (1<<5) /* sensitiveDataOrigin */ \
547
                    | (1<<6) /* userWithAuth */ \
548
                    | (1<<10) /* noDA */ \
549
                    | (1<<16) /* restricted */ \
550
                    | (1<<17)) /* decrypt */
551

552
/* IAK: fixedTPM, fixedParent, sensitiveDataOrigin, adminWithPolicy, restricted, sign */
553
#define KEYFLAGS_IAK ((1<<1) /* fixedTPM */ \
554
                    | (1<<4) /* fixedParent */ \
555
                    | (1<<5) /* sensitiveDataOrigin */ \
556
                    | (1<<6) /* userWithAuth */ \
557
                    | (1<<7) /* adminWithPolicy */ \
558
                    | (1<<16) /* restricted */ \
559
                    | (1<<18)) /* sign */
560

561
/* IDevID: fixedTPM, fixedParent, sensitiveDataOrigin, adminWithPolicy, sign */
562
#define KEYFLAGS_IDEVID ((1<<1) /* fixedTPM */ \
563
                       | (1<<4) /* fixedParent */ \
564
                       | (1<<5) /* sensitiveDataOrigin */ \
565
                       | (1<<6) /* userWithAuth */ \
566
                       | (1<<7) /* adminWithPolicy */ \
567
                       | (1<<18)) /* sign */
568

569
static const struct bank_to_name {
570
    uint16_t hashAlg;
571
    const char *name;
572
} banks_to_names[] = {
573
    {TPM2_ALG_SHA1, "sha1"},
574
    {TPM2_ALG_SHA256, "sha256"},
575
    {TPM2_ALG_SHA384, "sha384"},
576
    {TPM2_ALG_SHA512, "sha512"},
577
    {TPM2_ALG_SM3, "sm3-256"},
578
    {TPM2_ALG_SHA3_256, "sha3-256"},
579
    {TPM2_ALG_SHA3_384, "sha3-384"},
580
    {TPM2_ALG_SHA3_512, "sha3-512"},
581
    {0, NULL},
582
};
583

584
struct pk_params {
585
    enum keyalgo keyalgo;
586
    uint16_t keyalgo_param; // RSA key size or ECC curve Id
587
    const char *keydescription;
588
    uint32_t keyflags;
589
    const unsigned char *nonce;
590
    size_t nonce_len;
591
    const unsigned char *nonce2; // For ECC if nonce != nonce2
592
    size_t nonce2_len;
593
    uint16_t hashalg;
594
    const unsigned char *authpolicy;
595
    size_t authpolicy_len;
596
#define SCHEMEDATA_SIZE 10
597
    unsigned char schemedata[SCHEMEDATA_SIZE];
598
    size_t schemedata_len;
599
    unsigned int symkey_len;
600
    int duration;
601
    size_t off; // offset of public key in TPM response
602
    unsigned keysize;
603
};
604

605
static const struct ek_params {
606
    struct pk_params pk;
607
    uint32_t ek_handle;
608
    const char *keytype;
609
    uint32_t nvindex_ekcert;
610
    uint32_t nvindex_template;
611
} ek_params[] = {
612
    {
613
        .pk = {
614
            .keyalgo = KEYALGO_ECC,
615
            .keyalgo_param = TPM2_ECC_NIST_P256,
616
            .keydescription = "secp256r1",
617
            .nonce = NONCE_ECC_256,
618
            .nonce_len = sizeof(NONCE_ECC_256),
619
            .hashalg = TPM2_ALG_SHA256,
620
            .authpolicy = PolicyA_SHA256,
621
            .authpolicy_len = sizeof(PolicyA_SHA256),
622
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
623
                AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P256), AS2BE(TPM2_ALG_NULL)
624
             },
625
            .schemedata_len = 6,
626
            .symkey_len = 128,
627
            .duration = TPM2_DURATION_LONG,
628
            .keysize = 32,
629
        },
630
        .ek_handle = TPM2_EK_ECC_SECP256R1_HANDLE,
631
        .keytype = "secp256r1",
632
        .nvindex_ekcert = TPM2_NV_INDEX_ECC_SECP256R1_EKCERT,
633
        .nvindex_template = TPM2_NV_INDEX_ECC_SECP256R1_EKTEMPLATE,
634
    }, {
635
        .pk = {
636
            .keyalgo = KEYALGO_ECC,
637
            .keyalgo_param = TPM2_ECC_NIST_P384,
638
            .keydescription = "secp384r1",
639
            .nonce = NONCE_EMPTY,
640
            .nonce_len = sizeof(NONCE_EMPTY),
641
            .hashalg = TPM2_ALG_SHA384,
642
            .authpolicy = PolicyB_SHA384,
643
            .authpolicy_len = sizeof(PolicyB_SHA384),
644
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
645
                AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P384), AS2BE(TPM2_ALG_NULL)
646
             },
647
            .schemedata_len = 6,
648
            .symkey_len = 256,
649
            .duration = TPM2_DURATION_LONG,
650
            .keysize = 48,
651
        },
652
        .ek_handle = TPM2_EK_ECC_SECP384R1_HANDLE,
653
        .keytype = "rsa384r1",
654
        .nvindex_ekcert = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT,
655
        .nvindex_template = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE,
656
    }, {
657
        .pk = {
658
            .keyalgo = KEYALGO_ECC,
659
            .keyalgo_param = TPM2_ECC_NIST_P521,
660
            .keydescription = "secp521r1",
661
            .nonce = NONCE_EMPTY,
662
            .nonce_len = sizeof(NONCE_EMPTY),
663
            .hashalg = TPM2_ALG_SHA512,
664
            .authpolicy = PolicyB_SHA512,
665
            .authpolicy_len = sizeof(PolicyB_SHA512),
666
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
667
                AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P521), AS2BE(TPM2_ALG_NULL)
668
             },
669
            .schemedata_len = 6,
670
            .symkey_len = 256,
671
            .duration = TPM2_DURATION_LONG,
672
            .keysize = 66,
673
        },
674
        .ek_handle = TPM2_EK_ECC_SECP521R1_HANDLE,
675
        .keytype = "secp521r1",
676
        .nvindex_ekcert = TPM2_NV_INDEX_ECC_SECP521R1_HI_EKCERT,
677
        .nvindex_template = TPM2_NV_INDEX_ECC_SECP521R1_HI_EKTEMPLATE,
678
    }, {
679
        .pk = {
680
            .keyalgo = KEYALGO_RSA,
681
            .keyalgo_param = 2048,
682
            .keydescription = "rsa2048",
683
            .nonce = NONCE_RSA2048,
684
            .nonce_len = sizeof(NONCE_RSA2048),
685
            .hashalg = TPM2_ALG_SHA256,
686
            .authpolicy = PolicyA_SHA256,
687
            .authpolicy_len = sizeof(PolicyA_SHA256),
688
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
689
                AS2BE(TPM2_ALG_NULL), AS2BE(2048), AS4BE(0)
690
             },
691
            .schemedata_len = 8,
692
            .symkey_len = 128,
693
            .duration = TPM2_DURATION_LONG,
694
            .keysize = 2048 / 8,
695
        },
696
        .ek_handle = TPM2_EK_RSA_HANDLE,
697
        .keytype = "RSA 2048",
698
        .nvindex_ekcert = TPM2_NV_INDEX_RSA2048_EKCERT,
699
        .nvindex_template = TPM2_NV_INDEX_RSA2048_EKTEMPLATE,
700
    }, {
701
        .pk = {
702
            .keyalgo = KEYALGO_RSA,
703
            .keyalgo_param = 3072,
704
            .keydescription = "rsa3072",
705
            .nonce = NONCE_EMPTY,
706
            .nonce_len = sizeof(NONCE_EMPTY),
707
            .hashalg = TPM2_ALG_SHA384,
708
            .authpolicy = PolicyB_SHA384,
709
            .authpolicy_len = sizeof(PolicyB_SHA384),
710
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
711
                AS2BE(TPM2_ALG_NULL), AS2BE(3072), AS4BE(0)
712
             },
713
            .schemedata_len = 8,
714
            .symkey_len = 256,
715
            .duration = TPM2_DURATION_LONG,
716
            .keysize = 3072 / 8,
717
        },
718
        .ek_handle = TPM2_EK_RSA3072_HANDLE,
719
        .keytype = "RSA 3072",
720
        .nvindex_ekcert = TPM2_NV_INDEX_RSA3072_HI_EKCERT,
721
        .nvindex_template = TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE,
722
    }, {
723
        .pk = {
724
            .keyalgo = KEYALGO_RSA,
725
            .keyalgo_param = 4096,
726
            .keydescription = "rsa4096",
727
            .nonce = NONCE_EMPTY,
728
            .nonce_len = sizeof(NONCE_EMPTY),
729
            .hashalg = TPM2_ALG_SHA384,
730
            .authpolicy = PolicyB_SHA384,
731
            .authpolicy_len = sizeof(PolicyB_SHA384),
732
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
733
                AS2BE(TPM2_ALG_NULL), AS2BE(4096), AS4BE(0)
734
             },
735
            .schemedata_len = 8,
736
            .symkey_len = 256,
737
            .duration = TPM2_DURATION_EXTRA_LONG,
738
            .keysize = 4096 / 8,
739
        },
740
        .ek_handle = TPM2_EK_RSA4096_HANDLE,
741
        .keytype = "RSA 4096",
742
        .nvindex_ekcert = TPM2_NV_INDEX_RSA4096_HI_EKCERT,
743
        .nvindex_template = TPM2_NV_INDEX_RSA4096_HI_EKTEMPLATE,
744
    }
745
};
746

747
static const unsigned char null_authpolicy[] = {};
748

749
static const struct spk_params {
750
    struct pk_params pk;
751
} spk_params[] = {
752
    {
753
        .pk = {
754
            .keyalgo = KEYALGO_ECC,
755
            .keyalgo_param = TPM2_ECC_NIST_P256,
756
            .keyflags = KEYFLAGS_SPK,
757
            .nonce = NONCE_ECC_256,
758
            .nonce_len = sizeof(NONCE_ECC_256),
759
            .hashalg = TPM2_ALG_SHA256,
760
            .authpolicy = null_authpolicy,
761
            .authpolicy_len = 0,
762
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
763
                AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P256), AS2BE(TPM2_ALG_NULL)
764
             },
765
            .schemedata_len = 6,
766
            .keysize = 32,
767
            .symkey_len = 128,
768
            .off = 42,
769
            .duration = TPM2_DURATION_LONG,
770
        }
771
   }, {
772
        .pk = {
773
            .keyalgo = KEYALGO_ECC,
774
            .keyalgo_param = TPM2_ECC_NIST_P384,
775
            .keyflags = KEYFLAGS_SPK,
776
            /* per "TCG TPM v2.0 Provisioning Guidance v1.0" page 37
777
             * -> "Ek Credential Profile 2.0" rev.14 section 2.1.5.2:
778
             * template for NIST P256 uses 2 identical 32-byte all-zero nonces
779
             * -> Use two 48-byte all-zero nonces for NIST P384.
780
             */
781
            .nonce = NONCE_ECC_384,
782
            .nonce_len = sizeof(NONCE_ECC_384),
783
            .hashalg = TPM2_ALG_SHA384,
784
            .authpolicy = null_authpolicy,
785
            .authpolicy_len = 0,
786
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
787
                AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P384), AS2BE(TPM2_ALG_NULL),
788
             },
789
            .schemedata_len = 6,
790
            .keysize = 48,
791
            .symkey_len = 256,
792
            .off = 42,
793
            .duration = TPM2_DURATION_LONG,
794
        },
795
    }, {
796
        .pk = {
797
            .keyalgo = KEYALGO_ECC,
798
            .keyalgo_param = TPM2_ECC_NIST_P521,
799
            .keyflags = KEYFLAGS_SPK,
800
            .nonce = NONCE_ECC_521,
801
            .nonce_len = sizeof(NONCE_ECC_521),
802
            .hashalg = TPM2_ALG_SHA512,
803
            .authpolicy = null_authpolicy,
804
            .authpolicy_len = 0,
805
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
806
                AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P521), AS2BE(TPM2_ALG_NULL)
807
             },
808
            .schemedata_len = 6,
809
            .keysize = 66,
810
            .symkey_len = 256,
811
            .off = 42,
812
            .duration = TPM2_DURATION_LONG,
813
       },
814
    }, {
815
        .pk = {
816
            .keyalgo = KEYALGO_RSA,
817
            .keyalgo_param = 2048,
818
            .keyflags = KEYFLAGS_SPK,
819
            .nonce = NONCE_RSA2048,
820
            .nonce_len = sizeof(NONCE_RSA2048),
821
            .hashalg = TPM2_ALG_SHA256,
822
            .authpolicy = null_authpolicy,
823
            .authpolicy_len = 0,
824
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
825
                AS2BE(TPM2_ALG_NULL), AS2BE(2048), AS4BE(0)
826
             },
827
            .schemedata_len = 8,
828
            .keysize = 2048/8,
829
            .symkey_len = 128,
830
            .off = 44,
831
            .duration = TPM2_DURATION_LONG,
832
       },
833
    }, {
834
        .pk = {
835
            .keyalgo = KEYALGO_RSA,
836
            .keyalgo_param = 3072,
837
            .keyflags = KEYFLAGS_SPK,
838
            .nonce = NONCE_RSA3072,
839
            .nonce_len = sizeof(NONCE_RSA3072),
840
            .hashalg = TPM2_ALG_SHA384,
841
            .authpolicy = null_authpolicy,
842
            .authpolicy_len = 0,
843
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
844
                AS2BE(TPM2_ALG_NULL), AS2BE(3072), AS4BE(0)
845
             },
846
            .schemedata_len = 8,
847
            .keysize = 3072/8,
848
            .symkey_len = 256,
849
            .off = 44,
850
            .duration = TPM2_DURATION_LONG,
851
       },
852
    }, {
853
        .pk = {
854
            .keyalgo = KEYALGO_RSA,
855
            .keyalgo_param = 4096,
856
            .keyflags = KEYFLAGS_SPK,
857
            .nonce = NONCE_RSA4096,
858
            .nonce_len = sizeof(NONCE_RSA4096),
859
            .hashalg = TPM2_ALG_SHA384,
860
            .authpolicy = null_authpolicy,
861
            .authpolicy_len = 0,
862
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
863
                AS2BE(TPM2_ALG_NULL), AS2BE(4096), AS4BE(0)
864
             },
865
            .schemedata_len = 8,
866
            .keysize = 4096/8,
867
            .symkey_len = 256,
868
            .off = 44,
869
            .duration = TPM2_DURATION_EXTRA_LONG,
870
       },
871
    }
872
};
873

874

875
static const unsigned char Attestation_PolicyIDevIDKey_SHA256[32] = {
876
    0x54, 0x37, 0x18, 0x23, 0x26, 0xe4, 0x14, 0xfc,
877
    0xa7, 0x97, 0xd5, 0xf1, 0x74, 0x61, 0x5a, 0x16,
878
    0x41, 0xf6, 0x12, 0x55, 0x79, 0x7c, 0x3a, 0x2b,
879
    0x22, 0xc2, 0x1d, 0x12, 0x0b, 0x2d, 0x1e, 0x07,
880
};
881

882
static const unsigned char Attestation_PolicyIDevIDKey_SHA384[48] = {
883
    0x12, 0x9d, 0x94, 0xeb, 0xf8, 0x45, 0x56, 0x65,
884
    0x2c, 0x6e, 0xef, 0x43, 0xbb, 0xb7, 0x57, 0x51,
885
    0x2a, 0xc8, 0x7e, 0x52, 0xbe, 0x7b, 0x34, 0x9c,
886
    0xa6, 0xce, 0x4d, 0x82, 0x6f, 0x74, 0x9f, 0xcf,
887
    0x67, 0x2f, 0x51, 0x71, 0x6c, 0x5c, 0xbb, 0x60,
888
    0x5f, 0x31, 0x3b, 0xf3, 0x45, 0xaa, 0xb3, 0x12,
889
};
890

891
static const unsigned char Attestation_PolicyIDevIDKey_SHA512[64] = {
892
    0x80, 0x60, 0xd1, 0xfb, 0x31, 0x71, 0x6a, 0x29,
893
    0xe4, 0x8a, 0x6e, 0x5f, 0xec, 0xe0, 0x88, 0xbc,
894
    0xfc, 0x1b, 0x27, 0x8f, 0xc1, 0x62, 0x25, 0x5e,
895
    0x81, 0xc3, 0xec, 0xa3, 0x54, 0x4c, 0xd4, 0x4a,
896
    0xf9, 0x44, 0x10, 0xc3, 0x71, 0x5d, 0x56, 0x1c,
897
    0xcc, 0xd9, 0xe3, 0x9a, 0x6c, 0xb2, 0x64, 0x6d,
898
    0x43, 0x53, 0x5b, 0xb5, 0x4e, 0xa8, 0x87, 0x10,
899
    0xde, 0xb5, 0xf7, 0x83, 0x6b, 0xd9, 0xb5, 0x86
900
};
901

902
static const struct iak_params {
903
    struct pk_params pk;
904
    const char *keytype;
905
} iak_params[] = {
906
    {
907
        .pk = {
908
            .keyalgo = KEYALGO_ECC,
909
            .keyalgo_param = TPM2_ECC_NIST_P256,
910
            .keydescription = "secp256r1",
911
            .keyflags = KEYFLAGS_IAK,
912
            .nonce = NONCE_IAK,
913
            .nonce_len = sizeof(NONCE_IAK),
914
            .nonce2 = NONCE_EMPTY,
915
            .nonce2_len = sizeof(NONCE_EMPTY),
916
            .hashalg = TPM2_ALG_SHA256,
917
            .authpolicy = Attestation_PolicyIDevIDKey_SHA256,
918
            .authpolicy_len = sizeof(Attestation_PolicyIDevIDKey_SHA256),
919
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
920
                AS2BE(TPM2_ALG_ECDSA), AS2BE(TPM2_ALG_SHA256),
921
                AS2BE(TPM2_ECC_NIST_P256), AS2BE(TPM2_ALG_NULL),
922
            },
923
            .schemedata_len = 8,
924
            .keysize = 32,
925
            .symkey_len = 0,
926
            .off = 0x48,
927
            .duration = TPM2_DURATION_LONG,
928
        },
929
        .keytype = "secp256r1",
930
   }, {
931
        .pk = {
932
            .keyalgo = KEYALGO_ECC,
933
            .keyalgo_param = TPM2_ECC_NIST_P384,
934
            .keydescription = "secp384r1",
935
            .keyflags = KEYFLAGS_IAK,
936
            .nonce = NONCE_IAK,
937
            .nonce_len = sizeof(NONCE_IAK),
938
            .nonce2 = NONCE_EMPTY,
939
            .nonce2_len = sizeof(NONCE_EMPTY),
940
            .hashalg = TPM2_ALG_SHA384,
941
            .authpolicy = Attestation_PolicyIDevIDKey_SHA384,
942
            .authpolicy_len = sizeof(Attestation_PolicyIDevIDKey_SHA384),
943
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
944
                AS2BE(TPM2_ALG_ECDSA), AS2BE(TPM2_ALG_SHA384),
945
                AS2BE(TPM2_ECC_NIST_P384), AS2BE(TPM2_ALG_NULL),
946
            },
947
            .schemedata_len = 8,
948
            .keysize = 48,
949
            .symkey_len = 0,
950
            .off = 0x58,
951
            .duration = TPM2_DURATION_LONG,
952
        },
953
        .keytype = "secp384r1",
954
    }, {
955
        .pk = {
956
            .keyalgo = KEYALGO_ECC,
957
            .keyalgo_param = TPM2_ECC_NIST_P521,
958
            .keydescription = "secp521r1",
959
            .keyflags = KEYFLAGS_IAK,
960
            .nonce = NONCE_IAK,
961
            .nonce_len = sizeof(NONCE_IAK),
962
            .nonce2 = NONCE_EMPTY,
963
            .nonce2_len = sizeof(NONCE_EMPTY),
964
            .hashalg = TPM2_ALG_SHA512,
965
            .authpolicy = Attestation_PolicyIDevIDKey_SHA512,
966
            .authpolicy_len = sizeof(Attestation_PolicyIDevIDKey_SHA512),
967
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
968
                AS2BE(TPM2_ALG_ECDSA), AS2BE(TPM2_ALG_SHA512),
969
                AS2BE(TPM2_ECC_NIST_P521), AS2BE(TPM2_ALG_NULL),
970
            },
971
            .schemedata_len = 8,
972
            .keysize = 66,
973
            .symkey_len = 0,
974
            .off = 0x68,
975
            .duration = TPM2_DURATION_LONG,
976
       },
977
        .keytype = "secp521r1",
978
    }, {
979
        .pk = {
980
            .keyalgo = KEYALGO_RSA,
981
            .keyalgo_param = 2048,
982
            .keydescription = "rsa2048",
983
            .keyflags = KEYFLAGS_IAK,
984
            .nonce = NONCE_IAK,
985
            .nonce_len = sizeof(NONCE_IAK),
986
            .hashalg = TPM2_ALG_SHA256,
987
            .authpolicy = Attestation_PolicyIDevIDKey_SHA256,
988
            .authpolicy_len = sizeof(Attestation_PolicyIDevIDKey_SHA256),
989
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
990
                AS2BE(TPM2_ALG_RSAPSS), AS2BE(TPM2_ALG_SHA256),
991
                AS2BE(2048), AS4BE(0),
992
            },
993
            .schemedata_len = 10,
994
            .keysize = 2048/8,
995
            .symkey_len = 0,
996
            .off = 0x4a,
997
            .duration = TPM2_DURATION_LONG,
998
        },
999
        .keytype = "RSA 2048",
1000
   }, {
1001
        .pk = {
1002
            .keyalgo = KEYALGO_RSA,
1003
            .keyalgo_param = 3072,
1004
            .keydescription = "rsa3072",
1005
            .keyflags = KEYFLAGS_IAK,
1006
            .nonce = NONCE_IAK,
1007
            .nonce_len = sizeof(NONCE_IAK),
1008
            .hashalg = TPM2_ALG_SHA384,
1009
            .authpolicy = Attestation_PolicyIDevIDKey_SHA384,
1010
            .authpolicy_len = sizeof(Attestation_PolicyIDevIDKey_SHA384),
1011
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
1012
                AS2BE(TPM2_ALG_RSAPSS), AS2BE(TPM2_ALG_SHA384),
1013
                AS2BE(3072), AS4BE(0),
1014
            },
1015
            .schemedata_len = 10,
1016
            .keysize = 3072/8,
1017
            .symkey_len = 0,
1018
            .off = 0x5a,
1019
            .duration = TPM2_DURATION_LONG,
1020
        },
1021
        .keytype = "RSA 3072",
1022
    }, {
1023
        .pk = {
1024
            .keyalgo = KEYALGO_RSA,
1025
            .keyalgo_param = 4096,
1026
            .keydescription = "rsa4096",
1027
            .keyflags = KEYFLAGS_IAK,
1028
            .nonce = NONCE_IAK,
1029
            .nonce_len = sizeof(NONCE_IAK),
1030
            .hashalg = TPM2_ALG_SHA384,
1031
            .authpolicy = Attestation_PolicyIDevIDKey_SHA384,
1032
            .authpolicy_len = sizeof(Attestation_PolicyIDevIDKey_SHA384),
1033
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
1034
                AS2BE(TPM2_ALG_RSAPSS), AS2BE(TPM2_ALG_SHA384),
1035
                AS2BE(4096), AS4BE(0),
1036
            },
1037
            .schemedata_len = 10,
1038
            .keysize = 4096/8,
1039
            .symkey_len = 0,
1040
            .off = 0x5a,
1041
            .duration = TPM2_DURATION_EXTRA_LONG,
1042
        },
1043
        .keytype = "RSA 4096",
1044
    }
1045
};
1046

1047
static const unsigned char Signing_PolicyIDevIDKey_SHA256[32] = {
1048
    0xad, 0x6b, 0x3a, 0x22, 0x84, 0xfd, 0x69, 0x8a,
1049
    0x07, 0x10, 0xbf, 0x5c, 0xc1, 0xb9, 0xbd, 0xf1,
1050
    0x5e, 0x25, 0x32, 0xe3, 0xf6, 0x01, 0xfa, 0x4b,
1051
    0x93, 0xa6, 0xa8, 0xfa, 0x8d, 0xe5, 0x79, 0xea
1052
};
1053

1054
static const unsigned char Signing_PolicyIDevIDKey_SHA384[48] = {
1055
    0x4d, 0xb1, 0xaa, 0x83, 0x6d, 0x0b, 0x56, 0x15,
1056
    0xdf, 0x6e, 0xe5, 0x3a, 0x40, 0xef, 0x70, 0xc6,
1057
    0x1c, 0x21, 0x7f, 0x43, 0x03, 0xd4, 0x46, 0x95,
1058
    0x92, 0x59, 0x72, 0xbc, 0x92, 0x70, 0x06, 0xcf,
1059
    0xa5, 0xcb, 0xdf, 0x6d, 0xc1, 0x8c, 0x4d, 0xbe,
1060
    0x32, 0x9b, 0x2f, 0x15, 0x42, 0xc3, 0xdd, 0x33
1061
};
1062

1063
static const unsigned char Signing_PolicyIDevIDKey_SHA512[64] = {
1064
    0x7d, 0xd7, 0x50, 0x0f, 0xd6, 0xc1, 0xb9, 0x4f,
1065
    0x97, 0xa6, 0xaf, 0x91, 0x0d, 0xa1, 0x47, 0x30,
1066
    0x1e, 0xf2, 0x8f, 0x66, 0x2f, 0xee, 0x06, 0xf2,
1067
    0x25, 0xa4, 0xcc, 0xad, 0xda, 0x3b, 0x4e, 0x6b,
1068
    0x38, 0xe6, 0x6b, 0x2f, 0x3a, 0xd5, 0xde, 0xe1,
1069
    0xa0, 0x50, 0x3c, 0xd2, 0xda, 0xed, 0xb1, 0xe6,
1070
    0x8c, 0xfe, 0x4f, 0x84, 0xb0, 0x3a, 0x8c, 0xd2,
1071
    0x2b, 0xb6, 0xa9, 0x76, 0xf0, 0x71, 0xa7, 0x2f
1072
};
1073

1074
static const struct idevid_params {
1075
    struct pk_params pk;
1076
    const char *keytype;
1077
} idevid_params[] = {
1078
    {
1079
        .pk = {
1080
            .keyalgo = KEYALGO_ECC,
1081
            .keyalgo_param = TPM2_ECC_NIST_P256,
1082
            .keydescription = "secp256r1",
1083
            .keyflags = KEYFLAGS_IDEVID,
1084
            .nonce = NONCE_IDEVID,
1085
            .nonce_len = sizeof(NONCE_IDEVID),
1086
            .nonce2 = NONCE_EMPTY,
1087
            .nonce2_len = sizeof(NONCE_EMPTY),
1088
            .hashalg = TPM2_ALG_SHA256,
1089
            .authpolicy = Signing_PolicyIDevIDKey_SHA256,
1090
            .authpolicy_len = sizeof(Signing_PolicyIDevIDKey_SHA256),
1091
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
1092
                AS2BE(TPM2_ALG_ECDSA), AS2BE(TPM2_ALG_SHA256),
1093
                AS2BE(TPM2_ECC_NIST_P256), AS2BE(TPM2_ALG_NULL),
1094
            },
1095
            .schemedata_len = 8,
1096
            .keysize = 32,
1097
            .symkey_len = 0,
1098
            .off = 0x48,
1099
            .duration = TPM2_DURATION_LONG,
1100
        },
1101
        .keytype = "secp256r1",
1102
   }, {
1103
        .pk = {
1104
            .keyalgo = KEYALGO_ECC,
1105
            .keyalgo_param = TPM2_ECC_NIST_P384,
1106
            .keydescription = "secp384r1",
1107
            .keyflags = KEYFLAGS_IDEVID,
1108
            .nonce = NONCE_IDEVID,
1109
            .nonce_len = sizeof(NONCE_IDEVID),
1110
            .nonce2 = NONCE_EMPTY,
1111
            .nonce2_len = sizeof(NONCE_EMPTY),
1112
            .hashalg = TPM2_ALG_SHA384,
1113
            .authpolicy = Signing_PolicyIDevIDKey_SHA384,
1114
            .authpolicy_len = sizeof(Signing_PolicyIDevIDKey_SHA384),
1115
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
1116
                AS2BE(TPM2_ALG_ECDSA), AS2BE(TPM2_ALG_SHA384),
1117
                AS2BE(TPM2_ECC_NIST_P384), AS2BE(TPM2_ALG_NULL),
1118
            },
1119
            .schemedata_len = 8,
1120
            .keysize = 48,
1121
            .symkey_len = 0,
1122
            .off = 0x58,
1123
            .duration = TPM2_DURATION_LONG,
1124
        },
1125
        .keytype = "secp384r1",
1126
    }, {
1127
        .pk = {
1128
            .keyalgo = KEYALGO_ECC,
1129
            .keyalgo_param = TPM2_ECC_NIST_P521,
1130
            .keydescription = "secp521r1",
1131
            .keyflags = KEYFLAGS_IDEVID,
1132
            .nonce = NONCE_IDEVID,
1133
            .nonce_len = sizeof(NONCE_IDEVID),
1134
            .nonce2 = NONCE_EMPTY,
1135
            .nonce2_len = sizeof(NONCE_EMPTY),
1136
            .hashalg = TPM2_ALG_SHA512,
1137
            .authpolicy = Signing_PolicyIDevIDKey_SHA512,
1138
            .authpolicy_len = sizeof(Signing_PolicyIDevIDKey_SHA512),
1139
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
1140
                AS2BE(TPM2_ALG_ECDSA), AS2BE(TPM2_ALG_SHA512),
1141
                AS2BE(TPM2_ECC_NIST_P521), AS2BE(TPM2_ALG_NULL),
1142
            },
1143
            .schemedata_len = 8,
1144
            .keysize = 66,
1145
            .symkey_len = 0,
1146
            .off = 0x68,
1147
            .duration = TPM2_DURATION_LONG,
1148
        },
1149
        .keytype = "secp521r1",
1150
    }, {
1151
        .pk = {
1152
            .keyalgo = KEYALGO_RSA,
1153
            .keyalgo_param = 2048,
1154
            .keydescription = "rsa2048",
1155
            .keyflags = KEYFLAGS_IDEVID,
1156
            .nonce = NONCE_IDEVID,
1157
            .nonce_len = sizeof(NONCE_IDEVID),
1158
            .hashalg = TPM2_ALG_SHA256,
1159
            .authpolicy = Signing_PolicyIDevIDKey_SHA256,
1160
            .authpolicy_len = sizeof(Signing_PolicyIDevIDKey_SHA256),
1161
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
1162
                AS2BE(TPM2_ALG_NULL), AS2BE(2048), AS4BE(0)
1163
             },
1164
            .schemedata_len = 8,
1165
            .keysize = 2048/8,
1166
            .symkey_len = 0,
1167
            .off = 0x48,
1168
            .duration = TPM2_DURATION_LONG,
1169
        },
1170
        .keytype = "RSA 2048",
1171
   }, {
1172
        .pk = {
1173
            .keyalgo = KEYALGO_RSA,
1174
            .keyalgo_param = 3072,
1175
            .keydescription = "rsa3072",
1176
            .keyflags = KEYFLAGS_IDEVID,
1177
            .nonce = NONCE_IDEVID,
1178
            .nonce_len = sizeof(NONCE_IDEVID),
1179
            .hashalg = TPM2_ALG_SHA384,
1180
            .authpolicy = Signing_PolicyIDevIDKey_SHA384,
1181
            .authpolicy_len = sizeof(Signing_PolicyIDevIDKey_SHA384),
1182
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
1183
                AS2BE(TPM2_ALG_NULL), AS2BE(3072), AS4BE(0)
1184
             },
1185
            .schemedata_len = 8,
1186
            .keysize = 3072/8,
1187
            .symkey_len = 0,
1188
            .off = 0x58,
1189
            .duration = TPM2_DURATION_LONG,
1190
        },
1191
        .keytype = "RSA 3072",
1192
    }, {
1193
        .pk = {
1194
            .keyalgo = KEYALGO_RSA,
1195
            .keyalgo_param = 4096,
1196
            .keydescription = "rsa4096",
1197
            .keyflags = KEYFLAGS_IDEVID,
1198
            .nonce = NONCE_IDEVID,
1199
            .nonce_len = sizeof(NONCE_IDEVID),
1200
            .hashalg = TPM2_ALG_SHA384,
1201
            .authpolicy = Signing_PolicyIDevIDKey_SHA384,
1202
            .authpolicy_len = sizeof(Signing_PolicyIDevIDKey_SHA384),
1203
            .schemedata = (unsigned char[SCHEMEDATA_SIZE]) {
1204
                AS2BE(TPM2_ALG_NULL), AS2BE(4096), AS4BE(0)
1205
             },
1206
            .schemedata_len = 8,
1207
            .keysize = 4096/8,
1208
            .symkey_len = 0,
1209
            .off = 0x68,
1210
            .duration = TPM2_DURATION_EXTRA_LONG,
1211
        },
1212
        .keytype = "RSA 4096",
1213
    }
1214
};
1215

1216
static const struct ek_params *get_ek_params(struct swtpm *self,
259✔
1217
                                             enum keyalgo keyalgo,
1218
                                             unsigned int keyalgo_param)
1219
{
1220
    size_t i;
259✔
1221

1222
    for (i = 0; i < ARRAY_LEN(ek_params); i++) {
936✔
1223
        if (ek_params[i].pk.keyalgo == keyalgo &&
936✔
1224
            ek_params[i].pk.keyalgo_param == keyalgo_param) {
444✔
1225
            return &ek_params[i];
259✔
1226
        }
1227
    }
1228
    logerr(self->logfile, "Internal error: Unsupported keyalgo and keyalgo_param: %u/%u\n",
×
1229
           keyalgo, keyalgo_param);
1230
    return NULL;
×
1231
}
1232

1233
static const struct spk_params *get_spk_params(struct swtpm *self,
16✔
1234
                                               enum keyalgo keyalgo,
1235
                                               unsigned int keyalgo_param)
1236
{
1237
    size_t i;
16✔
1238

1239
    for (i = 0; i < ARRAY_LEN(spk_params); i++) {
62✔
1240
        if (spk_params[i].pk.keyalgo == keyalgo &&
62✔
1241
            spk_params[i].pk.keyalgo_param == keyalgo_param) {
32✔
1242
            return &spk_params[i];
16✔
1243
        }
1244
    }
1245
    logerr(self->logfile, "Internal error: Unsupported SRK keyalgo and keyalgo_param: %u/%u\n",
×
1246
           keyalgo, keyalgo_param);
1247
    return NULL;
×
1248
}
1249

1250
static const struct iak_params *get_iak_params(struct swtpm *self,
5✔
1251
                                               enum keyalgo keyalgo,
1252
                                               unsigned int keyalgo_param)
1253
{
1254
    size_t i;
5✔
1255

1256
    for (i = 0; i < ARRAY_LEN(iak_params); i++) {
22✔
1257
        if (iak_params[i].pk.keyalgo == keyalgo &&
22✔
1258
            iak_params[i].pk.keyalgo_param == keyalgo_param) {
10✔
1259
            return &iak_params[i];
5✔
1260
        }
1261
    }
1262
    logerr(self->logfile, "Internal error: Unsupported IAK keyalgo and keyalgo_param: %u/%u\n",
×
1263
           keyalgo, keyalgo_param);
1264
    return NULL;
×
1265
}
1266

1267
static const struct idevid_params *get_idevid_params(struct swtpm *self,
5✔
1268
                                                     enum keyalgo keyalgo,
1269
                                                     unsigned int keyalgo_param)
1270
{
1271
    size_t i;
5✔
1272

1273
    for (i = 0; i < ARRAY_LEN(idevid_params); i++) {
15✔
1274
        if (idevid_params[i].pk.keyalgo == keyalgo &&
15✔
1275
            idevid_params[i].pk.keyalgo_param == keyalgo_param) {
12✔
1276
            return &idevid_params[i];
5✔
1277
        }
1278
    }
1279
    logerr(self->logfile, "Internal error: Unsupported IDevID keyalgo and keyalgo_param: %u/%u\n",
×
1280
           keyalgo, keyalgo_param);
1281
    return NULL;
×
1282
}
1283

1284

1285
/* function prototypes */
1286
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
1287
                                        const struct pk_params *pk_params,
1288
                                        size_t off, uint32_t *curr_handle,
1289
                                        unsigned char *ektemplate, size_t *ektemplate_len,
1290
                                        gchar **ekparam, const gchar **key_description);
1291

1292
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
1293
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
1294
                                  const char *purpose);
1295

1296
/* Given a hash algo identifier, return the name of the hash bank */
1297
static const char *get_name_for_bank(uint16_t hashAlg) {
438✔
1298
    size_t i;
438✔
1299

1300
    for (i = 0; banks_to_names[i].name; i++) {
1,098✔
1301
        if (banks_to_names[i].hashAlg == hashAlg)
1,098✔
1302
            return banks_to_names[i].name;
1303
    }
1304
    return NULL;
1305
}
1306

1307
/* Give the name of a hash bank, return its algo identifier */
1308
static uint16_t get_hashalg_by_bankname(const char *name) {
436✔
1309
    size_t i;
436✔
1310

1311
    for (i = 0; banks_to_names[i].name; i++) {
1,093✔
1312
        if (strcmp(banks_to_names[i].name, name) == 0)
1,093✔
1313
            return banks_to_names[i].hashAlg;
436✔
1314
    }
1315
    return 0;
1316
}
1317

1318
/* Do an SU_CLEAR shutdown of the TPM 2 */
1319
static int swtpm_tpm2_shutdown(struct swtpm *self)
121✔
1320
{
1321
    struct tpm2_shutdown_req {
121✔
1322
        struct tpm_req_header hdr;
1323
        uint16_t shutdownType;
1324
    } __attribute__((packed)) req = {
121✔
1325
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_SHUTDOWN),
121✔
1326
        .shutdownType = htobe16(TPM2_SU_CLEAR)
121✔
1327
    };
1328

1329
    return transfer(self, &req, sizeof(req), "TPM2_Shutdown", FALSE,
121✔
1330
                    NULL, NULL, TPM2_DURATION_SHORT);
1331
}
1332

1333
/* Get all available PCR banks */
1334
static int swtpm_tpm2_get_all_pcr_banks(struct swtpm *self, gchar ***all_pcr_banks)
122✔
1335
{
1336
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, 0, TPM2_CC_GETCAPABILITY);
122✔
1337
    g_autofree unsigned char *req = NULL;
244✔
1338
    ssize_t req_len;
122✔
1339
    unsigned char tpmresp[256];
122✔
1340
    size_t tpmresp_len = sizeof(tpmresp);
122✔
1341
    uint16_t count, bank;
122✔
1342
    const char *name;
122✔
1343
    uint8_t length;
122✔
1344
    size_t offset;
122✔
1345
    size_t i;
122✔
1346
    int ret;
122✔
1347

1348
    req_len = memconcat(&req,
244✔
1349
                        &hdr, sizeof(hdr),
1350
                        (unsigned char[]){AS4BE(TPM2_CAP_PCRS), AS4BE(0), AS4BE(64)}, (size_t)12,
122✔
1351
                        NULL);
1352
    if (req_len < 0) {
122✔
1353
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1354
        return 1;
×
1355
    }
1356
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
122✔
1357

1358
    ret = transfer(self, req, req_len, "TPM2_GetCapability", FALSE,
122✔
1359
                   tpmresp, &tpmresp_len, TPM2_DURATION_MEDIUM);
1360
    if (ret != 0)
122✔
1361
        return 1;
1362

1363
    *all_pcr_banks = NULL;
122✔
1364

1365
    if (tpmresp_len < 17 + sizeof(count))
122✔
1366
        goto err_too_short;
×
1367
    memcpy(&count, &tpmresp[17], sizeof(count));
122✔
1368
    count = be16toh(count);
122✔
1369

1370
    /* unreasonable number of PCR banks ? */
1371
    if (count > 20)
122✔
1372
        goto err_num_pcrbanks;
×
1373

1374
    *all_pcr_banks = g_malloc0(sizeof(char *) * (count + 1));
122✔
1375

1376
    offset = 19;
122✔
1377

1378
    for (i = 0; i < count; i++) {
560✔
1379
        gchar *n;
438✔
1380

1381
        if (tpmresp_len < offset + sizeof(bank))
438✔
1382
            goto err_too_short;
×
1383
        memcpy(&bank, &tpmresp[offset], sizeof(bank));
438✔
1384
        bank = be16toh(bank);
438✔
1385

1386
        if (tpmresp_len < offset + 2 + sizeof(length))
438✔
1387
            goto err_too_short;
×
1388
        length = tpmresp[offset + 2];
438✔
1389

1390
        name = get_name_for_bank(bank);
438✔
1391
        if (name != NULL)
438✔
1392
            n = g_strdup(name);
438✔
1393
        else
1394
            n = g_strdup_printf("%02x", bank);
×
1395

1396
        (*all_pcr_banks)[i] = n;
438✔
1397

1398
        offset += 2 + 1 + length;
438✔
1399
    }
1400
    return 0;
1401

1402
err_num_pcrbanks:
×
1403
    logerr(self->logfile, "Unreasonable number of PCR banks (%u) returned.\n", count);
×
1404
    goto err_exit;
×
1405

1406
err_too_short:
×
1407
    logerr(self->logfile, "Response from TPM2_GetCapability is too short!\n");
×
1408

1409
err_exit:
×
1410
    g_strfreev(*all_pcr_banks);
×
1411
    *all_pcr_banks = NULL;
×
1412

1413
    return 1;
×
1414
}
1415

1416
/* Activate all user-chosen PCR banks and deactivate all others */
1417
static int swtpm_tpm2_set_active_pcr_banks(struct swtpm *self, gchar **pcr_banks,
122✔
1418
                                           gchar **all_pcr_banks, gchar ***active)
1419
{
1420
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_PCR_ALLOCATE);
122✔
1421
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
122✔
1422
    unsigned char pcrselects[6 * 10]; // supports up to 10 PCR banks
122✔
1423
    ssize_t pcrselects_len = 0;
122✔
1424
    size_t count = 0;
122✔
1425
    size_t idx, j;
122✔
1426
    uint16_t hashAlg;
122✔
1427
    g_autofree unsigned char *req = NULL;
244✔
1428
    ssize_t req_len, len;
122✔
1429
    int ret;
122✔
1430
    uint64_t activated_mask = 0;
122✔
1431

1432
    for (idx = 0; pcr_banks[idx] != NULL; idx++)
244✔
1433
        ;
1434
    *active = g_malloc0(sizeof(char *) * (idx + 1));
122✔
1435

1436
    for (idx = 0; pcr_banks[idx] != NULL; idx++) {
244✔
1437
        hashAlg = 0;
220✔
1438
        // Is user-chosen pcr_banks[idx] available?
1439
        for (j = 0; all_pcr_banks[j] != NULL; j++) {
220✔
1440
            if (strcmp(pcr_banks[idx], all_pcr_banks[j]) == 0) {
219✔
1441
                hashAlg = get_hashalg_by_bankname(pcr_banks[idx]);
121✔
1442
                break;
121✔
1443
            }
1444
        }
1445
        if (hashAlg != 0 && (activated_mask & ((uint64_t)1 << j)) == 0) {
122✔
1446
            (*active)[count] = g_strdup(pcr_banks[idx]);
121✔
1447
            len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
242✔
1448
                         (unsigned char[]){AS2BE(hashAlg), 3, 0xff, 0xff, 0xff} , (size_t)6,
121✔
1449
                         NULL);
1450
            if (len < 0) {
121✔
1451
                logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
1452
                return 1;
×
1453
            }
1454
            pcrselects_len += len;
121✔
1455
            count++;
121✔
1456
            activated_mask |= ((uint64_t)1 << j);
121✔
1457
        }
1458
    }
1459

1460
    if (count == 0) {
122✔
1461
        logerr(self->logfile,
1✔
1462
               "No PCR banks could be allocated. None of the selected algorithms are supported.\n");
1463
        goto error;
1✔
1464
    }
1465

1466
    // disable all the other ones not chosen by the user
1467
    for (idx = 0; all_pcr_banks[idx] != NULL; idx++) {
557✔
1468
        gboolean found = FALSE;
751✔
1469

1470
        for (j = 0; pcr_banks[j] != NULL; j++) {
751✔
1471
            if (strcmp(pcr_banks[j], all_pcr_banks[idx]) == 0) {
436✔
1472
                found = TRUE;
1473
                break;
1474
            }
1475
        }
1476
        if (found)
436✔
1477
            continue;
121✔
1478

1479
        /* not found, so not chosen by user */
1480
        hashAlg = get_hashalg_by_bankname(all_pcr_banks[idx]);
315✔
1481

1482
        len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
630✔
1483
                     (unsigned char[]){AS2BE(hashAlg), 3, 0, 0, 0}, (size_t)6,
315✔
1484
                     NULL);
1485
        if (len < 0) {
315✔
1486
            logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
1487
            goto error;
×
1488
        }
1489
        pcrselects_len += len;
315✔
1490
        count++;
315✔
1491
    }
1492

1493
    req_len = memconcat(&req,
242✔
1494
                        &hdr, sizeof(hdr),
1495
                        (unsigned char[]){
121✔
1496
                             AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))
1497
                        }, (size_t)8,
1498
                        &authblock, sizeof(authblock),
1499
                        (unsigned char[]){AS4BE(count)}, (size_t)4,
121✔
1500
                        pcrselects, pcrselects_len,
1501
                        NULL);
1502
    if (req_len < 0) {
121✔
1503
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
1504
        goto error;
×
1505
    }
1506
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
121✔
1507

1508
    ret = transfer(self, req, req_len, "TPM2_PCR_Allocate", FALSE,
121✔
1509
                   NULL, NULL, TPM2_DURATION_SHORT);
1510
    if (ret != 0)
121✔
1511
        goto error;
×
1512

1513
    return 0;
1514

1515
error:
1✔
1516
    g_strfreev(*active);
1✔
1517
    *active = NULL;
1✔
1518

1519
    return 1;
1✔
1520
}
1521

1522
static int swtpm_tpm2_flushcontext(struct swtpm *self, uint32_t handle)
26✔
1523
{
1524
    struct tpm2_flushcontext_req {
26✔
1525
        struct tpm_req_header hdr;
1526
        uint32_t flushHandle;
1527
    } __attribute__((packed)) req = {
26✔
1528
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_FLUSHCONTEXT),
26✔
1529
        .flushHandle = htobe32(handle),
26✔
1530
    };
1531

1532
    return transfer(self, &req, sizeof(req), "TPM2_FlushContext", FALSE,
26✔
1533
                    NULL, NULL, TPM2_DURATION_SHORT);
1534
}
1535

1536
/* Make object at the curr_handler permanent with the perm_handle */
1537
static int swtpm_tpm2_evictcontrol(struct swtpm *self, uint32_t curr_handle, uint32_t perm_handle)
134✔
1538
{
1539
    struct tpm2_evictcontrol_req {
134✔
1540
        struct tpm_req_header hdr;
1541
        uint32_t auth;
1542
        uint32_t objectHandle;
1543
        uint32_t authblockLen;
1544
        struct tpm2_authblock authblock;
1545
        uint32_t persistentHandle;
1546
    } __attribute__((packed)) req = {
134✔
1547
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, sizeof(req), TPM2_CC_EVICTCONTROL),
134✔
1548
        .auth = htobe32(TPM2_RH_OWNER),
134✔
1549
        .objectHandle = htobe32(curr_handle),
134✔
1550
        .authblockLen = htobe32(sizeof(req.authblock)),
134✔
1551
        .authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW),
134✔
1552
        .persistentHandle = htobe32(perm_handle),
134✔
1553
    };
1554

1555
    return transfer(self, &req, sizeof(req), "TPM2_EvictControl", FALSE,
134✔
1556
                    NULL, NULL, TPM2_DURATION_SHORT);
1557
}
1558

1559
static size_t create_symkeydata(const struct pk_params *pk_params,
134✔
1560
                                unsigned char symkeydata[6])
1561
{
1562
    size_t symkeydata_len;
134✔
1563

1564
    if (pk_params->symkey_len) {
134✔
1565
        symkeydata_len = 6;
82✔
1566
        memcpy(symkeydata,
82✔
1567
               ((unsigned char[]){
82✔
1568
                   AS2BE(TPM2_ALG_AES),
1569
                   AS2BE(pk_params->symkey_len),
82✔
1570
                   AS2BE(TPM2_ALG_CFB)
1571
               }),
1572
               symkeydata_len);
1573
    } else {
1574
        symkeydata_len = 2;
52✔
1575
        memcpy(symkeydata,
52✔
1576
               ((unsigned char[]){AS2BE(TPM2_ALG_NULL)}),
52✔
1577
               symkeydata_len);
1578
    }
1579
    return symkeydata_len;
134✔
1580
}
1581

1582
/* Common function to create a TPM 2 primary key.
1583
 *
1584
 * Returns 1 on error with errors having been reported.
1585
 * If tpmresp is != 0 on return then a TPM2 response was received.
1586
 */
1587
static int swtpm_tpm2_createprimary(struct swtpm *self, uint32_t primaryhandle,
134✔
1588
                                    unsigned char *ektemplate, size_t *ektemplate_len,
1589
                                    const unsigned char *public, size_t public_len,
1590
                                    const char *tpm2_function, int duration,
1591
                                    unsigned char *tpmresp, size_t *tpmresp_len,
1592
                                    uint32_t *curr_handle)
1593
{
1594
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY);
134✔
1595
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
134✔
1596
    g_autofree unsigned char *createprimary = NULL;
268✔
1597
    ssize_t createprimary_len;
134✔
1598
    int ret;
134✔
1599

1600
    if (ektemplate) {
134✔
1601
        if (*ektemplate_len < (size_t)public_len) {
108✔
1602
            logerr(self->logfile, "Internal error in %s: Need %zu bytes for ektemplate (rsa) but got only %zu\n",
×
1603
                   __func__, public_len, *ektemplate_len);
1604
            *tpmresp_len = 0;
×
1605
            return 1;
×
1606
        }
1607
        memcpy(ektemplate, public, public_len);
108✔
1608
        *ektemplate_len = public_len;
108✔
1609
    }
1610

1611
    createprimary_len =
134✔
1612
        memconcat(&createprimary,
268✔
1613
                  &hdr, sizeof(hdr),
1614
                  (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8,
134✔
1615
                  &authblock, sizeof(authblock),
1616
                  (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8,
134✔
1617
                  public, public_len,
1618
                  (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
134✔
1619
                  NULL);
1620
    if (createprimary_len < 0) {
134✔
1621
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1622
        *tpmresp_len = 0;
×
1623
        return 1;
×
1624
    }
1625
    ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len);
134✔
1626

1627
    ret = transfer(self, createprimary, createprimary_len, tpm2_function, FALSE,
134✔
1628
                   tpmresp, tpmresp_len, duration);
1629
    if (ret != 0)
134✔
1630
        return 1;
1631

1632
    if (curr_handle) {
134✔
1633
        if (*tpmresp_len < 10 + sizeof(*curr_handle))
134✔
1634
            goto err_too_short;
×
1635
        memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle));
134✔
1636
        *curr_handle = be32toh(*curr_handle);
134✔
1637
    }
1638
    return 0;
1639

1640
err_too_short:
×
1641
    logerr(self->logfile, "Response from %s is too short!\n", tpm2_function);
×
1642
    return 1;
×
1643
}
1644

1645
/* Create an RSA EK */
1646
static int swtpm_tpm2_createprimary_ek_rsa(struct swtpm *self, unsigned int rsa_keysize,
57✔
1647
                                           gboolean allowsigning, gboolean decryption,
1648
                                           uint32_t *curr_handle,
1649
                                           unsigned char *ektemplate, size_t *ektemplate_len,
1650
                                           gchar **ekparam, const gchar **key_description)
1651
{
1652
    const struct ek_params *ekps;
57✔
1653
    struct pk_params pkps;
57✔
1654
    unsigned int keyflags;
57✔
1655
    size_t addlen, off;
57✔
1656

1657
    ekps = get_ek_params(self, KEYALGO_RSA, rsa_keysize);
57✔
1658
    if (!ekps)
57✔
1659
        return 1;
1660
    pkps = ekps->pk;
57✔
1661

1662
    switch (rsa_keysize) {
57✔
1663
    case 2048:
1664
        keyflags = 0;
1665
        addlen = 0;
1666
        break;
1667
    case 3072:
24✔
1668
    case 4096:
1669
        keyflags = 0x40; // userWithAuth
24✔
1670
        addlen = 16;
24✔
1671
        break;
24✔
1672
    default:
1673
        return 1;
1674
    }
1675

1676
    if (allowsigning && decryption) {
57✔
1677
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1678
        // adminWithPolicy, sign, decrypt; restricted CANNOT be set
1679
        keyflags |= 0x000600b2;
7✔
1680
        // symmetric: TPM_ALG_NULL
1681
        pkps.symkey_len = 0;
7✔
1682
        off = 72 + addlen;
7✔
1683
    } else if (allowsigning) {
50✔
1684
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1685
        // adminWithPolicy, sign; restricted CANNOT be set
1686
        keyflags |= 0x000400b2;
14✔
1687
        // symmetric: TPM_ALG_NULL
1688
        pkps.symkey_len = 0;
14✔
1689
        off = 72 + addlen;
14✔
1690
    } else {
1691
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1692
        // adminWithPolicy, restricted, decrypt
1693
        keyflags |= 0x000300b2;
36✔
1694
        // symmetric: TPM_ALG_AES, 128bit or 256bit, TPM_ALG_CFB
1695
        off = 76 + addlen;
36✔
1696
    }
1697

1698
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_ENDORSEMENT, keyflags,
57✔
1699
                                        &pkps, off, curr_handle,
1700
                                        ektemplate, ektemplate_len, ekparam,
1701
                                        key_description);
1702
}
1703

1704
/* Create an RSA key with the given parameters */
1705
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
72✔
1706
                                        const struct pk_params *pk_params,
1707
                                        size_t off, uint32_t *curr_handle,
1708
                                        unsigned char *ektemplate, size_t *ektemplate_len,
1709
                                        gchar **ekparam, const gchar **key_description)
1710
{
1711
    const char *tpm2_function = "TPM2_CreatePrimary(RSA)";
72✔
1712
    g_autofree unsigned char *public = NULL;
144✔
1713
    unsigned char tpmresp[2048];
72✔
1714
    unsigned char symkeydata[6];
72✔
1715
    size_t tpmresp_len = sizeof(tpmresp);
72✔
1716
    size_t symkeydata_len;
72✔
1717
    ssize_t public_len;
72✔
1718
    uint16_t modlen;
72✔
1719
    int ret;
72✔
1720

1721
    if (key_description)
72✔
1722
        *key_description = pk_params->keydescription;
62✔
1723

1724
    symkeydata_len = create_symkeydata(pk_params, symkeydata);
72✔
1725

1726
    public_len =
72✔
1727
        memconcat(&public,
144✔
1728
                  (unsigned char[]) {
72✔
1729
                      AS2BE(TPM2_ALG_RSA), AS2BE(pk_params->hashalg),
72✔
1730
                      AS4BE(keyflags), AS2BE(pk_params->authpolicy_len)
72✔
1731
                  }, (size_t)10,
1732
                  pk_params->authpolicy, pk_params->authpolicy_len,
72✔
1733
                  symkeydata, symkeydata_len,
1734
                  pk_params->schemedata, pk_params->schemedata_len,
72✔
1735
                  pk_params->nonce, pk_params->nonce_len,
72✔
1736
                  NULL);
1737
    if (public_len < 0) {
72✔
1738
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1739
        return 1;
×
1740
    }
1741
    ret = swtpm_tpm2_createprimary(self, primaryhandle,
144✔
1742
                                   ektemplate, ektemplate_len,
1743
                                   public, public_len,
1744
                                   tpm2_function, pk_params->duration,
72✔
1745
                                   tpmresp, &tpmresp_len, curr_handle);
1746
    if (ret != 0) {
72✔
1747
        if (tpmresp_len >= sizeof(struct tpm_resp_header) &&
×
1748
            be32toh(((struct tpm_resp_header *)tpmresp)->errcode) == 0x2c4) {
×
1749
            /*
1750
             * Error may appear when key size is not supported by profile:
1751
             * value is out of range or is not correct for the context Parameter number 2
1752
             */
1753
            logerr(self->logfile,
×
1754
                   ">> Is RSA-%u supported by the profile? RSA-%u needs 'default-v2'.<<\n",
1755
                   pk_params->keysize * 8,
1756
                   pk_params->keysize * 8);
×
1757
        }
1758
        return 1;
×
1759
    }
1760

1761
    if (tpmresp_len < off + sizeof(modlen))
72✔
1762
         goto err_too_short;
×
1763
    memcpy(&modlen, &tpmresp[off], sizeof(modlen));
72✔
1764
    modlen = be16toh(modlen);
72✔
1765
    if (modlen != pk_params->keysize) {
72✔
1766
        logerr(self->logfile, "Internal error in %s: Getting modulus from wrong offset %zu\n",
×
1767
               __func__, off);
1768
        return 1;
×
1769
    }
1770
    if (ekparam) {
72✔
1771
        if (tpmresp_len < off + 2 + modlen)
62✔
1772
            goto err_too_short;
×
1773
        *ekparam = print_as_hex(&tpmresp[off + 2], modlen);
62✔
1774
    }
1775

1776
    return 0;
1777

1778
err_too_short:
×
1779
    logerr(self->logfile, "Response from %s is too short!\n", tpm2_function);
×
1780
    return 1;
×
1781
}
1782

1783
/* Create an ECC key with the given parameters */
1784
static int swtpm_tpm2_createprimary_ecc(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
62✔
1785
                                        const struct pk_params *pk_params,
1786
                                        size_t off, uint32_t *curr_handle,
1787
                                        unsigned char *ektemplate, size_t *ektemplate_len,
1788
                                        gchar **ekparam, const gchar **key_description)
1789
{
1790
    const char *tpm2_function = "TPM2_CreatePrimary(ECC)";
62✔
1791
    g_autofree unsigned char *public = NULL;
124✔
1792
    unsigned char tpmresp[2048];
62✔
1793
    size_t tpmresp_len = sizeof(tpmresp);
62✔
1794
    unsigned char symkeydata[6];
62✔
1795
    uint16_t ksize1, ksize2;
62✔
1796
    size_t symkeydata_len;
62✔
1797
    ssize_t public_len;
62✔
1798
    size_t off2;
62✔
1799
    int ret;
62✔
1800

1801
    if (key_description)
62✔
1802
        *key_description = pk_params->keydescription;
56✔
1803

1804
    symkeydata_len = create_symkeydata(pk_params, symkeydata);
62✔
1805

1806
    public_len =
62✔
1807
        memconcat(&public,
62✔
1808
                  (unsigned char[]){
62✔
1809
                      AS2BE(TPM2_ALG_ECC),
1810
                      AS2BE(pk_params->hashalg),
62✔
1811
                      AS4BE(keyflags),
62✔
1812
                      AS2BE(pk_params->authpolicy_len)
62✔
1813
                  }, (size_t)10,
1814
                  pk_params->authpolicy, pk_params->authpolicy_len,
62✔
1815
                  symkeydata, symkeydata_len,
1816
                  pk_params->schemedata, pk_params->schemedata_len,
62✔
1817
                  pk_params->nonce, pk_params->nonce_len,
62✔
1818
                  pk_params->nonce2 ? pk_params->nonce2     : pk_params->nonce,
1819
                  pk_params->nonce2 ? pk_params->nonce2_len : pk_params->nonce_len,
62✔
1820
                  NULL);
1821
    if (public_len < 0) {
62✔
1822
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1823
        return 1;
×
1824
    }
1825
    ret = swtpm_tpm2_createprimary(self, primaryhandle,
124✔
1826
                                   ektemplate, ektemplate_len,
1827
                                   public, public_len,
1828
                                   tpm2_function, pk_params->duration,
62✔
1829
                                   tpmresp, &tpmresp_len, curr_handle);
1830
    if (ret != 0)
62✔
1831
        return 1;
1832

1833
    if (tpmresp_len < off + sizeof(ksize1))
62✔
1834
        goto err_too_short;
×
1835
    memcpy(&ksize1, &tpmresp[off], sizeof(ksize1));
62✔
1836
    ksize1 = be16toh(ksize1);
62✔
1837
    off2 = off + 2 + ksize1;
62✔
1838

1839
    if (tpmresp_len < off2 + sizeof(ksize2))
62✔
1840
        goto err_too_short;
×
1841
    memcpy(&ksize2, &tpmresp[off2], sizeof(ksize2));
62✔
1842
    ksize2 = be16toh(ksize2);
62✔
1843

1844
    if (ksize1 != pk_params->keysize || ksize2 != pk_params->keysize) {
62✔
1845
        logerr(self->logfile, "ECC: Getting key parameters from wrong offset\n");
×
1846
        return 1;
×
1847
    }
1848

1849
    if (ekparam) {
62✔
1850
        unsigned char *xparam = &tpmresp[off + 2];
56✔
1851
        unsigned char *yparam = &tpmresp[off2 + 2];
56✔
1852
        if (tpmresp_len < off + 2 + ksize1 || tpmresp_len < off2 + 2 + ksize2)
56✔
1853
            goto err_too_short;
×
1854
        g_autofree gchar *xparam_str = print_as_hex(xparam, ksize1);
112✔
1855
        g_autofree gchar *yparam_str = print_as_hex(yparam, ksize2);
112✔
1856

1857
        *ekparam = g_strdup_printf("x=%s,y=%s,id=%s", xparam_str, yparam_str,
56✔
1858
                                   pk_params->keydescription);
56✔
1859
    }
1860

1861
    return 0;
1862

1863
err_too_short:
×
1864
    logerr(self->logfile, "Response from %s is too short!\n", tpm2_function);
×
1865
    return 1;
×
1866
}
1867

1868
static int swtpm_tpm2_createprimary_spk_ecc(struct swtpm *self,
6✔
1869
                                            unsigned int keyalgo_param,
1870
                                            uint32_t *curr_handle)
1871
{
1872
    const struct spk_params *spks;
6✔
1873

1874
    spks = get_spk_params(self, KEYALGO_ECC, keyalgo_param);
6✔
1875
    if (!spks)
6✔
1876
        return 1;
1877

1878
    return swtpm_tpm2_createprimary_ecc(self, TPM2_RH_OWNER, spks->pk.keyflags,
6✔
1879
                                        &spks->pk, spks->pk.off, curr_handle,
6✔
1880
                                        NULL, 0, NULL, NULL);
1881
}
1882

1883
static int swtpm_tpm2_createprimary_spk_rsa(struct swtpm *self, unsigned int keyalgo_param,
10✔
1884
                                            uint32_t *curr_handle)
1885
{
1886
    const struct spk_params *spks;
10✔
1887

1888
    spks = get_spk_params(self, KEYALGO_RSA, keyalgo_param);
10✔
1889
    if (!spks)
10✔
1890
        return 1;
1891

1892
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_OWNER, spks->pk.keyflags,
10✔
1893
                                        &spks->pk, spks->pk.off, curr_handle,
10✔
1894
                                        NULL, 0, NULL, NULL);
1895
}
1896

1897
/* Create either an ECC or RSA storage primary key (deprecated) */
1898
static int swtpm_tpm2_create_spk(struct swtpm *self, enum keyalgo keyalgo,
16✔
1899
                                 unsigned int keyalgo_param)
1900
{
1901
    int ret;
16✔
1902
    uint32_t curr_handle;
16✔
1903

1904
    switch (keyalgo) {
16✔
1905
    case KEYALGO_ECC:
6✔
1906
        ret = swtpm_tpm2_createprimary_spk_ecc(self, keyalgo_param, &curr_handle);
6✔
1907
        break;
6✔
1908
    case KEYALGO_RSA:
10✔
1909
        ret = swtpm_tpm2_createprimary_spk_rsa(self, keyalgo_param, &curr_handle);
10✔
1910
        break;
10✔
1911
    case KEYALGO_NONE:
1912
    default:
1913
        ret = 1;
1914
    }
1915

1916
    if (ret != 0)
16✔
1917
        return 1;
×
1918

1919
    ret = swtpm_tpm2_evictcontrol(self, curr_handle, TPM2_SPK_HANDLE);
16✔
1920
    if (ret == 0)
16✔
1921
        logit(self->logfile,
16✔
1922
              "Successfully created storage primary key with handle 0x%x.\n", TPM2_SPK_HANDLE);
1923

1924
    ret = swtpm_tpm2_flushcontext(self, curr_handle);
16✔
1925
    if (ret != 0) {
16✔
1926
        logerr(self->logfile, "Could not flush storage primary key.\n");
×
1927
        ret = 1;
×
1928
    }
1929

1930
    return ret;
1931
}
1932

1933
static int swtpm_tpm2_create_iak(struct swtpm *self,
5✔
1934
                                 enum keyalgo keyalgo, unsigned int keyalgo_param,
1935
                                 gchar **keyparam, const gchar **key_description)
1936
{
1937
    const struct iak_params *iaks;
5✔
1938
    uint32_t curr_handle = 0;
5✔
1939
    int ret;
5✔
1940

1941
    iaks = get_iak_params(self, keyalgo, keyalgo_param);
5✔
1942
    if (!iaks)
5✔
1943
        return 1;
1944

1945
    switch (keyalgo) {
5✔
1946
    case KEYALGO_RSA:
4✔
1947
        ret = swtpm_tpm2_createprimary_rsa(self, TPM2_RH_ENDORSEMENT, iaks->pk.keyflags,
4✔
1948
                                           &iaks->pk, iaks->pk.off, &curr_handle,
4✔
1949
                                           NULL, 0, keyparam, key_description);
1950
        break;
4✔
1951
    case KEYALGO_ECC:
1✔
1952
        ret = swtpm_tpm2_createprimary_ecc(self, TPM2_RH_ENDORSEMENT, iaks->pk.keyflags,
1✔
1953
                                           &iaks->pk, iaks->pk.off, &curr_handle,
1✔
1954
                                           NULL, 0, keyparam, key_description);
1955
        break;
1✔
1956
    case KEYALGO_NONE:
1957
    default:
1958
        return 1;
1959
    }
1960

1961
    if (ret != 0)
5✔
1962
        return 1;
1963

1964
    ret = swtpm_tpm2_evictcontrol(self, curr_handle, TPM2_IAK_HANDLE);
5✔
1965
    if (ret == 0)
5✔
1966
        logit(self->logfile,
5✔
1967
              "Successfully created %s IAK primary key with handle 0x%x.\n",
1968
              iaks->keytype, TPM2_IAK_HANDLE);
5✔
1969

1970
    return swtpm_tpm2_flushcontext(self, curr_handle);
5✔
1971
}
1972

1973
static int swtpm_tpm2_create_idevid(struct swtpm *self,
5✔
1974
                                    enum keyalgo keyalgo, unsigned int keyalgo_param,
1975
                                    gchar **keyparam, const gchar **key_description)
1976
{
1977
    const struct idevid_params *idps;
5✔
1978
    uint32_t curr_handle = 0;
5✔
1979
    int ret;
5✔
1980

1981
    idps = get_idevid_params(self, keyalgo, keyalgo_param);
5✔
1982
    if (!idps)
5✔
1983
        return 1;
1984

1985
    switch (keyalgo) {
5✔
1986
    case KEYALGO_RSA:
1✔
1987
        ret = swtpm_tpm2_createprimary_rsa(self, TPM2_RH_ENDORSEMENT, idps->pk.keyflags,
1✔
1988
                                           &idps->pk, idps->pk.off, &curr_handle,
1✔
1989
                                           NULL, 0, keyparam, key_description);
1990
        break;
1✔
1991
    case KEYALGO_ECC:
4✔
1992
        ret = swtpm_tpm2_createprimary_ecc(self, TPM2_RH_ENDORSEMENT, idps->pk.keyflags,
4✔
1993
                                           &idps->pk, idps->pk.off, &curr_handle,
4✔
1994
                                           NULL, 0, keyparam, key_description);
1995
        break;
4✔
1996
    case KEYALGO_NONE:
1997
    default:
1998
        return 1;
1999
    }
2000

2001
    if (ret != 0)
5✔
2002
        return 1;
2003

2004
    ret = swtpm_tpm2_evictcontrol(self, curr_handle, TPM2_IDEVID_HANDLE);
5✔
2005
    if (ret == 0)
5✔
2006
        logit(self->logfile,
5✔
2007
              "Successfully created %s IDevID primary key with handle 0x%x.\n",
2008
              idps->keytype, TPM2_IDEVID_HANDLE);
5✔
2009

2010
    return swtpm_tpm2_flushcontext(self, curr_handle);
5✔
2011
}
2012

2013

2014
/* Create an ECC EK key that may be allowed to sign and/or decrypt */
2015
static int swtpm_tpm2_createprimary_ek_ecc(struct swtpm *self, const struct ek_params *ekps,
51✔
2016
                                           gboolean allowsigning, gboolean decryption,
2017
                                           uint32_t *curr_handle,
2018
                                           unsigned char *ektemplate, size_t *ektemplate_len,
2019
                                           gchar **ekparam, const char **key_description)
2020
{
2021
    struct pk_params pkps;
51✔
2022
    unsigned int keyflags;
51✔
2023
    size_t off;
51✔
2024
    int ret;
51✔
2025

2026
    pkps = ekps->pk;
51✔
2027

2028
    switch (pkps.keyalgo_param) {
51✔
2029
    case TPM2_ECC_NIST_P256:
2030
        off = 0x4a;
2031
        keyflags = 0;
2032
        break;
2033
    case TPM2_ECC_NIST_P384:
2034
        off = 0x5a;
2035
        keyflags = 0x40; // userWithAuth (high range)
2036
        break;
2037
    case TPM2_ECC_NIST_P521:
2038
        off = 0x6a;
2039
        keyflags = 0x40; // userWithAuth (high range)
2040
        break;
2041
    default:
2042
        return 1;
2043
    }
2044

2045
    if (allowsigning && decryption) {
51✔
2046
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
2047
        // userWithAuth, adminWithPolicy, sign, decrypt; restricted CANNOT be set
2048
        keyflags |= 0x000600b2;
7✔
2049
        // symmetric: TPM_ALG_NULL
2050
        pkps.symkey_len = 0;
7✔
2051
        off -= 4;
7✔
2052
    } else if (allowsigning) {
44✔
2053
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
2054
        // userWithAuth, adminWithPolicy, sign; restricted CANNOT be set
2055
        keyflags |= 0x000400b2;
14✔
2056
        // symmetric: TPM_ALG_NULL
2057
        pkps.symkey_len = 0;
14✔
2058
        off -= 4;
14✔
2059
    } else {
2060
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
2061
        // userWithAuth, adminWithPolicy, restricted, decrypt
2062
        keyflags |= 0x000300b2;
30✔
2063
        // symmetric: TPM_ALG_AES, 256bit, TPM_ALG_CFB
2064
    }
2065

2066
    ret = swtpm_tpm2_createprimary_ecc(self, TPM2_RH_ENDORSEMENT, keyflags,
51✔
2067
                                       &pkps, off, curr_handle,
2068
                                       ektemplate, ektemplate_len, ekparam,
2069
                                       key_description);
2070
    if (ret != 0)
51✔
2071
       logerr(self->logfile, "%s failed\n", __func__);
×
2072

2073
    return ret;
2074
}
2075

2076
/* Create an ECC or RSA EK */
2077
static int swtpm_tpm2_create_ek(struct swtpm *self, enum keyalgo keyalgo, unsigned int keyalgo_param,
108✔
2078
                                gboolean allowsigning, gboolean decryption, gboolean lock_nvram,
2079
                                gchar **ekparam, const  gchar **key_description)
2080
{
2081
    unsigned char ektemplate[512];
108✔
2082
    size_t ektemplate_len = sizeof(ektemplate);
108✔
2083
    const struct ek_params *ekps;
108✔
2084
    uint32_t curr_handle;
108✔
2085
    int ret;
108✔
2086

2087
    ekps = get_ek_params(self, keyalgo, keyalgo_param);
108✔
2088
    if (!ekps)
108✔
2089
        return 1;
2090

2091
    switch (keyalgo) {
108✔
2092
    case KEYALGO_ECC:
51✔
2093
        ret = swtpm_tpm2_createprimary_ek_ecc(self, ekps,
51✔
2094
                                              allowsigning, decryption,
2095
                                              &curr_handle,
2096
                                              ektemplate, &ektemplate_len,
2097
                                              ekparam, key_description);
2098
        break;
51✔
2099
    case KEYALGO_RSA:
57✔
2100
        ret = swtpm_tpm2_createprimary_ek_rsa(self, keyalgo_param, allowsigning,
57✔
2101
                                              decryption, &curr_handle,
2102
                                              ektemplate, &ektemplate_len, ekparam,
2103
                                              key_description);
2104
        break;
57✔
2105
    case KEYALGO_NONE:
2106
    default:
2107
        ret = 1;
2108
    }
2109

2110
    if (ret == 0)
108✔
2111
        ret = swtpm_tpm2_evictcontrol(self, curr_handle, ekps->ek_handle);
108✔
2112
    if (ret != 0) {
108✔
2113
        logerr(self->logfile, "create_ek failed: 0x%x\n", ret);
×
2114
        return 1;
×
2115
    }
2116

2117
    logit(self->logfile, "Successfully created %s EK with handle 0x%x.\n",
108✔
2118
          ekps->keytype, ekps->ek_handle);
108✔
2119

2120
    if (allowsigning) {
108✔
2121
        uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE | \
42✔
2122
                TPMA_NV_AUTHREAD | \
2123
                TPMA_NV_OWNERREAD | \
2124
                TPMA_NV_PPREAD | \
2125
                TPMA_NV_PPWRITE | \
2126
                TPMA_NV_NO_DA | \
2127
                TPMA_NV_WRITEDEFINE;
2128
        ret = swtpm_tpm2_write_nvram(self, ekps->nvindex_template, nvindexattrs,
42✔
2129
                                     ektemplate, ektemplate_len,
2130
                                     lock_nvram, "EK template");
2131
        if (ret == 0)
42✔
2132
            logit(self->logfile,
42✔
2133
                  "Successfully created NVRAM area 0x%x for %s EK template.\n",
2134
                  ekps->nvindex_template, ekps->keytype);
42✔
2135
    }
2136

2137
    return ret;
2138
}
2139

2140
static int swtpm_tpm2_nvdefinespace(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
195✔
2141
                                    uint16_t data_len)
2142
{
2143
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_DEFINESPACE);
195✔
2144
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
195✔
2145
    g_autofree unsigned char *nvpublic = NULL;
390✔
2146
    ssize_t nvpublic_len;
195✔
2147
    g_autofree unsigned char *req = NULL;
195✔
2148
    ssize_t req_len;
195✔
2149

2150
    nvpublic_len = memconcat(&nvpublic,
390✔
2151
                             (unsigned char[]){
195✔
2152
                                 AS4BE(nvindex), AS2BE(TPM2_ALG_SHA256), AS4BE(nvindexattrs),
195✔
2153
                                 AS2BE(0), AS2BE(data_len)}, (size_t)14,
2154
                             NULL);
2155
    if (nvpublic_len < 0) {
195✔
2156
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
2157
        return 1;
×
2158
    }
2159

2160
    req_len = memconcat(&req,
390✔
2161
                        &hdr, sizeof(hdr),
2162
                        (unsigned char[]){AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))}, (size_t)8,
195✔
2163
                        &authblock, sizeof(authblock),
2164
                        (unsigned char[]){AS2BE(0), AS2BE(nvpublic_len)}, (size_t)4,
195✔
2165
                        nvpublic, nvpublic_len,
2166
                        NULL);
2167
    if (req_len < 0) {
195✔
2168
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
2169
        return 1;
×
2170
    }
2171

2172
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
195✔
2173

2174
    return transfer(self, req, req_len, "TPM2_NV_DefineSpace", FALSE,
195✔
2175
                    NULL, NULL, TPM2_DURATION_SHORT);
2176
}
2177

2178
/* Write the data into the given NVIndex */
2179
static int swtpm_tpm2_nv_write(struct swtpm *self, uint32_t nvindex,
195✔
2180
                               const unsigned char *data, size_t data_len)
2181
{
2182
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITE);
195✔
2183
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
195✔
2184
    g_autofree unsigned char *req = NULL;
390✔
2185
    ssize_t req_len;
195✔
2186
    size_t offset = 0, txlen;
195✔
2187
    int ret;
195✔
2188

2189
    while (offset < data_len) {
392✔
2190
        txlen = min(data_len - offset, 1024);
197✔
2191

2192
        g_free(req);
197✔
2193
        req_len = memconcat(&req,
394✔
2194
                            &hdr, sizeof(hdr),
2195
                            (unsigned char[]){
197✔
2196
                                AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
197✔
2197
                            }, (size_t)12,
2198
                            &authblock, sizeof(authblock),
2199
                            (unsigned char[]){AS2BE(txlen)}, (size_t)2,
197✔
2200
                            &data[offset], txlen,
2201
                            (unsigned char[]){AS2BE(offset)}, (size_t)2,
197✔
2202
                            NULL);
2203
        if (req_len < 0) {
197✔
2204
            logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
2205
            return 1;
×
2206
        }
2207
        ((struct tpm_req_header *)req)->size = htobe32(req_len);
197✔
2208

2209
        ret = transfer(self, req, req_len, "TPM2_NV_Write", FALSE,
197✔
2210
                       NULL, NULL, TPM2_DURATION_SHORT);
2211
        if (ret != 0)
197✔
2212
            return 1;
2213

2214
        offset += txlen;
197✔
2215
    }
2216
    return 0;
2217
}
2218

2219
static int swtpm_tpm2_nv_writelock(struct swtpm *self, uint32_t nvindex)
12✔
2220
{
2221
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITELOCK);
12✔
2222
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
12✔
2223
    g_autofree unsigned char *req;
24✔
2224
    ssize_t req_len;
12✔
2225

2226
    req_len = memconcat(&req,
24✔
2227
                        &hdr, sizeof(hdr),
2228
                        (unsigned char[]){
12✔
2229
                           AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
12✔
2230
                        }, (size_t)12,
2231
                        &authblock, sizeof(authblock),
2232
                        NULL);
2233
    if (req_len < 0) {
12✔
2234
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
2235
        return 1;
×
2236
    }
2237

2238
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
12✔
2239

2240
    return transfer(self, req, req_len, "TPM2_NV_WriteLock", FALSE,
12✔
2241
                    NULL, NULL, TPM2_DURATION_SHORT);
2242
}
2243

2244
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
195✔
2245
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
2246
                                  const char *certtype)
2247
{
2248
    int ret = swtpm_tpm2_nvdefinespace(self, nvindex, nvindexattrs, data_len);
195✔
2249
    if (ret != 0) {
195✔
2250
        logerr(self->logfile, "Could not create NVRAM area 0x%x for %s.\n", nvindex, certtype);
×
2251
        return 1;
×
2252
    }
2253

2254
    ret = swtpm_tpm2_nv_write(self, nvindex, data, data_len);
195✔
2255
    if (ret != 0) {
195✔
2256
        logerr(self->logfile,
×
2257
               "Could not write %s into NVRAM area 0x%x.\n", certtype, nvindex);
2258
        return 1;
×
2259
    }
2260

2261
    if (lock_nvram) {
195✔
2262
        ret = swtpm_tpm2_nv_writelock(self, nvindex);
12✔
2263
        if (ret != 0) {
12✔
2264
            logerr(self->logfile, "Could not lock EK template NVRAM area 0x%x.\n", nvindex);
×
2265
            return 1;
×
2266
        }
2267
    }
2268

2269
    return 0;
2270
}
2271

2272
static int swtpm_tpm2_write_cert_nvram(struct swtpm *self, uint32_t nvindex,
153✔
2273
                                       uint32_t nvindexattrs,
2274
                                       const unsigned char *data, size_t data_len,
2275
                                       gboolean lock_nvram, const char *keytype,
2276
                                       const char *certtype)
2277
{
2278
    int ret;
153✔
2279

2280
    ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, data, data_len, lock_nvram,
153✔
2281
                                 certtype);
2282
    if (ret == 0)
153✔
2283
        logit(self->logfile,
153✔
2284
              "Successfully created NVRAM area 0x%x for %s%s.\n",
2285
              nvindex, keytype, certtype);
2286

2287
    return ret;
153✔
2288
}
2289

2290
/* Write the platform certificate into an NVRAM area */
2291
static int swtpm_tpm2_write_ek_cert_nvram(struct swtpm *self, enum keyalgo keyalgo,
94✔
2292
                                           unsigned int keyalgo_param, gboolean lock_nvram,
2293
                                           const unsigned char *data, size_t data_len)
2294
{
2295
    g_autofree gchar *keytype = NULL;
188✔
2296
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
94✔
2297
            TPMA_NV_AUTHREAD |
2298
            TPMA_NV_OWNERREAD |
2299
            TPMA_NV_PPREAD |
2300
            TPMA_NV_PPWRITE |
2301
            TPMA_NV_NO_DA |
2302
            TPMA_NV_WRITEDEFINE;
2303
    const struct ek_params *ekps;
94✔
2304

2305
    ekps = get_ek_params(self, keyalgo, keyalgo_param);
94✔
2306
    if (!ekps)
94✔
2307
        return 1;
2308

2309
    keytype = g_strdup_printf("%s ", ekps->keytype);
94✔
2310

2311
    return swtpm_tpm2_write_cert_nvram(self, ekps->nvindex_ekcert,
94✔
2312
                                       nvindexattrs, data, data_len,
2313
                                       lock_nvram, keytype, "EK certificate");
2314
}
2315

2316
static int swtpm_tpm2_write_platform_cert_nvram(struct swtpm *self, gboolean lock_nvram,
49✔
2317
                                                const unsigned char *data, size_t data_len)
2318
{
2319
    uint32_t nvindex = TPM2_NV_INDEX_PLATFORMCERT;
49✔
2320
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
49✔
2321
            TPMA_NV_AUTHREAD |
2322
            TPMA_NV_OWNERREAD |
2323
            TPMA_NV_PPREAD |
2324
            TPMA_NV_PPWRITE |
2325
            TPMA_NV_NO_DA |
2326
            TPMA_NV_WRITEDEFINE;
2327

2328
    return swtpm_tpm2_write_cert_nvram(self, nvindex, nvindexattrs, data, data_len,
49✔
2329
                                       lock_nvram, "", "platform certificate");
2330
}
2331

2332
static char *swtpm_tpm2_get_active_profile(struct swtpm *self)
125✔
2333
{
2334
    gchar *result = NULL;
125✔
2335

2336
    if (do_cmd_get_info(self, SWTPM_INFO_ACTIVE_PROFILE, &result))
125✔
2337
        return NULL;
2338
    return result;
122✔
2339
}
2340

2341
static int swtpm_tpm2_write_iak_cert_nvram(struct swtpm *self, gboolean lock_nvram,
5✔
2342
                                           const unsigned char *data, size_t data_len)
2343
{
2344
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
5✔
2345
            TPMA_NV_AUTHREAD |
2346
            TPMA_NV_OWNERREAD |
2347
            TPMA_NV_PPREAD |
2348
            TPMA_NV_PPWRITE |
2349
            TPMA_NV_NO_DA |
2350
            TPMA_NV_WRITEDEFINE;
2351
    uint32_t nvindex = TPM2_NV_INDEX_IAK_CERT;
5✔
2352

2353
    return swtpm_tpm2_write_cert_nvram(self, nvindex, nvindexattrs, data, data_len,
5✔
2354
                                       lock_nvram, "", "IAK certificate");
2355
}
2356

2357
static int swtpm_tpm2_write_idevid_cert_nvram(struct swtpm *self, gboolean lock_nvram,
5✔
2358
                                              const unsigned char *data, size_t data_len)
2359
{
2360
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
5✔
2361
            TPMA_NV_AUTHREAD |
2362
            TPMA_NV_OWNERREAD |
2363
            TPMA_NV_PPREAD |
2364
            TPMA_NV_PPWRITE |
2365
            TPMA_NV_NO_DA |
2366
            TPMA_NV_WRITEDEFINE;
2367
    uint32_t nvindex = TPM2_NV_INDEX_IDEVID_CERT;
5✔
2368

2369
    return swtpm_tpm2_write_cert_nvram(self, nvindex, nvindexattrs, data, data_len,
5✔
2370
                                       lock_nvram, "", "IDevID certificate");
2371
}
2372

2373
static int swtpm_tpm2_get_capability(struct swtpm *self, uint32_t cap, uint32_t prop,
5✔
2374
                                     uint32_t *res)
2375
{
2376
    struct tpm2_get_capability_req {
5✔
2377
        struct tpm_req_header hdr;
2378
        uint32_t cap;
2379
        uint32_t prop;
2380
        uint32_t count;
2381
    } __attribute__((packed)) req = {
5✔
2382
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_GETCAPABILITY),
5✔
2383
        .cap = htobe32(cap),
5✔
2384
        .prop = htobe32(prop),
5✔
2385
        .count = htobe32(1),
5✔
2386
    };
2387
    unsigned char tpmresp[27];
5✔
2388
    size_t tpmresp_len = sizeof(tpmresp);
5✔
2389
    uint32_t val;
5✔
2390
    int ret;
5✔
2391

2392
    ret = transfer(self, &req, sizeof(req), "TPM2_GetCapability", FALSE,
5✔
2393
                   tpmresp, &tpmresp_len, TPM2_DURATION_SHORT);
2394
    if (ret != 0)
5✔
2395
        return 1;
2396

2397
    memcpy(&val, &tpmresp[23], sizeof(val));
5✔
2398
    *res = be32toh(val);
5✔
2399

2400
    return 0;
5✔
2401
}
2402

2403
static const struct swtpm2_ops swtpm_tpm2_ops = {
2404
    .shutdown = swtpm_tpm2_shutdown,
2405
    .create_spk = swtpm_tpm2_create_spk,
2406
    .create_ek = swtpm_tpm2_create_ek,
2407
    .create_iak = swtpm_tpm2_create_iak,
2408
    .create_idevid = swtpm_tpm2_create_idevid,
2409
    .get_all_pcr_banks = swtpm_tpm2_get_all_pcr_banks,
2410
    .set_active_pcr_banks = swtpm_tpm2_set_active_pcr_banks,
2411
    .write_ek_cert_nvram = swtpm_tpm2_write_ek_cert_nvram,
2412
    .write_platform_cert_nvram = swtpm_tpm2_write_platform_cert_nvram,
2413
    .write_iak_cert_nvram = swtpm_tpm2_write_iak_cert_nvram,
2414
    .write_idevid_cert_nvram = swtpm_tpm2_write_idevid_cert_nvram,
2415
    .get_active_profile = swtpm_tpm2_get_active_profile,
2416
    .get_capability = swtpm_tpm2_get_capability,
2417
};
2418

2419
/*
2420
 * TPM 1.2 support
2421
 */
2422
#define TPM_TAG_RQU_COMMAND       0x00c1
2423
#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
2424

2425
#define TPM_ORD_OIAP                     0x0000000A
2426
#define TPM_ORD_TAKE_OWNERSHIP           0x0000000D
2427
#define TPM_ORD_PHYSICAL_ENABLE          0x0000006F
2428
#define TPM_ORD_PHYSICAL_SET_DEACTIVATED 0x00000072
2429
#define TPM_ORD_NV_DEFINE_SPACE          0x000000CC
2430
#define TPM_ORD_NV_WRITE_VALUE           0x000000CD
2431
#define TSC_ORD_PHYSICAL_PRESENCE        0x4000000A
2432

2433
#define TPM_ST_CLEAR 0x0001
2434

2435
#define TPM_PHYSICAL_PRESENCE_CMD_ENABLE  0x0020
2436
#define TPM_PHYSICAL_PRESENCE_PRESENT     0x0008
2437

2438
#define TPM_ALG_RSA 0x00000001
2439

2440
#define TPM_KEY_STORAGE 0x0011
2441

2442
#define TPM_AUTH_ALWAYS 0x01
2443

2444
#define TPM_PID_OWNER  0x0005
2445

2446
#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003
2447
#define TPM_SS_NONE 0x0001
2448

2449
#define TPM_TAG_PCR_INFO_LONG   0x0006
2450
#define TPM_TAG_NV_ATTRIBUTES   0x0017
2451
#define TPM_TAG_NV_DATA_PUBLIC  0x0018
2452
#define TPM_TAG_KEY12           0x0028
2453

2454
#define TPM_LOC_ZERO   0x01
2455
#define TPM_LOC_ALL    0x1f
2456

2457
#define TPM_NV_INDEX_D_BIT        0x10000000
2458
#define TPM_NV_INDEX_EKCERT       0xF000
2459
#define TPM_NV_INDEX_PLATFORMCERT 0xF002
2460

2461
#define TPM_NV_INDEX_LOCK 0xFFFFFFFF
2462

2463
#define TPM_NV_PER_OWNERREAD   0x00020000
2464
#define TPM_NV_PER_OWNERWRITE  0x00000002
2465

2466
#define TPM_ET_OWNER 0x02
2467
#define TPM_ET_NV    0x0b
2468

2469
#define TPM_KH_EK    0x40000006
2470

2471
#define TPM_DURATION_SHORT  ( 2000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
2472
#define TPM_DURATION_MEDIUM ( 7500 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
2473
#define TPM_DURATION_LONG   (15000 /* ms */ * ARCH_PROCESSING_DELAY_FACTOR)
2474

2475
static int swtpm_tpm12_tsc_physicalpresence(struct swtpm *self, uint16_t physicalpresence)
52✔
2476
{
2477
    struct tpm12_tsc_physicalpresence {
52✔
2478
        struct tpm_req_header hdr;
2479
        uint16_t pp;
2480
    } req = {
52✔
2481
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TSC_ORD_PHYSICAL_PRESENCE),
52✔
2482
        .pp = htobe16(physicalpresence),
52✔
2483
    };
2484

2485
    /* use medium duration to avoid t/o on busy system */
2486
    return transfer(self, &req, sizeof(req), "TSC_PhysicalPresence", FALSE,
52✔
2487
                    NULL, NULL, TPM_DURATION_MEDIUM);
2488
}
2489

2490
static int swtpm_tpm12_physical_enable(struct swtpm *self)
26✔
2491
{
2492
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_ENABLE);
26✔
2493

2494
    return transfer(self, &req, sizeof(req), "TPM_PhysicalEnable", FALSE,
26✔
2495
                    NULL, NULL, TPM_DURATION_SHORT);
2496
}
2497

2498
static int swtpm_tpm12_physical_set_deactivated(struct swtpm *self, uint8_t state)
26✔
2499
{
2500
    struct tpm12_tsc_physical_set_deactivated {
26✔
2501
        struct tpm_req_header hdr;
2502
        uint8_t state;
2503
    } req = {
26✔
2504
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_SET_DEACTIVATED),
26✔
2505
        .state = state,
2506
    };
2507

2508
    return transfer(self, &req, sizeof(req), "TSC_PhysicalSetDeactivated", FALSE,
26✔
2509
                    NULL, NULL, TPM_DURATION_SHORT);
2510
}
2511

2512
/* Initialize the TPM1.2 */
2513
static int swtpm_tpm12_run_swtpm_bios(struct swtpm *self)
26✔
2514
{
2515
    if (swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_CMD_ENABLE) ||
52✔
2516
        swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_PRESENT) ||
52✔
2517
        swtpm_tpm12_physical_enable(self) ||
52✔
2518
        swtpm_tpm12_physical_set_deactivated(self, 0))
26✔
2519
        return 1;
×
2520

2521
    return 0;
2522
}
2523

2524
static int swptm_tpm12_create_endorsement_keypair(struct swtpm *self,
19✔
2525
                                                  gchar **pubek, size_t *pubek_len)
2526
{
2527
    unsigned char req[] = {
19✔
2528
        0x00, 0xc1, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x78, 0x38, 0xf0, 0x30, 0x81, 0x07, 0x2b,
2529
        0x0c, 0xa9, 0x10, 0x98, 0x08, 0xc0, 0x4B, 0x05, 0x11, 0xc9, 0x50, 0x23, 0x52, 0xc4, 0x00, 0x00,
2530
        0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2531
        0x00, 0x02, 0x00, 0x00, 0x00, 0x00
2532
    };
2533
    unsigned char tpmresp[512];
19✔
2534
    size_t tpmresp_len = sizeof(tpmresp);
19✔
2535
    uint32_t length;
19✔
2536
    int ret;
19✔
2537

2538
    ret = transfer(self, &req, sizeof(req), "TPM_CreateEndorsementKeyPair", FALSE,
19✔
2539
                   &tpmresp, &tpmresp_len, TPM_DURATION_LONG);
2540
    if (ret != 0)
19✔
2541
        return 1;
2542

2543
    if (tpmresp_len < 34 + sizeof(length))
19✔
2544
        goto err_too_short;
×
2545
    memcpy(&length, &tpmresp[34], sizeof(length));
19✔
2546
    length = be32toh(length);
19✔
2547
    if (length != 256) {
19✔
2548
        logerr(self->logfile, "Offset to EK Public key is wrong.\n");
×
2549
        return 1;
×
2550
    }
2551

2552
    *pubek_len = 256;
19✔
2553
    if (tpmresp_len < 38 + *pubek_len)
19✔
2554
        goto err_too_short;
×
2555
    *pubek = g_malloc(256);
19✔
2556
    memcpy(*pubek, &tpmresp[38], *pubek_len);
19✔
2557

2558
    return 0;
19✔
2559

2560
err_too_short:
×
2561
    logerr(self->logfile, "Response from TPM_CreateEndorsementKeyPair is too short!\n");
×
2562
    return 1;
×
2563
}
2564

2565
/* Create an OIAP session */
2566
static int swtpm_tpm12_oiap(struct swtpm *self, uint32_t *authhandle, unsigned char nonce_even[SHA_DIGEST_LENGTH])
9✔
2567
{
2568
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_OIAP);
9✔
2569
    unsigned char tpmresp[64];
9✔
2570
    size_t tpmresp_len = sizeof(tpmresp);
9✔
2571
    int ret;
9✔
2572

2573
    ret = transfer(self, &req, sizeof(req), "TPM_OIAP", FALSE,
9✔
2574
                   &tpmresp, &tpmresp_len, TPM_DURATION_SHORT);
2575
    if (ret != 0)
9✔
2576
        return ret;
2577

2578
    if (tpmresp_len < 10 + sizeof(*authhandle) || tpmresp_len < 14 + SHA_DIGEST_LENGTH)
9✔
2579
        goto err_too_short;
×
2580
    memcpy(authhandle, &tpmresp[10], sizeof(*authhandle));
9✔
2581
    *authhandle = be32toh(*authhandle);
9✔
2582
    memcpy(nonce_even, &tpmresp[14], SHA_DIGEST_LENGTH);
9✔
2583

2584
    return 0;
9✔
2585

2586
err_too_short:
×
2587
    logerr(self->logfile, "Response from TPM_OIAP is too short!\n");
×
2588
    return 1;
×
2589
}
2590

2591
static int swtpm_tpm12_take_ownership(struct swtpm *self, const unsigned char ownerpass_digest[SHA_DIGEST_LENGTH],
9✔
2592
                                      const unsigned char srkpass_digest[SHA_DIGEST_LENGTH],
2593
                                      const unsigned char *pubek, size_t pubek_len)
2594
{
2595
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_AUTH1_COMMAND, 0, TPM_ORD_TAKE_OWNERSHIP);
9✔
2596
    EVP_PKEY *pkey = NULL;
9✔
2597
    EVP_PKEY_CTX *ctx = NULL;
9✔
2598
    BIGNUM *exp = BN_new();
9✔
2599
    BIGNUM *mod = NULL;
9✔
2600
#if OPENSSL_VERSION_NUMBER < 0x30000000L
2601
    RSA *rsakey = RSA_new();
2602
#endif
2603
    int ret = 1;
9✔
2604
    const EVP_MD *sha1 = EVP_sha1();
9✔
2605
    g_autofree unsigned char *enc_owner_auth = g_malloc(pubek_len);
9✔
2606
    size_t enc_owner_auth_len = pubek_len;
9✔
2607
    g_autofree unsigned char *enc_srk_auth = g_malloc(pubek_len);
18✔
2608
    size_t enc_srk_auth_len = pubek_len;
9✔
2609
    uint32_t auth_handle;
9✔
2610
    unsigned char nonce_even[SHA_DIGEST_LENGTH];
9✔
2611
    unsigned char nonce_odd[SHA_DIGEST_LENGTH] = {1, 2, 3, 4, 5, 6, };
9✔
2612
    g_autofree unsigned char *tpm_rsa_key_parms = NULL;
9✔
2613
    ssize_t tpm_rsa_key_parms_len;
9✔
2614
    g_autofree unsigned char *tpm_key_parms = NULL;
9✔
2615
    ssize_t tpm_key_parms_len;
9✔
2616
    g_autofree unsigned char *tpm_key12 = NULL;
9✔
2617
    ssize_t tpm_key12_len;
9✔
2618
    g_autofree unsigned char *in_auth_setup_params = NULL;
9✔
2619
    ssize_t in_auth_setup_params_len;
9✔
2620
    g_autofree unsigned char *macinput = NULL;
9✔
2621
    ssize_t macinput_len;
9✔
2622
    unsigned char in_param_digest[SHA_DIGEST_LENGTH];
9✔
2623
    unsigned char owner_auth[SHA_DIGEST_LENGTH];
9✔
2624
    unsigned int owner_auth_len = sizeof(owner_auth);
9✔
2625
    uint8_t continue_auth_session = 0;
9✔
2626
    unsigned char req[1024];
9✔
2627
    ssize_t req_len, len;
9✔
2628
    struct tpm_req_header *trh;
9✔
2629

2630
    mod = BN_bin2bn((const unsigned char *)pubek, pubek_len, NULL);
9✔
2631
    if (exp == NULL || mod == NULL ||
18✔
2632
        BN_hex2bn(&exp, "10001") == 0) {
9✔
2633
        logerr(self->logfile, "Could not create public RSA key!\n");
×
2634
        goto error_free_bn;
×
2635
    }
2636

2637
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
2638
    ctx = EVP_PKEY_CTX_new_from_name(NULL, "rsa", NULL);
9✔
2639
    if (ctx != NULL) {
9✔
2640
        OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
9✔
2641
        OSSL_PARAM *params;
9✔
2642

2643
        if (bld == NULL ||
18✔
2644
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, exp) != 1 ||
18✔
2645
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, mod) != 1 ||
9✔
2646
            (params = OSSL_PARAM_BLD_to_param(bld)) == NULL) {
9✔
2647
            OSSL_PARAM_BLD_free(bld);
×
2648
            goto error_free_bn;
×
2649
        }
2650
        OSSL_PARAM_BLD_free(bld);
9✔
2651

2652
        if (EVP_PKEY_fromdata_init(ctx) != 1 ||
18✔
2653
            EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) != 1) {
9✔
2654
            logerr(self->logfile, "Could not set pkey parameters!\n");
×
2655
            OSSL_PARAM_free(params);
×
2656
            goto error_free_bn;
×
2657
        }
2658
        OSSL_PARAM_free(params);
9✔
2659

2660
        EVP_PKEY_CTX_free(ctx);
9✔
2661
    } else {
2662
        logerr(self->logfile, "Could not create key creation context!\n");
×
2663
        goto error_free_bn;
×
2664
    }
2665
    ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
9✔
2666
    if (ctx == NULL)
9✔
2667
        goto error_free_bn;
×
2668
#else
2669
    pkey = EVP_PKEY_new();
2670
    if (pkey == NULL) {
2671
        logerr(self->logfile, "Could not allocate pkey!\n");
2672
        goto error_free_bn;
2673
    }
2674

2675
# if OPENSSL_VERSION_NUMBER < 0x10100000
2676
    rsakey->n = mod;
2677
    rsakey->e = exp;
2678
# else
2679
    if (RSA_set0_key(rsakey, mod, exp, NULL) != 1) {
2680
        logerr(self->logfile, "Could not create public RSA key!\n");
2681
        goto error_free_bn;
2682
    }
2683
# endif
2684
    if (EVP_PKEY_assign_RSA(pkey, rsakey) != 1) {
2685
        logerr(self->logfile, "Could not create public RSA key!\n");
2686
        goto error_free_pkey_and_rsa;
2687
    }
2688

2689
    ctx = EVP_PKEY_CTX_new(pkey, NULL);
2690
    if (ctx == NULL)
2691
        goto error_free_pkey;
2692
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
2693

2694
    if (EVP_PKEY_encrypt_init(ctx) < 1 ||
18✔
2695
        EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) < 1 ||
18✔
2696
        EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sha1) < 1 ||
18✔
2697
        EVP_PKEY_CTX_set_rsa_oaep_md(ctx, sha1) < 1 ||
18✔
2698
        EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, g_strdup("TCPA"), 4) < 1 ||
18✔
2699
        EVP_PKEY_encrypt(ctx, enc_owner_auth, &enc_owner_auth_len,
9✔
2700
                         ownerpass_digest, SHA_DIGEST_LENGTH) < 1||
9✔
2701
        EVP_PKEY_encrypt(ctx, enc_srk_auth, &enc_srk_auth_len,
9✔
2702
                         srkpass_digest, SHA_DIGEST_LENGTH) < 1) {
2703
        logerr(self->logfile, "Internal error in %s: encryption failed\n", __func__);
×
2704
        goto error;
×
2705
    }
2706
    ret = swtpm_tpm12_oiap(self, &auth_handle, nonce_even);
9✔
2707
    if (ret != 0)
9✔
2708
        goto error;
×
2709

2710
    tpm_rsa_key_parms_len = memconcat(&tpm_rsa_key_parms,
18✔
2711
                                      (unsigned char[]){
9✔
2712
                                          AS4BE(2048), AS4BE(2), AS4BE(0)
2713
                                      }, (size_t)12,
2714
                                      NULL);
2715
    if (tpm_rsa_key_parms_len < 0) {
9✔
2716
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2717
        goto error;
×
2718
    }
2719

2720
    tpm_key_parms_len = memconcat(&tpm_key_parms,
18✔
2721
                                  (unsigned char[]){
9✔
2722
                                      AS4BE(TPM_ALG_RSA),
2723
                                      AS2BE(TPM_ES_RSAESOAEP_SHA1_MGF1),
2724
                                      AS2BE(TPM_SS_NONE),
2725
                                      AS4BE(tpm_rsa_key_parms_len)}, (size_t)12,
9✔
2726
                                  tpm_rsa_key_parms, tpm_rsa_key_parms_len,
2727
                                  NULL);
2728
    if (tpm_key_parms_len < 0) {
9✔
2729
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2730
        goto error;
×
2731
    }
2732

2733
    tpm_key12_len = memconcat(&tpm_key12,
18✔
2734
                              (unsigned char[]){
9✔
2735
                                  AS2BE(TPM_TAG_KEY12), AS2BE(0),
2736
                                  AS2BE(TPM_KEY_STORAGE), AS4BE(0), TPM_AUTH_ALWAYS
2737
                              }, (size_t)11,
2738
                              tpm_key_parms, tpm_key_parms_len,
2739
                              (unsigned char[]){AS4BE(0), AS4BE(0), AS4BE(0)}, (size_t)12,
9✔
2740
                              NULL);
2741
    if (tpm_key12_len < 0) {
9✔
2742
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2743
        goto error;
×
2744
    }
2745

2746
    req_len = concat(req, sizeof(req),
18✔
2747
                     &hdr, sizeof(hdr),
2748
                     (unsigned char[]){AS2BE(TPM_PID_OWNER), AS4BE(enc_owner_auth_len)}, (size_t)6,
9✔
2749
                     enc_owner_auth, enc_owner_auth_len,
2750
                     (unsigned char[]){AS4BE(enc_srk_auth_len)}, (size_t)4,
9✔
2751
                     enc_srk_auth, enc_srk_auth_len,
2752
                     tpm_key12, tpm_key12_len,
2753
                     NULL);
2754
    if (req_len < 0) {
9✔
2755
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
2756
        goto error;
×
2757
    }
2758
    SHA1(&req[6], req_len - 6, in_param_digest);
9✔
2759

2760
    in_auth_setup_params_len = memconcat(&in_auth_setup_params,
9✔
2761
                                         nonce_even, sizeof(nonce_even),
2762
                                         nonce_odd, sizeof(nonce_odd),
2763
                                         &continue_auth_session, (size_t)1,
2764
                                         NULL);
2765
    if (in_auth_setup_params_len < 0) {
9✔
2766
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2767
        goto error;
×
2768
    }
2769

2770
    macinput_len = memconcat(&macinput,
9✔
2771
                             in_param_digest, sizeof(in_param_digest),
2772
                             in_auth_setup_params, in_auth_setup_params_len,
2773
                             NULL);
2774
    if (macinput_len < 0) {
9✔
2775
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2776
        goto error;
×
2777
    }
2778

2779
    HMAC(sha1, ownerpass_digest, SHA_DIGEST_LENGTH, macinput, macinput_len,
9✔
2780
         owner_auth, &owner_auth_len);
2781

2782
    len = concat(&req[req_len], sizeof(req) - req_len,
18✔
2783
                 (unsigned char[]){AS4BE(auth_handle)}, (size_t)4,
9✔
2784
                 nonce_odd, sizeof(nonce_odd),
2785
                 &continue_auth_session, (size_t)1,
2786
                 owner_auth, owner_auth_len,
2787
                 NULL);
2788
    if (len < 0) {
9✔
2789
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
2790
        goto error;
×
2791
    }
2792
    req_len += len;
9✔
2793

2794
    trh = (struct tpm_req_header *)req; /* old gcc type-punned pointer */
9✔
2795
    trh->size = htobe32(req_len);
9✔
2796

2797
    ret = transfer(self, req, req_len, "TPM_TakeOwnership", FALSE,
9✔
2798
                   NULL, NULL, TPM_DURATION_LONG);
2799

2800
error:
9✔
2801
    EVP_PKEY_free(pkey);
9✔
2802
    EVP_PKEY_CTX_free(ctx);
9✔
2803
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
2804
    BN_free(exp);
9✔
2805
    BN_free(mod);
9✔
2806
#endif
2807
    return ret;
9✔
2808

2809
error_free_bn:
×
2810
    BN_free(exp);
×
2811
    BN_free(mod);
×
2812

2813
#if OPENSSL_VERSION_NUMBER < 0x30000000L
2814
error_free_pkey_and_rsa:
2815
    RSA_free(rsakey);
2816
error_free_pkey:
2817
#else
2818
    EVP_PKEY_CTX_free(ctx);
×
2819
#endif
2820
    EVP_PKEY_free(pkey);
×
2821

2822
    return 1;
×
2823
}
2824

2825
static int swtpm_tpm12_nv_define_space(struct swtpm *self, uint32_t nvindex,
27✔
2826
                                       uint32_t nvindexattrs, size_t size)
2827
{
2828
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_DEFINE_SPACE);
27✔
2829
    g_autofree unsigned char *pcr_info_short = NULL;
54✔
2830
    ssize_t pcr_info_short_len;
27✔
2831
    g_autofree unsigned char *nv_data_public = NULL;
27✔
2832
    ssize_t nv_data_public_len;
27✔
2833
    g_autofree unsigned char *req = NULL;
27✔
2834
    ssize_t req_len;
27✔
2835
    unsigned char zeroes[SHA_DIGEST_LENGTH] = {0, };
27✔
2836

2837
    pcr_info_short_len = memconcat(&pcr_info_short,
54✔
2838
                                   (unsigned char[]){AS2BE(3), 0, 0, 0, TPM_LOC_ALL}, (size_t)6,
27✔
2839
                                   zeroes, sizeof(zeroes),
2840
                                   NULL);
2841
    if (pcr_info_short_len < 0) {
27✔
2842
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2843
        return 1;
×
2844
    }
2845

2846
    nv_data_public_len = memconcat(&nv_data_public,
54✔
2847
                                   (unsigned char[]){
27✔
2848
                                       AS2BE(TPM_TAG_NV_DATA_PUBLIC), AS4BE(nvindex)
27✔
2849
                                   }, (size_t)6,
2850
                                   pcr_info_short, pcr_info_short_len,
2851
                                   pcr_info_short, pcr_info_short_len,
2852
                                   (unsigned char[]){
27✔
2853
                                       AS2BE(TPM_TAG_NV_ATTRIBUTES), AS4BE(nvindexattrs),
27✔
2854
                                       0, 0, 0, AS4BE(size)
27✔
2855
                                   }, (size_t)13,
2856
                                   NULL);
2857
    if (nv_data_public_len < 0) {
27✔
2858
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2859
        return 1;
×
2860
    }
2861

2862
    req_len = memconcat(&req,
27✔
2863
                        &hdr, sizeof(hdr),
2864
                        nv_data_public, nv_data_public_len,
2865
                        zeroes, sizeof(zeroes),
2866
                        NULL);
2867
    if (req_len < 0) {
27✔
2868
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2869
        return 1;
×
2870
    }
2871

2872
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
27✔
2873

2874
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE,
27✔
2875
                    NULL, NULL, TPM_DURATION_SHORT);
2876
}
2877

2878
static int swtpm_tpm12_nv_write_value(struct swtpm *self, uint32_t nvindex,
15✔
2879
                                      const unsigned char *data, size_t data_len)
2880
{
2881
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_WRITE_VALUE);
15✔
2882
    g_autofree unsigned char *req = NULL;
30✔
2883
    ssize_t req_len;
15✔
2884

2885
    req_len = memconcat(&req,
30✔
2886
                        &hdr, sizeof(hdr),
2887
                        (unsigned char[]){AS4BE(nvindex), AS4BE(0), AS4BE(data_len)}, (size_t)12,
15✔
2888
                        data, data_len,
2889
                        NULL);
2890
    if (req_len < 0) {
15✔
2891
        logerr(self->logfile, "Internal error in %s: out of memory\n", __func__);
×
2892
        return 1;
×
2893
    }
2894

2895
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
15✔
2896

2897
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE,
15✔
2898
                    NULL, NULL, TPM_DURATION_SHORT);
2899
}
2900

2901
/* Write the EK Certificate into NVRAM */
2902
static int swtpm_tpm12_write_ek_cert_nvram(struct swtpm *self,
8✔
2903
                                           const unsigned char *data, size_t data_len)
2904
{
2905
    uint32_t nvindex = TPM_NV_INDEX_EKCERT | TPM_NV_INDEX_D_BIT;
8✔
2906
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
8✔
2907
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
2908
    if (ret != 0)
8✔
2909
        return 1;
2910

2911
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
8✔
2912
    if (ret != 0)
8✔
2913
        return 1;
2914

2915
    return 0;
2916
}
2917

2918
/* Write the Platform Certificate into NVRAM */
2919
static int swtpm_tpm12_write_platform_cert_nvram(struct swtpm *self,
7✔
2920
                                                 const unsigned char *data, size_t data_len)
2921
{
2922
    uint32_t nvindex = TPM_NV_INDEX_PLATFORMCERT | TPM_NV_INDEX_D_BIT;
7✔
2923
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
7✔
2924
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
2925
    if (ret != 0)
7✔
2926
        return 1;
2927

2928
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
7✔
2929
    if (ret != 0)
7✔
2930
        return 1;
2931

2932
    return 0;
2933
}
2934

2935
static int swtpm_tpm12_nv_lock(struct swtpm *self)
12✔
2936
{
2937
    return swtpm_tpm12_nv_define_space(self, TPM_NV_INDEX_LOCK, 0, 0);
12✔
2938
}
2939

2940
static const struct swtpm12_ops swtpm_tpm12_ops = {
2941
    .run_swtpm_bios = swtpm_tpm12_run_swtpm_bios,
2942
    .create_endorsement_key_pair = swptm_tpm12_create_endorsement_keypair,
2943
    .take_ownership = swtpm_tpm12_take_ownership,
2944
    .write_ek_cert_nvram = swtpm_tpm12_write_ek_cert_nvram,
2945
    .write_platform_cert_nvram = swtpm_tpm12_write_platform_cert_nvram,
2946
    .nv_lock = swtpm_tpm12_nv_lock,
2947
};
2948

2949
static void swtpm_init(struct swtpm *swtpm,
155✔
2950
                       gchar **swtpm_exec_l, const gchar *state_path,
2951
                       const gchar *keyopts, const gchar *logfile,
2952
                       int *fds_to_pass, size_t n_fds_to_pass,
2953
                       gboolean is_tpm2, const gchar *json_profile,
2954
                       int json_profile_fd,
2955
                       const gchar *profile_remove_disabled_param)
2956
{
2957
    swtpm->cops = &swtpm_cops;
155✔
2958
    swtpm->swtpm_exec_l = swtpm_exec_l;
155✔
2959
    swtpm->state_path = state_path;
155✔
2960
    swtpm->keyopts = keyopts;
155✔
2961
    swtpm->logfile = logfile;
155✔
2962
    swtpm->fds_to_pass = fds_to_pass;
155✔
2963
    swtpm->n_fds_to_pass = n_fds_to_pass;
155✔
2964
    swtpm->is_tpm2 = is_tpm2;
155✔
2965
    swtpm->json_profile = json_profile;
155✔
2966
    swtpm->json_profile_fd = json_profile_fd;
155✔
2967
    swtpm->profile_remove_disabled_param = profile_remove_disabled_param;
155✔
2968

2969
    swtpm->pid = -1;
155✔
2970
    swtpm->ctrl_fds[0] = swtpm->ctrl_fds[1] = -1;
155✔
2971
    swtpm->data_fds[0] = swtpm->data_fds[1] = -1;
155✔
2972
}
2973

2974
struct swtpm12 *swtpm12_new(gchar **swtpm_exec_l, const gchar *state_path,
26✔
2975
                            const gchar *keyopts, const gchar *logfile,
2976
                            int *fds_to_pass, size_t n_fds_to_pass)
2977
{
2978
    struct swtpm12 *swtpm12 = g_malloc0(sizeof(struct swtpm12));
26✔
2979

2980
    swtpm_init(&swtpm12->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
26✔
2981
               fds_to_pass, n_fds_to_pass, FALSE, NULL, 0, NULL);
2982
    swtpm12->ops = &swtpm_tpm12_ops;
26✔
2983

2984
    return swtpm12;
26✔
2985
}
2986

2987
struct swtpm2 *swtpm2_new(gchar **swtpm_exec_l, const gchar *state_path,
129✔
2988
                         const gchar *keyopts, const gchar *logfile,
2989
                         int *fds_to_pass, size_t n_fds_to_pass,
2990
                         const gchar *json_profile, int json_profile_fd,
2991
                         const gchar *profile_remove_disabled_param)
2992
{
2993
    struct swtpm2 *swtpm2 = g_malloc0(sizeof(struct swtpm2));
129✔
2994

2995
    swtpm_init(&swtpm2->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
129✔
2996
               fds_to_pass, n_fds_to_pass, TRUE, json_profile, json_profile_fd,
2997
               profile_remove_disabled_param);
2998
    swtpm2->ops = &swtpm_tpm2_ops;
129✔
2999

3000
    return swtpm2;
129✔
3001
}
3002

3003
void swtpm_free(struct swtpm *swtpm) {
155✔
3004
    if (!swtpm)
155✔
3005
        return;
3006
    g_free(swtpm);
155✔
3007
}
3008

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

© 2026 Coveralls, Inc