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

stefanberger / swtpm / #2758

24 Feb 2025 12:35PM UTC coverage: 73.297% (-0.03%) from 73.325%
#2758

push

travis-ci

web-flow
Merge bf5eb49cb into 0528ac733

8029 of 10954 relevant lines covered (73.3%)

13618.17 hits per line

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

83.08
/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

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

48
#define CMD_DURATION_SHORT  2000 /* ms */
49

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

212
    close(pidfile_fd);
141✔
213
    unlink(pidfile);
141✔
214

215
error_no_pidfile:
141✔
216
    return ret;
141✔
217
}
218

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

225
    if (self->pid > 0) {
139✔
226
        self->cops->ctrl_shutdown(self);
134✔
227
        for (c = 0; c < 500; c++) {
523✔
228
            if (kill(self->pid, 0) < 0) {
389✔
229
                ended = TRUE;
230
                break;
231
            }
232
            usleep(1000);
255✔
233
        }
234
        if (!ended)
134✔
235
            kill(self->pid, SIGKILL);
×
236
        waitpid(self->pid, NULL, 0);
134✔
237

238
        self->pid = 0;
134✔
239
    }
240

241
    swtpm_close_comm(self, true);
139✔
242
}
139✔
243

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

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

265
    if (use_ctrl) {
1,279✔
266
        sockfd = self->ctrl_fds[0];
312✔
267
        offset = 0;
312✔
268
    } else {
269
        sockfd = self->data_fds[0];
967✔
270
        offset = 6;
967✔
271
    }
272

273
    n = write(sockfd, buffer, buffer_len);
1,279✔
274
    if (n < 0) {
1,279✔
275
        logerr(self->logfile, "Could not send %s buffer to swtpm: %s\n",
4✔
276
               cmdname, strerror(errno));
2✔
277
        return 1;
2✔
278
    }
279
    if ((size_t)n != buffer_len) {
1,277✔
280
        logerr(self->logfile, "Could not send all bytes to swtpm: %zu < %zu\n",
×
281
               (size_t)n, buffer_len);
282
        return 1;
×
283
    }
284

285
    fds.fd = sockfd;
1,277✔
286
    n = poll(&fds, 1, timeout_ms);
1,277✔
287
    if (n != 1 || (fds.revents & POLLIN) == 0) {
1,277✔
288
        logerr(self->logfile, "Could not receive response to %s from swtpm: %s\n",
×
289
               cmdname, strerror(errno));
×
290
        return 1;
×
291
    }
292

293
    resplen = read(sockfd, resp, sizeof(resp));
1,277✔
294
    if (resplen < 0) {
1,277✔
295
        logerr(self->logfile, "Could not receive response to %s from swtpm: %s\n",
×
296
               cmdname, strerror(errno));
×
297
        return 1;
×
298
    }
299

300
    if (!use_ctrl) {
1,277✔
301
        if ((size_t)resplen < sizeof(struct tpm_resp_header)) {
967✔
302
            logerr(self->logfile,
×
303
                   "Response for %s has only %d bytes.\n", cmdname, resplen);
304
            return 1;
×
305
        }
306
    } else if ((size_t)resplen < 4) {
310✔
307
        logerr(self->logfile,
×
308
               "Response for %s has only %d bytes.\n", cmdname, resplen);
309
        return 1;
×
310
    }
311

312
    memcpy(&returncode, &resp[offset], sizeof(returncode));
1,277✔
313
    returncode = be32toh(returncode);
1,277✔
314
    if (returncode != 0) {
1,277✔
315
        logerr(self->logfile,
×
316
               "%s failed: 0x%x\n", cmdname, returncode);
317
        return 1;
×
318
    }
319

320
    if (respbuffer) {
1,277✔
321
        *respbuffer_len = min((size_t)resplen, *respbuffer_len);
393✔
322
        memcpy(respbuffer, resp, *respbuffer_len);
393✔
323
    }
324

325
    return 0;
326
}
327

328
/* Send a CMD_SHUTDOWN over the control channel */
329
static int swtpm_ctrl_shutdown(struct swtpm *self)
134✔
330
{
331
    uint32_t cmd = htobe32(CMD_SHUTDOWN);
134✔
332

333
    return transfer(self, &cmd, sizeof(cmd), "CMD_SHUTDOWN", TRUE,
134✔
334
                    NULL, NULL, CMD_DURATION_SHORT);
335
}
336

337
/* Get the TPM specification parameters over the control channel */
338
static int do_cmd_get_info(struct swtpm *self, uint64_t swtpm_info_flags,
178✔
339
                           gchar **result)
340
{
341
    unsigned char req[] = {AS4BE(CMD_GET_INFO),
178✔
342
                           AS8BE(swtpm_info_flags),
178✔
343
                           AS4BE(0), AS4BE(0)};
344
    unsigned char tpmresp[16 * 1024];
178✔
345
    size_t tpmresp_len = sizeof(tpmresp);
178✔
346
    int ret;
178✔
347
    uint32_t length;
178✔
348

349
    ret = transfer(self, req, sizeof(req), "CMD_GET_INFO", TRUE,
178✔
350
                   tpmresp, &tpmresp_len, CMD_DURATION_SHORT);
351
    if (ret != 0)
178✔
352
        return 1;
353

354
    if (tpmresp_len < 8 + sizeof(length))
176✔
355
        goto err_too_short;
×
356
    memcpy(&length, &tpmresp[8], sizeof(length));
176✔
357
    length = htobe32(length);
176✔
358

359
    if (tpmresp_len < 12 + length)
176✔
360
        goto err_too_short;
×
361
    *result = g_strndup((gchar *)&tpmresp[12], length);
176✔
362

363
    return 0;
176✔
364

365
err_too_short:
×
366
    logerr(self->logfile, "Response from CMD_GET_INFO is too short!\n");
×
367

368
    return 1;
×
369
}
370

371
static int swtpm_ctrl_get_tpm_specs_and_attrs(struct swtpm *self, gchar **result)
74✔
372
{
373
    return do_cmd_get_info(self,
74✔
374
                           SWTPM_INFO_TPMSPECIFICATION | SWTPM_INFO_TPMATTRIBUTES,
375
                           result);
376
}
377

378
static const struct swtpm_cops swtpm_cops = {
379
    .start = swtpm_start,
380
    .stop = swtpm_stop,
381
    .destroy = swtpm_destroy,
382
    .ctrl_shutdown = swtpm_ctrl_shutdown,
383
    .ctrl_get_tpm_specs_and_attrs = swtpm_ctrl_get_tpm_specs_and_attrs,
384
};
385

386
/*
387
 * TPM 2 support
388
 */
389

390
#define TPM2_ST_NO_SESSIONS  0x8001
391
#define TPM2_ST_SESSIONS     0x8002
392

393
#define TPM2_CC_EVICTCONTROL   0x00000120
394
#define TPM2_CC_NV_DEFINESPACE 0x0000012a
395
#define TPM2_CC_PCR_ALLOCATE   0x0000012b
396
#define TPM2_CC_CREATEPRIMARY  0x00000131
397
#define TPM2_CC_NV_WRITE       0x00000137
398
#define TPM2_CC_NV_WRITELOCK   0x00000138
399
#define TPM2_CC_SHUTDOWN       0x00000145
400
#define TPM2_CC_FLUSHCONTEXT   0x00000165
401
#define TPM2_CC_GETCAPABILITY  0x0000017a
402

403
#define TPM2_SU_CLEAR        0x0000
404

405
#define TPM2_RH_OWNER        0x40000001
406
#define TPM2_RS_PW           0x40000009
407
#define TPM2_RH_ENDORSEMENT  0x4000000b
408
#define TPM2_RH_PLATFORM     0x4000000c
409

410
#define TPM2_ALG_RSA      0x0001
411
#define TPM2_ALG_SHA1     0x0004
412
#define TPM2_ALG_AES      0x0006
413
#define TPM2_ALG_SHA256   0x000b
414
#define TPM2_ALG_SHA384   0x000c
415
#define TPM2_ALG_SHA512   0x000d
416
#define TPM2_ALG_SHA3_256 0x0027
417
#define TPM2_ALG_SHA3_384 0x0028
418
#define TPM2_ALG_SHA3_512 0x0029
419
#define TPM2_ALG_NULL     0x0010
420
#define TPM2_ALG_SM3      0x0012
421
#define TPM2_ALG_ECC      0x0023
422
#define TPM2_ALG_CFB      0x0043
423

424
#define TPM2_CAP_PCRS     0x00000005
425

426
#define TPM2_ECC_NIST_P384 0x0004
427

428
#define TPMA_NV_PLATFORMCREATE 0x40000000
429
#define TPMA_NV_AUTHREAD       0x40000
430
#define TPMA_NV_NO_DA          0x2000000
431
#define TPMA_NV_PPWRITE        0x1
432
#define TPMA_NV_PPREAD         0x10000
433
#define TPMA_NV_OWNERREAD      0x20000
434
#define TPMA_NV_WRITEDEFINE    0x2000
435

436
// Use standard EK Cert NVRAM, EK and SRK handles per IWG spec.
437
// "TCG TPM v2.0 Provisioning Guide"; Version 1.0, Rev 1.0, March 15, 2017
438
// Table 2
439
#define TPM2_NV_INDEX_RSA2048_EKCERT         0x01c00002
440
#define TPM2_NV_INDEX_RSA2048_EKTEMPLATE     0x01c00004
441
#define TPM2_NV_INDEX_RSA3072_HI_EKCERT      0x01c0001c
442
#define TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE  0x01c0001d
443
// For ECC follow "TCG EK Credential Profile For TPM Family 2.0; Level 0"
444
// Specification Version 2.1; Revision 13; 10 December 2018
445
#define TPM2_NV_INDEX_PLATFORMCERT           0x01c08000
446

447
#define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT     0x01c00016
448
#define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE 0x01c00017
449

450
#define TPM2_EK_RSA_HANDLE           0x81010001
451
#define TPM2_EK_RSA3072_HANDLE       0x8101001c
452
#define TPM2_EK_ECC_SECP384R1_HANDLE 0x81010016
453
#define TPM2_SPK_HANDLE              0x81000001
454

455
#define TPM2_DURATION_SHORT     2000 /* ms */
456
#define TPM2_DURATION_MEDIUM    7500 /* ms */
457
#define TPM2_DURATION_LONG     15000 /* ms */
458

459
#define TPM_REQ_HEADER_INITIALIZER(TAG, SIZE, ORD) \
460
    { \
461
        .tag = htobe16(TAG), \
462
        .size = htobe32(SIZE), \
463
        .ordinal = htobe32(ORD), \
464
    }
465

466
struct tpm2_authblock {
467
    uint32_t auth;
468
    uint16_t nonceSize; // currently always 0
469
    uint8_t continueSession;
470
    uint16_t pwdSize; // currently always 0
471
} __attribute__((packed));
472

473
#define TPM2_AUTHBLOCK_INITIALIZER(AUTH) \
474
    { \
475
        .auth = htobe32(AUTH), \
476
        .nonceSize = htobe16(0), \
477
        .continueSession = 0, \
478
        .pwdSize = htobe16(0), \
479
    }
480

481
static const unsigned char NONCE_EMPTY[2] = {AS2BE(0)};
482
static const unsigned char NONCE_RSA2048[2+0x100] = {AS2BE(0x100), 0, };
483
static const unsigned char NONCE_RSA3072[2+0x180] = {AS2BE(0x180), 0, };
484
static const unsigned char NONCE_ECC_384[2+0x30] = {AS2BE(0x30), 0, };
485

486
static const struct bank_to_name {
487
    uint16_t hashAlg;
488
    const char *name;
489
} banks_to_names[] = {
490
    {TPM2_ALG_SHA1, "sha1"},
491
    {TPM2_ALG_SHA256, "sha256"},
492
    {TPM2_ALG_SHA384, "sha384"},
493
    {TPM2_ALG_SHA512, "sha512"},
494
    {TPM2_ALG_SM3, "sm3-256"},
495
    {TPM2_ALG_SHA3_256, "sha3-256"},
496
    {TPM2_ALG_SHA3_384, "sha3-384"},
497
    {TPM2_ALG_SHA3_512, "sha3-512"},
498
    {0, NULL},
499
};
500

501
/* function prototypes */
502
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
503
                                        const unsigned char *symkeydata, size_t symkeydata_len,
504
                                        const unsigned char *authpolicy, size_t authpolicy_len,
505
                                        unsigned int rsa_keysize, gboolean havenonce, size_t off,
506
                                        uint32_t *curr_handle,
507
                                        unsigned char *ektemplate, size_t *ektemplate_len,
508
                                        gchar **ekparam, const gchar **key_description);
509

510
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
511
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
512
                                  const char *purpose);
513

514
/* Given a hash algo identifier, return the name of the hash bank */
515
static const char *get_name_for_bank(uint16_t hashAlg) {
382✔
516
    size_t i;
382✔
517

518
    for (i = 0; banks_to_names[i].name; i++) {
958✔
519
        if (banks_to_names[i].hashAlg == hashAlg)
958✔
520
            return banks_to_names[i].name;
521
    }
522
    return NULL;
523
}
524

525
/* Give the name of a hash bank, return its algo identifier */
526
static uint16_t get_hashalg_by_bankname(const char *name) {
380✔
527
    size_t i;
380✔
528

529
    for (i = 0; banks_to_names[i].name; i++) {
953✔
530
        if (strcmp(banks_to_names[i].name, name) == 0)
953✔
531
            return banks_to_names[i].hashAlg;
380✔
532
    }
533
    return 0;
534
}
535

536
/* Do an SU_CLEAR shutdown of the TPM 2 */
537
static int swtpm_tpm2_shutdown(struct swtpm *self)
107✔
538
{
539
    struct tpm2_shutdown_req {
107✔
540
        struct tpm_req_header hdr;
541
        uint16_t shutdownType;
542
    } __attribute__((packed)) req = {
107✔
543
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_SHUTDOWN),
107✔
544
        .shutdownType = htobe16(TPM2_SU_CLEAR)
107✔
545
    };
546

547
    return transfer(self, &req, sizeof(req), "TPM2_Shutdown", FALSE,
107✔
548
                    NULL, NULL, TPM2_DURATION_SHORT);
549
}
550

551
/* Get all available PCR banks */
552
static int swtpm_tpm2_get_all_pcr_banks(struct swtpm *self, gchar ***all_pcr_banks)
108✔
553
{
554
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, 0, TPM2_CC_GETCAPABILITY);
108✔
555
    g_autofree unsigned char *req = NULL;
216✔
556
    ssize_t req_len;
108✔
557
    unsigned char tpmresp[256];
108✔
558
    size_t tpmresp_len = sizeof(tpmresp);
108✔
559
    uint16_t count, bank;
108✔
560
    const char *name;
108✔
561
    uint8_t length;
108✔
562
    size_t offset;
108✔
563
    size_t i;
108✔
564
    int ret;
108✔
565

566
    req_len = memconcat(&req,
216✔
567
                        &hdr, sizeof(hdr),
568
                        (unsigned char[]){AS4BE(TPM2_CAP_PCRS), AS4BE(0), AS4BE(64)}, (size_t)12,
108✔
569
                        NULL);
570
    if (req_len < 0) {
108✔
571
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
572
        return 1;
×
573
    }
574
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
108✔
575

576
    ret = transfer(self, req, req_len, "TPM2_GetCapability", FALSE,
108✔
577
                   tpmresp, &tpmresp_len, TPM2_DURATION_MEDIUM);
578
    if (ret != 0)
108✔
579
        return 1;
580

581
    *all_pcr_banks = NULL;
108✔
582

583
    if (tpmresp_len < 17 + sizeof(count))
108✔
584
        goto err_too_short;
×
585
    memcpy(&count, &tpmresp[17], sizeof(count));
108✔
586
    count = be16toh(count);
108✔
587

588
    /* unreasonable number of PCR banks ? */
589
    if (count > 20)
108✔
590
        goto err_num_pcrbanks;
×
591

592
    *all_pcr_banks = g_malloc0(sizeof(char *) * (count + 1));
108✔
593

594
    offset = 19;
108✔
595

596
    for (i = 0; i < count; i++) {
490✔
597
        gchar *n;
382✔
598

599
        if (tpmresp_len < offset + sizeof(bank))
382✔
600
            goto err_too_short;
×
601
        memcpy(&bank, &tpmresp[offset], sizeof(bank));
382✔
602
        bank = be16toh(bank);
382✔
603

604
        if (tpmresp_len < offset + 2 + sizeof(length))
382✔
605
            goto err_too_short;
×
606
        length = tpmresp[offset + 2];
382✔
607

608
        name = get_name_for_bank(bank);
382✔
609
        if (name != NULL)
382✔
610
            n = g_strdup(name);
382✔
611
        else
612
            n = g_strdup_printf("%02x", bank);
×
613

614
        (*all_pcr_banks)[i] = n;
382✔
615

616
        offset += 2 + 1 + length;
382✔
617
    }
618
    return 0;
619

620
err_num_pcrbanks:
×
621
    logerr(self->logfile, "Unreasonable number of PCR banks (%u) returned.\n", count);
×
622
    goto err_exit;
×
623

624
err_too_short:
×
625
    logerr(self->logfile, "Response from TPM2_GetCapability is too short!\n");
×
626

627
err_exit:
×
628
    g_strfreev(*all_pcr_banks);
×
629
    *all_pcr_banks = NULL;
×
630

631
    return 1;
×
632
}
633

634
/* Activate all user-chosen PCR banks and deactivate all others */
635
static int swtpm_tpm2_set_active_pcr_banks(struct swtpm *self, gchar **pcr_banks,
108✔
636
                                           gchar **all_pcr_banks, gchar ***active)
637
{
638
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_PCR_ALLOCATE);
108✔
639
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
108✔
640
    unsigned char pcrselects[6 * 10]; // supports up to 10 PCR banks
108✔
641
    ssize_t pcrselects_len = 0;
108✔
642
    size_t count = 0;
108✔
643
    size_t idx, j;
108✔
644
    uint16_t hashAlg;
108✔
645
    g_autofree unsigned char *req = NULL;
216✔
646
    ssize_t req_len, len;
108✔
647
    int ret;
108✔
648
    uint64_t activated_mask = 0;
108✔
649

650
    for (idx = 0; pcr_banks[idx] != NULL; idx++)
222✔
651
        ;
652
    *active = g_malloc0(sizeof(char *) * (idx + 1));
108✔
653

654
    for (idx = 0; pcr_banks[idx] != NULL; idx++) {
222✔
655
        hashAlg = 0;
212✔
656
        // Is user-chosen pcr_banks[idx] available?
657
        for (j = 0; all_pcr_banks[j] != NULL; j++) {
212✔
658
            if (strcmp(pcr_banks[idx], all_pcr_banks[j]) == 0) {
211✔
659
                hashAlg = get_hashalg_by_bankname(pcr_banks[idx]);
113✔
660
                break;
113✔
661
            }
662
        }
663
        if (hashAlg != 0 && (activated_mask & ((uint64_t)1 << j)) == 0) {
114✔
664
            (*active)[count] = g_strdup(pcr_banks[idx]);
113✔
665
            len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
226✔
666
                         (unsigned char[]){AS2BE(hashAlg), 3, 0xff, 0xff, 0xff} , (size_t)6,
113✔
667
                         NULL);
668
            if (len < 0) {
113✔
669
                logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
670
                return 1;
×
671
            }
672
            pcrselects_len += len;
113✔
673
            count++;
113✔
674
            activated_mask |= ((uint64_t)1 << j);
113✔
675
        }
676
    }
677

678
    if (count == 0) {
108✔
679
        logerr(self->logfile,
1✔
680
               "No PCR banks could be allocated. None of the selected algorithms are supported.\n");
681
        goto error;
1✔
682
    }
683

684
    // disable all the other ones not chosen by the user
685
    for (idx = 0; all_pcr_banks[idx] != NULL; idx++) {
487✔
686
        gboolean found = FALSE;
663✔
687

688
        for (j = 0; pcr_banks[j] != NULL; j++) {
663✔
689
            if (strcmp(pcr_banks[j], all_pcr_banks[idx]) == 0) {
396✔
690
                found = TRUE;
691
                break;
692
            }
693
        }
694
        if (found)
380✔
695
            continue;
113✔
696

697
        /* not found, so not chosen by user */
698
        hashAlg = get_hashalg_by_bankname(all_pcr_banks[idx]);
267✔
699

700
        len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
534✔
701
                     (unsigned char[]){AS2BE(hashAlg), 3, 0, 0, 0}, (size_t)6,
267✔
702
                     NULL);
703
        if (len < 0) {
267✔
704
            logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
705
            goto error;
×
706
        }
707
        pcrselects_len += len;
267✔
708
        count++;
267✔
709
    }
710

711
    req_len = memconcat(&req,
214✔
712
                        &hdr, sizeof(hdr),
713
                        (unsigned char[]){
107✔
714
                             AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))
715
                        }, (size_t)8,
716
                        &authblock, sizeof(authblock),
717
                        (unsigned char[]){AS4BE(count)}, (size_t)4,
107✔
718
                        pcrselects, pcrselects_len,
719
                        NULL);
720
    if (req_len < 0) {
107✔
721
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
722
        goto error;
×
723
    }
724
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
107✔
725

726
    ret = transfer(self, req, req_len, "TPM2_PCR_Allocate", FALSE,
107✔
727
                   NULL, NULL, TPM2_DURATION_SHORT);
728
    if (ret != 0)
107✔
729
        goto error;
×
730

731
    return 0;
732

733
error:
1✔
734
    g_strfreev(*active);
1✔
735
    *active = NULL;
1✔
736

737
    return 1;
1✔
738
}
739

740
static int swtpm_tpm2_flushcontext(struct swtpm *self, uint32_t handle)
3✔
741
{
742
    struct tpm2_flushcontext_req {
3✔
743
        struct tpm_req_header hdr;
744
        uint32_t flushHandle;
745
    } __attribute__((packed)) req = {
3✔
746
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_FLUSHCONTEXT),
3✔
747
        .flushHandle = htobe32(handle),
3✔
748
    };
749

750
    return transfer(self, &req, sizeof(req), "TPM2_FlushContext", FALSE,
3✔
751
                    NULL, NULL, TPM2_DURATION_SHORT);
752
}
753

754
/* Make object at the curr_handler permanent with the perm_handle */
755
static int swtpm_tpm2_evictcontrol(struct swtpm *self, uint32_t curr_handle, uint32_t perm_handle)
81✔
756
{
757
    struct tpm2_evictcontrol_req {
81✔
758
        struct tpm_req_header hdr;
759
        uint32_t auth;
760
        uint32_t objectHandle;
761
        uint32_t authblockLen;
762
        struct tpm2_authblock authblock;
763
        uint32_t persistentHandle;
764
    } __attribute__((packed)) req = {
81✔
765
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, sizeof(req), TPM2_CC_EVICTCONTROL),
81✔
766
        .auth = htobe32(TPM2_RH_OWNER),
81✔
767
        .objectHandle = htobe32(curr_handle),
81✔
768
        .authblockLen = htobe32(sizeof(req.authblock)),
81✔
769
        .authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW),
81✔
770
        .persistentHandle = htobe32(perm_handle),
81✔
771
    };
772

773
    return transfer(self, &req, sizeof(req), "TPM2_EvictControl", FALSE,
81✔
774
                    NULL, NULL, TPM2_DURATION_SHORT);
775
}
776

777
/* Create an RSA EK */
778
static int swtpm_tpm2_createprimary_ek_rsa(struct swtpm *self, unsigned int rsa_keysize,
39✔
779
                                           gboolean allowsigning, gboolean decryption,
780
                                           uint32_t *curr_handle,
781
                                           unsigned char *ektemplate, size_t *ektemplate_len,
782
                                           gchar **ekparam, const gchar **key_description)
783
{
784
    unsigned char authpolicy[48];
39✔
785
    size_t authpolicy_len;
39✔
786
    unsigned char symkeydata[6];
39✔
787
    size_t symkeydata_len;
39✔
788
    unsigned int keyflags;
39✔
789
    unsigned int symkeylen;
39✔
790
    gboolean havenonce;
39✔
791
    size_t addlen, off;
39✔
792

793
    if (rsa_keysize == 2048) {
39✔
794
        authpolicy_len = 32;
27✔
795
        memcpy(authpolicy, ((unsigned char []){
27✔
796
            0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d,
797
            0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64,
798
            0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa
799
        }), authpolicy_len);
800
        keyflags = 0;
27✔
801
        symkeylen = 128;
27✔
802
        havenonce = TRUE;
27✔
803
        addlen = 0;
27✔
804
    } else if (rsa_keysize == 3072) {
12✔
805
        authpolicy_len = 48;
12✔
806
        memcpy(authpolicy, ((unsigned char []){
12✔
807
            0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC, 0x53, 0xD8, 0x82, 0xBC,
808
            0xF5, 0xFD, 0x3A, 0x1A, 0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4,
809
            0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA, 0xCB, 0x47, 0xBA, 0x09,
810
            0x69, 0x96, 0x46, 0x15, 0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12
811
        }), authpolicy_len);
812
        keyflags = 0x40;
12✔
813
        symkeylen = 256;
12✔
814
        havenonce = FALSE;
12✔
815
        addlen = 16;
12✔
816
    } else {
817
        logerr(self->logfile, "Internal error in %s: unsupported RSA keysize %d.\n",
×
818
               __func__, rsa_keysize);
819
        return 1;
×
820
    }
821

822
    if (allowsigning && decryption) {
39✔
823
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
824
        // adminWithPolicy, sign, decrypt
825
        keyflags |= 0x000600b2;
6✔
826
        // symmetric: TPM_ALG_NULL
827
        symkeydata_len = 2;
6✔
828
        memcpy(symkeydata, ((unsigned char[]) {AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
6✔
829
        off = 72 + addlen;
6✔
830
    } else if (allowsigning) {
33✔
831
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
832
        // adminWithPolicy, sign
833
        keyflags |= 0x000400b2;
16✔
834
        // symmetric: TPM_ALG_NULL
835
        symkeydata_len = 2;
16✔
836
        memcpy(symkeydata, ((unsigned char[]) {AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
16✔
837
        off = 72 + addlen;
16✔
838
    } else {
839
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
840
        // adminWithPolicy, restricted, decrypt
841
        keyflags |= 0x000300b2;
17✔
842
        // symmetric: TPM_ALG_AES, 128bit or 256bit, TPM_ALG_CFB
843
        symkeydata_len = 6;
17✔
844
        memcpy(symkeydata,
17✔
845
               ((unsigned char[]) {AS2BE(TPM2_ALG_AES), AS2BE(symkeylen), AS2BE(TPM2_ALG_CFB)}),
17✔
846
               symkeydata_len);
847
        off = 76 + addlen;
17✔
848
    }
849

850
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_ENDORSEMENT, keyflags,
39✔
851
                                        symkeydata, symkeydata_len,
852
                                        authpolicy, authpolicy_len, rsa_keysize,
853
                                        havenonce, off, curr_handle,
854
                                        ektemplate, ektemplate_len, ekparam, key_description);
855
}
856

857
/* Create an RSA key with the given parameters */
858
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
41✔
859
                                        const unsigned char *symkeydata, size_t symkeydata_len,
860
                                        const unsigned char *authpolicy, size_t authpolicy_len,
861
                                        unsigned int rsa_keysize, gboolean havenonce, size_t off,
862
                                        uint32_t *curr_handle,
863
                                        unsigned char *ektemplate, size_t *ektemplate_len,
864
                                        gchar **ekparam, const gchar **key_description)
865
{
866
    const unsigned char *nonce;
41✔
867
    size_t nonce_len;
41✔
868
    uint16_t hashalg;
41✔
869
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY);
41✔
870
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
41✔
871
    g_autofree unsigned char *public = NULL;
82✔
872
    ssize_t public_len;
41✔
873
    g_autofree unsigned char *createprimary = NULL;
41✔
874
    ssize_t createprimary_len;
41✔
875
    int ret;
41✔
876
    unsigned char tpmresp[2048];
41✔
877
    size_t tpmresp_len = sizeof(tpmresp);
41✔
878
    uint16_t modlen;
41✔
879

880
    if (rsa_keysize == 2048) {
41✔
881
        nonce = NONCE_RSA2048;
28✔
882
        nonce_len = sizeof(NONCE_RSA2048);
28✔
883
        hashalg = TPM2_ALG_SHA256;
28✔
884
        if (key_description)
28✔
885
            *key_description = "rsa2048";
27✔
886
    } else if (rsa_keysize == 3072) {
13✔
887
        if (!havenonce) {
13✔
888
           nonce = NONCE_EMPTY;
889
           nonce_len = sizeof(NONCE_EMPTY);
890
        } else {
891
           nonce = NONCE_RSA3072;
1✔
892
           nonce_len = sizeof(NONCE_RSA3072);
1✔
893
        }
894
        hashalg = TPM2_ALG_SHA384;
13✔
895
        if (key_description)
13✔
896
            *key_description = "rsa3072";
12✔
897
    } else {
898
        logerr(self->logfile, "Internal error in %s: unsupported RSA keysize %d.\n",
×
899
               __func__, rsa_keysize);
900
        return 1;
×
901
    }
902

903
    public_len =
41✔
904
        memconcat(&public,
82✔
905
                  (unsigned char[]) {
41✔
906
                      AS2BE(TPM2_ALG_RSA), AS2BE(hashalg),
907
                      AS4BE(keyflags), AS2BE(authpolicy_len)
41✔
908
                  }, (size_t)10,
909
                  authpolicy, authpolicy_len,
910
                  symkeydata, symkeydata_len,
911
                  (unsigned char[]) {
41✔
912
                      AS2BE(TPM2_ALG_NULL), AS2BE(rsa_keysize), AS4BE(0)
41✔
913
                  }, (size_t)8,
914
                  nonce, nonce_len,
915
                  NULL);
916
    if (public_len < 0) {
41✔
917
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
918
        return 1;
×
919
    }
920
    if (ektemplate) {
41✔
921
        if (*ektemplate_len < (size_t)public_len) {
39✔
922
            logerr(self->logfile, "Internal error in %s: Need %zu bytes for ektemplate (rsa) but got only %zu\n",
×
923
                   __func__, public_len, *ektemplate_len);
924
            return 1;
×
925
        }
926
        memcpy(ektemplate, public, public_len);
39✔
927
        *ektemplate_len = public_len;
39✔
928
    }
929

930
    createprimary_len =
41✔
931
        memconcat(&createprimary,
82✔
932
                  &hdr, sizeof(hdr),
933
                  (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8,
41✔
934
                  &authblock, sizeof(authblock),
935
                  (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8,
41✔
936
                  public, public_len,
937
                  (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
41✔
938
                  NULL);
939
    if (createprimary_len < 0) {
41✔
940
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
941
        return 1;
×
942
    }
943
    ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len);
41✔
944

945
    ret = transfer(self, createprimary, createprimary_len, "TPM2_CreatePrimary(RSA)", FALSE,
41✔
946
                   tpmresp, &tpmresp_len, TPM2_DURATION_LONG);
947
    if (ret != 0)
41✔
948
        return 1;
949

950
    if (curr_handle) {
41✔
951
        if (tpmresp_len < 10 + sizeof(*curr_handle))
41✔
952
            goto err_too_short;
×
953
        memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle));
41✔
954
        *curr_handle = be32toh(*curr_handle);
41✔
955
    }
956

957
    if (tpmresp_len < off + sizeof(modlen))
41✔
958
         goto err_too_short;
×
959
    memcpy(&modlen, &tpmresp[off], sizeof(modlen));
41✔
960
    modlen = be16toh(modlen);
41✔
961
    if (modlen != rsa_keysize >> 3) {
41✔
962
        logerr(self->logfile, "Internal error in %s: Getting modulus from wrong offset %zu\n",
×
963
               __func__, off);
964
        return 1;
×
965
    }
966
    if (ekparam) {
41✔
967
        if (tpmresp_len < off + 2 + modlen)
39✔
968
            goto err_too_short;
×
969
        *ekparam = print_as_hex(&tpmresp[off + 2], modlen);
39✔
970
    }
971

972
    return 0;
973

974
err_too_short:
×
975
    logerr(self->logfile, "Response from TPM2_CreatePrimary(RSA) is too short!\n");
×
976
    return 1;
×
977
}
978

979
/* Create an ECC key with the given parameters */
980
static int swtpm_tpm2_createprimary_ecc(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
40✔
981
                                        const unsigned char *symkeydata, size_t symkeydata_len,
982
                                        const unsigned char *authpolicy, size_t authpolicy_len,
983
                                        const unsigned char *schemedata, size_t schemedata_len,
984
                                        unsigned short curveid, unsigned short hashalg,
985
                                        const unsigned char *nonce, size_t nonce_len,
986
                                        size_t off, uint32_t *curr_handle,
987
                                        unsigned char *ektemplate, size_t *ektemplate_len,
988
                                        gchar **ekparam, const gchar **key_description)
989
{
990
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY);
40✔
991
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
40✔
992
    g_autofree unsigned char *public = NULL;
80✔
993
    ssize_t public_len;
40✔
994
    g_autofree unsigned char *createprimary = NULL;
40✔
995
    ssize_t createprimary_len;
40✔
996
    int ret;
40✔
997
    unsigned char tpmresp[2048];
40✔
998
    size_t tpmresp_len = sizeof(tpmresp);
40✔
999
    size_t off2;
40✔
1000
    uint16_t exp_ksize, ksize1, ksize2;
40✔
1001
    const char *cid;
40✔
1002

1003
    public_len =
40✔
1004
        memconcat(&public,
80✔
1005
                  (unsigned char[]){
40✔
1006
                      AS2BE(TPM2_ALG_ECC), AS2BE(hashalg), AS4BE(keyflags), AS2BE(authpolicy_len)
40✔
1007
                  }, (size_t)10,
1008
                  authpolicy, authpolicy_len,
1009
                  symkeydata, symkeydata_len,
1010
                  schemedata, schemedata_len,
1011
                  nonce, nonce_len,
1012
                  nonce, nonce_len,
1013
                  NULL);
1014
    if (public_len < 0) {
40✔
1015
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1016
        return 1;
×
1017
    }
1018
    if (ektemplate) {
40✔
1019
        if (*ektemplate_len < (size_t)public_len) {
39✔
1020
            logerr(self->logfile, "Internal error: Need %zu bytes for ektemplate (ecc) but got only %zu\n",
×
1021
                   public_len, ektemplate_len);
1022
            return 1;
×
1023
        }
1024
        memcpy(ektemplate, public, public_len);
39✔
1025
        *ektemplate_len = public_len;
39✔
1026
    }
1027

1028
    createprimary_len =
40✔
1029
        memconcat(&createprimary,
80✔
1030
                  &hdr, sizeof(hdr),
1031
                  (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8,
40✔
1032
                  &authblock, sizeof(authblock),
1033
                  (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8,
40✔
1034
                  public, public_len,
1035
                  (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
40✔
1036
                  NULL);
1037
    if (createprimary_len < 0) {
40✔
1038
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1039
        return 1;
×
1040
    }
1041
    ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len);
40✔
1042

1043
    ret = transfer(self, createprimary, createprimary_len, "TPM2_CreatePrimary(ECC)", FALSE,
40✔
1044
                   tpmresp, &tpmresp_len, TPM2_DURATION_LONG);
1045
    if (ret != 0)
40✔
1046
        return 1;
1047
    if (curr_handle) {
40✔
1048
        if (tpmresp_len < 10 + sizeof(*curr_handle))
40✔
1049
            goto err_too_short;
×
1050
        memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle));
40✔
1051
        *curr_handle = be32toh(*curr_handle);
40✔
1052
    }
1053

1054
    if (curveid == TPM2_ECC_NIST_P384) {
40✔
1055
        exp_ksize = 48;
40✔
1056
        cid = "secp384r1";
40✔
1057
        if (key_description)
40✔
1058
            *key_description = cid;
39✔
1059
    } else {
1060
        logerr(self->logfile, "Unknown curveid 0x%x\n", curveid);
×
1061
        return 1;
×
1062
    }
1063

1064
    if (tpmresp_len < off + sizeof(ksize1))
40✔
1065
        goto err_too_short;
×
1066
    memcpy(&ksize1, &tpmresp[off], sizeof(ksize1));
40✔
1067
    ksize1 = be16toh(ksize1);
40✔
1068
    off2 = off + 2 + ksize1;
40✔
1069

1070
    if (tpmresp_len < off2 + sizeof(ksize2))
40✔
1071
        goto err_too_short;
×
1072
    memcpy(&ksize2, &tpmresp[off2], sizeof(ksize2));
40✔
1073
    ksize2 = be16toh(ksize2);
40✔
1074

1075
    if (ksize1 != exp_ksize || ksize2 != exp_ksize) {
40✔
1076
        logerr(self->logfile, "ECC: Getting key parameters from wrong offset\n");
×
1077
        return 1;
×
1078
    }
1079

1080
    if (ekparam) {
40✔
1081
        unsigned char *xparam = &tpmresp[off + 2];
39✔
1082
        unsigned char *yparam = &tpmresp[off2 + 2];
39✔
1083
        if (tpmresp_len < off + 2 + ksize1 || tpmresp_len < off2 + 2 + ksize2)
39✔
1084
            goto err_too_short;
×
1085
        g_autofree gchar *xparam_str = print_as_hex(xparam, ksize1);
78✔
1086
        g_autofree gchar *yparam_str = print_as_hex(yparam, ksize2);
78✔
1087

1088
        *ekparam = g_strdup_printf("x=%s,y=%s,id=%s", xparam_str, yparam_str, cid);
39✔
1089
    }
1090

1091
    return 0;
1092

1093
err_too_short:
×
1094
    logerr(self->logfile, "Response from TPM2_CreatePrimary(ECC) is too short!\n");
×
1095
    return 1;
×
1096
}
1097

1098
static int swtpm_tpm2_createprimary_spk_ecc_nist_p384(struct swtpm *self,
1✔
1099
                                                      uint32_t *curr_handle)
1100
{
1101
    // keyflags: fixedTPM, fixedParent, sensitiveDataOrigin, userWithAuth
1102
    //           noDA, restricted, decrypt
1103
    unsigned int keyflags = 0x00030472;
1✔
1104
    const unsigned char authpolicy[0] = { };
1✔
1105
    size_t authpolicy_len = sizeof(authpolicy);
1✔
1106
    const unsigned char symkeydata[] = {AS2BE(TPM2_ALG_AES), AS2BE(256), AS2BE(TPM2_ALG_CFB)};
1✔
1107
    size_t symkeydata_len = sizeof(symkeydata);
1✔
1108
    const unsigned char schemedata[] = {
1✔
1109
        AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P384), AS2BE(TPM2_ALG_NULL)
1110
    };
1111
    size_t schemedata_len = sizeof(schemedata);
1✔
1112
    size_t off = 42;
1✔
1113

1114
    /* per "TCG TPM v2.0 Provisioning Guidance v1.0" page 37
1115
     * -> "Ek Credential Profile 2.0" rev.14 section 2.1.5.2:
1116
     * template for NIST P256 uses 2 identical 32-byte all-zero nonces
1117
     * -> Use two 48-byte all-zero nonces for NIST P384.
1118
     */
1119

1120
    return swtpm_tpm2_createprimary_ecc(self, TPM2_RH_OWNER, keyflags, symkeydata, symkeydata_len,
1✔
1121
                                        authpolicy, authpolicy_len, schemedata, schemedata_len,
1122
                                        TPM2_ECC_NIST_P384, TPM2_ALG_SHA384,
1123
                                        NONCE_ECC_384, sizeof(NONCE_ECC_384), off, curr_handle,
1124
                                        NULL, 0, NULL, NULL);
1125
}
1126

1127
static int swtpm_tpm2_createprimary_spk_rsa(struct swtpm *self, unsigned int rsa_keysize,
2✔
1128
                                            uint32_t *curr_handle)
1129
{
1130
    // keyflags: fixedTPM, fixedParent, sensitiveDataOrigin, userWithAuth
1131
    //           noDA, restricted, decrypt
1132
    unsigned int keyflags = 0x00030472;
2✔
1133
    const unsigned char authpolicy[0] = { };
2✔
1134
    size_t authpolicy_len = sizeof(authpolicy);
2✔
1135
    unsigned short symkeylen = 0;
2✔
1136
    unsigned char symkeydata[6];
2✔
1137
    size_t symkeydata_len;
2✔
1138
    size_t off = 44;
2✔
1139

1140
    if (rsa_keysize == 2048)
2✔
1141
        symkeylen = 128;
1142
    else if (rsa_keysize == 3072)
1✔
1143
        symkeylen = 256;
1✔
1144

1145
    symkeydata_len = 6;
2✔
1146
    memcpy(symkeydata,
2✔
1147
           ((unsigned char[]) {AS2BE(TPM2_ALG_AES), AS2BE(symkeylen), AS2BE(TPM2_ALG_CFB)}),
2✔
1148
           symkeydata_len);
1149

1150
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_OWNER, keyflags,
2✔
1151
                                        symkeydata, symkeydata_len,
1152
                                        authpolicy, authpolicy_len, rsa_keysize, TRUE,
1153
                                        off, curr_handle, NULL, 0, NULL, NULL);
1154
}
1155

1156
/* Create either an ECC or RSA storage primary key (deprecated) */
1157
static int swtpm_tpm2_create_spk(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize)
3✔
1158
{
1159
    int ret;
3✔
1160
    uint32_t curr_handle;
3✔
1161

1162
    if (isecc)
3✔
1163
        ret = swtpm_tpm2_createprimary_spk_ecc_nist_p384(self, &curr_handle);
1✔
1164
    else
1165
        ret = swtpm_tpm2_createprimary_spk_rsa(self, rsa_keysize, &curr_handle);
2✔
1166

1167
    if (ret != 0)
3✔
1168
        return 1;
1169

1170
    ret = swtpm_tpm2_evictcontrol(self, curr_handle, TPM2_SPK_HANDLE);
3✔
1171
    if (ret == 0)
3✔
1172
        logit(self->logfile,
3✔
1173
              "Successfully created storage primary key with handle 0x%x.\n", TPM2_SPK_HANDLE);
1174

1175
    ret = swtpm_tpm2_flushcontext(self, curr_handle);
3✔
1176
    if (ret != 0) {
3✔
1177
        logerr(self->logfile, "Could not flush storage primary key.\n");
×
1178
        ret = 1;
×
1179
    }
1180

1181
    return ret;
1182
}
1183

1184
/* Create an ECC EK key that may be allowed to sign and/or decrypt */
1185
static int swtpm_tpm2_createprimary_ek_ecc_nist_p384(struct swtpm *self, gboolean allowsigning,
39✔
1186
                                                     gboolean decryption, uint32_t *curr_handle,
1187
                                                     unsigned char *ektemplate, size_t *ektemplate_len,
1188
                                                     gchar **ekparam, const char **key_description)
1189
{
1190
    unsigned char authpolicy[48]= {
39✔
1191
        0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC, 0x53, 0xD8, 0x82, 0xBC,
1192
        0xF5, 0xFD, 0x3A, 0x1A, 0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4,
1193
        0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA, 0xCB, 0x47, 0xBA, 0x09,
1194
        0x69, 0x96, 0x46, 0x15, 0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12
1195
    };
1196
    const unsigned char schemedata[] = {
39✔
1197
        AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P384), AS2BE(TPM2_ALG_NULL)
1198
    };
1199
    size_t schemedata_len = sizeof(schemedata);
39✔
1200
    size_t authpolicy_len = 48;
39✔
1201
    unsigned char symkeydata[6];
39✔
1202
    size_t symkeydata_len;
39✔
1203
    unsigned int keyflags;
39✔
1204
    size_t off;
39✔
1205
    int ret;
39✔
1206

1207
    if (allowsigning && decryption) {
39✔
1208
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1209
        // userWithAuth, adminWithPolicy, sign, decrypt
1210
        keyflags = 0x000600f2;
6✔
1211
        // symmetric: TPM_ALG_NULL
1212
        symkeydata_len = 2;
6✔
1213
        memcpy(symkeydata, ((unsigned char[]){AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
6✔
1214
        off = 86;
6✔
1215
    } else if (allowsigning) {
33✔
1216
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1217
        // userWithAuth, adminWithPolicy, sign
1218
        keyflags = 0x000400f2;
16✔
1219
        // symmetric: TPM_ALG_NULL
1220
        symkeydata_len = 2;
16✔
1221
        memcpy(symkeydata, ((unsigned char[]){AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
16✔
1222
        off = 86;
16✔
1223
    } else {
1224
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1225
        // userWithAuth, adminWithPolicy, restricted, decrypt
1226
        keyflags = 0x000300f2;
17✔
1227
        // symmetric: TPM_ALG_AES, 256bit, TPM_ALG_CFB
1228
        symkeydata_len = 6;
17✔
1229
        memcpy(symkeydata,
17✔
1230
               ((unsigned char[]){ AS2BE(TPM2_ALG_AES), AS2BE(256), AS2BE(TPM2_ALG_CFB)}),
17✔
1231
               symkeydata_len);
1232
        off = 90;
17✔
1233
    }
1234

1235
    ret = swtpm_tpm2_createprimary_ecc(self, TPM2_RH_ENDORSEMENT, keyflags,
39✔
1236
                                       symkeydata, symkeydata_len,
1237
                                       authpolicy, authpolicy_len,
1238
                                       schemedata, schemedata_len,
1239
                                       TPM2_ECC_NIST_P384, TPM2_ALG_SHA384,
1240
                                       NONCE_EMPTY, sizeof(NONCE_EMPTY), off, curr_handle,
1241
                                       ektemplate, ektemplate_len, ekparam, key_description);
1242
    if (ret != 0)
39✔
1243
       logerr(self->logfile, "%s failed\n", __func__);
×
1244

1245
    return ret;
39✔
1246
}
1247

1248
/* Create an ECC or RSA EK */
1249
static int swtpm_tpm2_create_ek(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize,
78✔
1250
                                gboolean allowsigning, gboolean decryption, gboolean lock_nvram,
1251
                                gchar **ekparam, const  gchar **key_description)
1252
{
1253
    uint32_t tpm2_ek_handle, nvindex, curr_handle;
78✔
1254
    const char *keytype;
78✔
1255
    int ret;
78✔
1256
    unsigned char ektemplate[512];
78✔
1257
    size_t ektemplate_len = sizeof(ektemplate);
78✔
1258

1259
    if (isecc) {
78✔
1260
        tpm2_ek_handle = TPM2_EK_ECC_SECP384R1_HANDLE;
1261
        keytype = "ECC";
1262
        nvindex = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE;
1263
    } else {
1264
        if (rsa_keysize == 2048) {
39✔
1265
            tpm2_ek_handle = TPM2_EK_RSA_HANDLE;
1266
            keytype = "RSA 2048";
1267
            nvindex = TPM2_NV_INDEX_RSA2048_EKTEMPLATE;
1268
        } else if (rsa_keysize == 3072) {
12✔
1269
            tpm2_ek_handle = TPM2_EK_RSA3072_HANDLE;
1270
            keytype = "RSA 3072";
1271
            nvindex = TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE;
1272
        } else {
1273
            logerr(self->logfile, "Internal error: Unsupported RSA keysize %u.\n", rsa_keysize);
×
1274
            return 1;
×
1275
        }
1276
    }
1277
    if (isecc)
78✔
1278
        ret = swtpm_tpm2_createprimary_ek_ecc_nist_p384(self, allowsigning, decryption, &curr_handle,
39✔
1279
                                                        ektemplate, &ektemplate_len, ekparam,
1280
                                                        key_description);
1281
    else
1282
        ret = swtpm_tpm2_createprimary_ek_rsa(self, rsa_keysize, allowsigning, decryption, &curr_handle,
39✔
1283
                                              ektemplate, &ektemplate_len, ekparam, key_description);
1284

1285
    if (ret == 0)
78✔
1286
        ret = swtpm_tpm2_evictcontrol(self, curr_handle, tpm2_ek_handle);
78✔
1287
    if (ret != 0) {
78✔
1288
        logerr(self->logfile, "create_ek failed: 0x%x\n", ret);
×
1289
        return 1;
×
1290
    }
1291

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

1295
    if (allowsigning) {
78✔
1296
        uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE | \
44✔
1297
                TPMA_NV_AUTHREAD | \
1298
                TPMA_NV_OWNERREAD | \
1299
                TPMA_NV_PPREAD | \
1300
                TPMA_NV_PPWRITE | \
1301
                TPMA_NV_NO_DA | \
1302
                TPMA_NV_WRITEDEFINE;
1303
        ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, ektemplate, ektemplate_len,
44✔
1304
                                     lock_nvram, "EK template");
1305
        if (ret == 0)
44✔
1306
            logit(self->logfile,
44✔
1307
                  "Successfully created NVRAM area 0x%x for %s EK template.\n",
1308
                  nvindex, keytype);
1309
    }
1310

1311
    return ret;
1312
}
1313

1314
static int swtpm_tpm2_nvdefinespace(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
143✔
1315
                                    uint16_t data_len)
1316
{
1317
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_DEFINESPACE);
143✔
1318
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
143✔
1319
    g_autofree unsigned char *nvpublic = NULL;
286✔
1320
    ssize_t nvpublic_len;
143✔
1321
    g_autofree unsigned char *req = NULL;
143✔
1322
    ssize_t req_len;
143✔
1323

1324
    nvpublic_len = memconcat(&nvpublic,
286✔
1325
                             (unsigned char[]){
143✔
1326
                                 AS4BE(nvindex), AS2BE(TPM2_ALG_SHA256), AS4BE(nvindexattrs),
143✔
1327
                                 AS2BE(0), AS2BE(data_len)}, (size_t)14,
1328
                             NULL);
1329
    if (nvpublic_len < 0) {
143✔
1330
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1331
        return 1;
×
1332
    }
1333

1334
    req_len = memconcat(&req,
286✔
1335
                        &hdr, sizeof(hdr),
1336
                        (unsigned char[]){AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))}, (size_t)8,
143✔
1337
                        &authblock, sizeof(authblock),
1338
                        (unsigned char[]){AS2BE(0), AS2BE(nvpublic_len)}, (size_t)4,
143✔
1339
                        nvpublic, nvpublic_len,
1340
                        NULL);
1341
    if (req_len < 0) {
143✔
1342
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1343
        return 1;
×
1344
    }
1345

1346
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
143✔
1347

1348
    return transfer(self, req, req_len, "TPM2_NV_DefineSpace", FALSE,
143✔
1349
                    NULL, NULL, TPM2_DURATION_SHORT);
1350
}
1351

1352
/* Write the data into the given NVIndex */
1353
static int swtpm_tpm2_nv_write(struct swtpm *self, uint32_t nvindex,
143✔
1354
                               const unsigned char *data, size_t data_len)
1355
{
1356
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITE);
143✔
1357
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
143✔
1358
    g_autofree unsigned char *req = NULL;
286✔
1359
    ssize_t req_len;
143✔
1360
    size_t offset = 0, txlen;
143✔
1361
    int ret;
143✔
1362

1363
    while (offset < data_len) {
288✔
1364
        txlen = min(data_len - offset, 1024);
145✔
1365

1366
        g_free(req);
145✔
1367
        req_len = memconcat(&req,
290✔
1368
                            &hdr, sizeof(hdr),
1369
                            (unsigned char[]){
145✔
1370
                                AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
145✔
1371
                            }, (size_t)12,
1372
                            &authblock, sizeof(authblock),
1373
                            (unsigned char[]){AS2BE(txlen)}, (size_t)2,
145✔
1374
                            &data[offset], txlen,
1375
                            (unsigned char[]){AS2BE(offset)}, (size_t)2,
145✔
1376
                            NULL);
1377
        if (req_len < 0) {
145✔
1378
            logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1379
            return 1;
×
1380
        }
1381
        ((struct tpm_req_header *)req)->size = htobe32(req_len);
145✔
1382

1383
        ret = transfer(self, req, req_len, "TPM2_NV_Write", FALSE,
145✔
1384
                       NULL, NULL, TPM2_DURATION_SHORT);
1385
        if (ret != 0)
145✔
1386
            return 1;
1387

1388
        offset += txlen;
145✔
1389
    }
1390
    return 0;
1391
}
1392

1393
static int swtpm_tpm2_nv_writelock(struct swtpm *self, uint32_t nvindex)
9✔
1394
{
1395
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITELOCK);
9✔
1396
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
9✔
1397
    g_autofree unsigned char *req;
18✔
1398
    ssize_t req_len;
9✔
1399

1400
    req_len = memconcat(&req,
18✔
1401
                        &hdr, sizeof(hdr),
1402
                        (unsigned char[]){
9✔
1403
                           AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
9✔
1404
                        }, (size_t)12,
1405
                        &authblock, sizeof(authblock),
1406
                        NULL);
1407
    if (req_len < 0) {
9✔
1408
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1409
        return 1;
×
1410
    }
1411

1412
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
9✔
1413

1414
    return transfer(self, req, req_len, "TPM2_NV_WriteLock", FALSE,
9✔
1415
                    NULL, NULL, TPM2_DURATION_SHORT);
1416
}
1417

1418
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
143✔
1419
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
1420
                                  const char *certtype)
1421
{
1422
    int ret = swtpm_tpm2_nvdefinespace(self, nvindex, nvindexattrs, data_len);
143✔
1423
    if (ret != 0) {
143✔
1424
        logerr(self->logfile, "Could not create NVRAM area 0x%x for %s.\n", nvindex, certtype);
×
1425
        return 1;
×
1426
    }
1427

1428
    ret = swtpm_tpm2_nv_write(self, nvindex, data, data_len);
143✔
1429
    if (ret != 0) {
143✔
1430
        logerr(self->logfile,
×
1431
               "Could not write %s into NVRAM area 0x%x.\n", certtype, nvindex);
1432
        return 1;
×
1433
    }
1434

1435
    if (lock_nvram) {
143✔
1436
        ret = swtpm_tpm2_nv_writelock(self, nvindex);
9✔
1437
        if (ret != 0) {
9✔
1438
            logerr(self->logfile, "Could not lock EK template NVRAM area 0x%x.\n", nvindex);
×
1439
            return 1;
×
1440
        }
1441
    }
1442

1443
    return 0;
1444
}
1445

1446
static int swtpm_tpm2_write_cert_nvram(struct swtpm *self, uint32_t nvindex,
99✔
1447
                                       uint32_t nvindexattrs,
1448
                                       const unsigned char *data, size_t data_len,
1449
                                       gboolean lock_nvram, const char *keytype,
1450
                                       const char *certtype)
1451
{
1452
    int ret;
99✔
1453

1454
    ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, data, data_len, lock_nvram,
99✔
1455
                                 certtype);
1456
    if (ret == 0)
99✔
1457
        logit(self->logfile,
99✔
1458
              "Successfully created NVRAM area 0x%x for %s%s.\n",
1459
              nvindex, keytype, certtype);
1460

1461
    return ret;
99✔
1462
}
1463

1464
/* Write the platform certificate into an NVRAM area */
1465
static int swtpm_tpm2_write_ek_cert_nvram(struct swtpm *self, gboolean isecc,
66✔
1466
                                           unsigned int rsa_keysize, gboolean lock_nvram,
1467
                                           const unsigned char *data, size_t data_len)
1468
{
1469
    uint32_t nvindex = 0;
66✔
1470
    g_autofree gchar *keytype = NULL;
132✔
1471
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
66✔
1472
            TPMA_NV_AUTHREAD |
1473
            TPMA_NV_OWNERREAD |
1474
            TPMA_NV_PPREAD |
1475
            TPMA_NV_PPWRITE |
1476
            TPMA_NV_NO_DA |
1477
            TPMA_NV_WRITEDEFINE;
1478

1479
    if (!isecc) {
66✔
1480
        if (rsa_keysize == 2048)
33✔
1481
            nvindex = TPM2_NV_INDEX_RSA2048_EKCERT;
1482
        else if (rsa_keysize == 3072)
10✔
1483
            nvindex = TPM2_NV_INDEX_RSA3072_HI_EKCERT;
10✔
1484
        keytype = g_strdup_printf("RSA %d ", rsa_keysize);
33✔
1485
    } else {
1486
        nvindex = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT;
33✔
1487
        keytype = g_strdup("ECC ");
33✔
1488
    }
1489

1490
    return swtpm_tpm2_write_cert_nvram(self, nvindex, nvindexattrs, data, data_len,
66✔
1491
                                       lock_nvram, keytype, "EK certificate");
1492
}
1493

1494
static int swtpm_tpm2_write_platform_cert_nvram(struct swtpm *self, gboolean lock_nvram,
33✔
1495
                                                const unsigned char *data, size_t data_len)
1496
{
1497
    uint32_t nvindex = TPM2_NV_INDEX_PLATFORMCERT;
33✔
1498
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
33✔
1499
            TPMA_NV_AUTHREAD |
1500
            TPMA_NV_OWNERREAD |
1501
            TPMA_NV_PPREAD |
1502
            TPMA_NV_PPWRITE |
1503
            TPMA_NV_NO_DA |
1504
            TPMA_NV_WRITEDEFINE;
1505

1506
    return swtpm_tpm2_write_cert_nvram(self, nvindex, nvindexattrs, data, data_len,
33✔
1507
                                       lock_nvram, "", "platform certificate");
1508
}
1509

1510
static char *swtpm_tpm2_get_active_profile(struct swtpm *self)
104✔
1511
{
1512
    gchar *result = NULL;
104✔
1513

1514
    if (do_cmd_get_info(self, SWTPM_INFO_ACTIVE_PROFILE, &result))
104✔
1515
        return NULL;
1516
    return result;
102✔
1517
}
1518

1519
static const struct swtpm2_ops swtpm_tpm2_ops = {
1520
    .shutdown = swtpm_tpm2_shutdown,
1521
    .create_spk = swtpm_tpm2_create_spk,
1522
    .create_ek = swtpm_tpm2_create_ek,
1523
    .get_all_pcr_banks = swtpm_tpm2_get_all_pcr_banks,
1524
    .set_active_pcr_banks = swtpm_tpm2_set_active_pcr_banks,
1525
    .write_ek_cert_nvram = swtpm_tpm2_write_ek_cert_nvram,
1526
    .write_platform_cert_nvram = swtpm_tpm2_write_platform_cert_nvram,
1527
    .get_active_profile = swtpm_tpm2_get_active_profile,
1528
};
1529

1530
/*
1531
 * TPM 1.2 support
1532
 */
1533
#define TPM_TAG_RQU_COMMAND       0x00c1
1534
#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
1535

1536
#define TPM_ORD_OIAP                     0x0000000A
1537
#define TPM_ORD_TAKE_OWNERSHIP           0x0000000D
1538
#define TPM_ORD_PHYSICAL_ENABLE          0x0000006F
1539
#define TPM_ORD_PHYSICAL_SET_DEACTIVATED 0x00000072
1540
#define TPM_ORD_NV_DEFINE_SPACE          0x000000CC
1541
#define TPM_ORD_NV_WRITE_VALUE           0x000000CD
1542
#define TSC_ORD_PHYSICAL_PRESENCE        0x4000000A
1543

1544
#define TPM_ST_CLEAR 0x0001
1545

1546
#define TPM_PHYSICAL_PRESENCE_CMD_ENABLE  0x0020
1547
#define TPM_PHYSICAL_PRESENCE_PRESENT     0x0008
1548

1549
#define TPM_ALG_RSA 0x00000001
1550

1551
#define TPM_KEY_STORAGE 0x0011
1552

1553
#define TPM_AUTH_ALWAYS 0x01
1554

1555
#define TPM_PID_OWNER  0x0005
1556

1557
#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003
1558
#define TPM_SS_NONE 0x0001
1559

1560
#define TPM_TAG_PCR_INFO_LONG   0x0006
1561
#define TPM_TAG_NV_ATTRIBUTES   0x0017
1562
#define TPM_TAG_NV_DATA_PUBLIC  0x0018
1563
#define TPM_TAG_KEY12           0x0028
1564

1565
#define TPM_LOC_ZERO   0x01
1566
#define TPM_LOC_ALL    0x1f
1567

1568
#define TPM_NV_INDEX_D_BIT        0x10000000
1569
#define TPM_NV_INDEX_EKCERT       0xF000
1570
#define TPM_NV_INDEX_PLATFORMCERT 0xF002
1571

1572
#define TPM_NV_INDEX_LOCK 0xFFFFFFFF
1573

1574
#define TPM_NV_PER_OWNERREAD   0x00020000
1575
#define TPM_NV_PER_OWNERWRITE  0x00000002
1576

1577
#define TPM_ET_OWNER 0x02
1578
#define TPM_ET_NV    0x0b
1579

1580
#define TPM_KH_EK    0x40000006
1581

1582
#define TPM_DURATION_SHORT     2000  /* ms */
1583
#define TPM_DURATION_MEDIUM    7500  /* ms */
1584
#define TPM_DURATION_LONG     15000  /* ms */
1585

1586
static int swtpm_tpm12_tsc_physicalpresence(struct swtpm *self, uint16_t physicalpresence)
52✔
1587
{
1588
    struct tpm12_tsc_physicalpresence {
52✔
1589
        struct tpm_req_header hdr;
1590
        uint16_t pp;
1591
    } req = {
52✔
1592
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TSC_ORD_PHYSICAL_PRESENCE),
52✔
1593
        .pp = htobe16(physicalpresence),
52✔
1594
    };
1595

1596
    /* use medium duration to avoid t/o on busy system */
1597
    return transfer(self, &req, sizeof(req), "TSC_PhysicalPresence", FALSE,
52✔
1598
                    NULL, NULL, TPM_DURATION_MEDIUM);
1599
}
1600

1601
static int swtpm_tpm12_physical_enable(struct swtpm *self)
26✔
1602
{
1603
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_ENABLE);
26✔
1604

1605
    return transfer(self, &req, sizeof(req), "TPM_PhysicalEnable", FALSE,
26✔
1606
                    NULL, NULL, TPM_DURATION_SHORT);
1607
}
1608

1609
static int swtpm_tpm12_physical_set_deactivated(struct swtpm *self, uint8_t state)
26✔
1610
{
1611
    struct tpm12_tsc_physical_set_deactivated {
26✔
1612
        struct tpm_req_header hdr;
1613
        uint8_t state;
1614
    } req = {
26✔
1615
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_SET_DEACTIVATED),
26✔
1616
        .state = state,
1617
    };
1618

1619
    return transfer(self, &req, sizeof(req), "TSC_PhysicalSetDeactivated", FALSE,
26✔
1620
                    NULL, NULL, TPM_DURATION_SHORT);
1621
}
1622

1623
/* Initialize the TPM1.2 */
1624
static int swtpm_tpm12_run_swtpm_bios(struct swtpm *self)
26✔
1625
{
1626
    if (swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_CMD_ENABLE) ||
52✔
1627
        swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_PRESENT) ||
52✔
1628
        swtpm_tpm12_physical_enable(self) ||
52✔
1629
        swtpm_tpm12_physical_set_deactivated(self, 0))
26✔
1630
        return 1;
×
1631

1632
    return 0;
1633
}
1634

1635
static int swptm_tpm12_create_endorsement_keypair(struct swtpm *self,
19✔
1636
                                                  gchar **pubek, size_t *pubek_len)
1637
{
1638
    unsigned char req[] = {
19✔
1639
        0x00, 0xc1, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x78, 0x38, 0xf0, 0x30, 0x81, 0x07, 0x2b,
1640
        0x0c, 0xa9, 0x10, 0x98, 0x08, 0xc0, 0x4B, 0x05, 0x11, 0xc9, 0x50, 0x23, 0x52, 0xc4, 0x00, 0x00,
1641
        0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1642
        0x00, 0x02, 0x00, 0x00, 0x00, 0x00
1643
    };
1644
    unsigned char tpmresp[512];
19✔
1645
    size_t tpmresp_len = sizeof(tpmresp);
19✔
1646
    uint32_t length;
19✔
1647
    int ret;
19✔
1648

1649
    ret = transfer(self, &req, sizeof(req), "TPM_CreateEndorsementKeyPair", FALSE,
19✔
1650
                   &tpmresp, &tpmresp_len, TPM_DURATION_LONG);
1651
    if (ret != 0)
19✔
1652
        return 1;
1653

1654
    if (tpmresp_len < 34 + sizeof(length))
19✔
1655
        goto err_too_short;
×
1656
    memcpy(&length, &tpmresp[34], sizeof(length));
19✔
1657
    length = be32toh(length);
19✔
1658
    if (length != 256) {
19✔
1659
        logerr(self->logfile, "Offset to EK Public key is wrong.\n");
×
1660
        return 1;
×
1661
    }
1662

1663
    *pubek_len = 256;
19✔
1664
    if (tpmresp_len < 38 + *pubek_len)
19✔
1665
        goto err_too_short;
×
1666
    *pubek = g_malloc(256);
19✔
1667
    memcpy(*pubek, &tpmresp[38], *pubek_len);
19✔
1668

1669
    return 0;
19✔
1670

1671
err_too_short:
×
1672
    logerr(self->logfile, "Response from TPM_CreateEndorsementKeyPair is too short!\n");
×
1673
    return 1;
×
1674
}
1675

1676
/* Create an OIAP session */
1677
static int swtpm_tpm12_oiap(struct swtpm *self, uint32_t *authhandle, unsigned char nonce_even[SHA_DIGEST_LENGTH])
9✔
1678
{
1679
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_OIAP);
9✔
1680
    unsigned char tpmresp[64];
9✔
1681
    size_t tpmresp_len = sizeof(tpmresp);
9✔
1682
    int ret;
9✔
1683

1684
    ret = transfer(self, &req, sizeof(req), "TPM_OIAP", FALSE,
9✔
1685
                   &tpmresp, &tpmresp_len, TPM_DURATION_SHORT);
1686
    if (ret != 0)
9✔
1687
        return ret;
1688

1689
    if (tpmresp_len < 10 + sizeof(*authhandle) || tpmresp_len < 14 + SHA_DIGEST_LENGTH)
9✔
1690
        goto err_too_short;
×
1691
    memcpy(authhandle, &tpmresp[10], sizeof(*authhandle));
9✔
1692
    *authhandle = be32toh(*authhandle);
9✔
1693
    memcpy(nonce_even, &tpmresp[14], SHA_DIGEST_LENGTH);
9✔
1694

1695
    return 0;
9✔
1696

1697
err_too_short:
×
1698
    logerr(self->logfile, "Response from TPM_OIAP is too short!\n");
×
1699
    return 1;
×
1700
}
1701

1702
static int swtpm_tpm12_take_ownership(struct swtpm *self, const unsigned char ownerpass_digest[SHA_DIGEST_LENGTH],
9✔
1703
                                      const unsigned char srkpass_digest[SHA_DIGEST_LENGTH],
1704
                                      const unsigned char *pubek, size_t pubek_len)
1705
{
1706
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_AUTH1_COMMAND, 0, TPM_ORD_TAKE_OWNERSHIP);
9✔
1707
    EVP_PKEY *pkey = NULL;
9✔
1708
    EVP_PKEY_CTX *ctx = NULL;
9✔
1709
    BIGNUM *exp = BN_new();
9✔
1710
    BIGNUM *mod = NULL;
9✔
1711
#if OPENSSL_VERSION_NUMBER < 0x30000000L
1712
    RSA *rsakey = RSA_new();
1713
#endif
1714
    int ret = 1;
9✔
1715
    const EVP_MD *sha1 = EVP_sha1();
9✔
1716
    g_autofree unsigned char *enc_owner_auth = g_malloc(pubek_len);
9✔
1717
    size_t enc_owner_auth_len = pubek_len;
9✔
1718
    g_autofree unsigned char *enc_srk_auth = g_malloc(pubek_len);
18✔
1719
    size_t enc_srk_auth_len = pubek_len;
9✔
1720
    uint32_t auth_handle;
9✔
1721
    unsigned char nonce_even[SHA_DIGEST_LENGTH];
9✔
1722
    unsigned char nonce_odd[SHA_DIGEST_LENGTH] = {1, 2, 3, 4, 5, 6, };
9✔
1723
    g_autofree unsigned char *tpm_rsa_key_parms = NULL;
9✔
1724
    ssize_t tpm_rsa_key_parms_len;
9✔
1725
    g_autofree unsigned char *tpm_key_parms = NULL;
9✔
1726
    ssize_t tpm_key_parms_len;
9✔
1727
    g_autofree unsigned char *tpm_key12 = NULL;
9✔
1728
    ssize_t tpm_key12_len;
9✔
1729
    g_autofree unsigned char *in_auth_setup_params = NULL;
9✔
1730
    ssize_t in_auth_setup_params_len;
9✔
1731
    g_autofree unsigned char *macinput = NULL;
9✔
1732
    ssize_t macinput_len;
9✔
1733
    unsigned char in_param_digest[SHA_DIGEST_LENGTH];
9✔
1734
    unsigned char owner_auth[SHA_DIGEST_LENGTH];
9✔
1735
    unsigned int owner_auth_len = sizeof(owner_auth);
9✔
1736
    uint8_t continue_auth_session = 0;
9✔
1737
    unsigned char req[1024];
9✔
1738
    ssize_t req_len, len;
9✔
1739
    struct tpm_req_header *trh;
9✔
1740

1741
    mod = BN_bin2bn((const unsigned char *)pubek, pubek_len, NULL);
9✔
1742
    if (exp == NULL || mod == NULL ||
18✔
1743
        BN_hex2bn(&exp, "10001") == 0) {
9✔
1744
        logerr(self->logfile, "Could not create public RSA key!\n");
×
1745
        goto error_free_bn;
×
1746
    }
1747

1748
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1749
    ctx = EVP_PKEY_CTX_new_from_name(NULL, "rsa", NULL);
9✔
1750
    if (ctx != NULL) {
9✔
1751
        OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
9✔
1752
        OSSL_PARAM *params;
9✔
1753

1754
        if (bld == NULL ||
18✔
1755
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, exp) != 1 ||
18✔
1756
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, mod) != 1 ||
9✔
1757
            (params = OSSL_PARAM_BLD_to_param(bld)) == NULL) {
9✔
1758
            OSSL_PARAM_BLD_free(bld);
×
1759
            goto error_free_bn;
×
1760
        }
1761
        OSSL_PARAM_BLD_free(bld);
9✔
1762

1763
        if (EVP_PKEY_fromdata_init(ctx) != 1 ||
18✔
1764
            EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) != 1) {
9✔
1765
            logerr(self->logfile, "Could not set pkey parameters!\n");
×
1766
            OSSL_PARAM_free(params);
×
1767
            goto error_free_bn;
×
1768
        }
1769
        OSSL_PARAM_free(params);
9✔
1770

1771
        EVP_PKEY_CTX_free(ctx);
9✔
1772
    } else {
1773
        logerr(self->logfile, "Could not create key creation context!\n");
×
1774
        goto error_free_bn;
×
1775
    }
1776
    ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
9✔
1777
    if (ctx == NULL)
9✔
1778
        goto error_free_bn;
×
1779
#else
1780
    pkey = EVP_PKEY_new();
1781
    if (pkey == NULL) {
1782
        logerr(self->logfile, "Could not allocate pkey!\n");
1783
        goto error_free_bn;
1784
    }
1785

1786
# if OPENSSL_VERSION_NUMBER < 0x10100000
1787
    rsakey->n = mod;
1788
    rsakey->e = exp;
1789
# else
1790
    if (RSA_set0_key(rsakey, mod, exp, NULL) != 1) {
1791
        logerr(self->logfile, "Could not create public RSA key!\n");
1792
        goto error_free_bn;
1793
    }
1794
# endif
1795
    if (EVP_PKEY_assign_RSA(pkey, rsakey) != 1) {
1796
        logerr(self->logfile, "Could not create public RSA key!\n");
1797
        goto error_free_pkey_and_rsa;
1798
    }
1799

1800
    ctx = EVP_PKEY_CTX_new(pkey, NULL);
1801
    if (ctx == NULL)
1802
        goto error_free_pkey;
1803
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
1804

1805
    if (EVP_PKEY_encrypt_init(ctx) < 1 ||
18✔
1806
        EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) < 1 ||
18✔
1807
        EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sha1) < 1 ||
18✔
1808
        EVP_PKEY_CTX_set_rsa_oaep_md(ctx, sha1) < 1 ||
18✔
1809
        EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, g_strdup("TCPA"), 4) < 1 ||
18✔
1810
        EVP_PKEY_encrypt(ctx, enc_owner_auth, &enc_owner_auth_len,
9✔
1811
                         ownerpass_digest, SHA_DIGEST_LENGTH) < 1||
9✔
1812
        EVP_PKEY_encrypt(ctx, enc_srk_auth, &enc_srk_auth_len,
9✔
1813
                         srkpass_digest, SHA_DIGEST_LENGTH) < 1) {
1814
        logerr(self->logfile, "Internal error in %s: encryption failed\n", __func__);
×
1815
        goto error;
×
1816
    }
1817
    ret = swtpm_tpm12_oiap(self, &auth_handle, nonce_even);
9✔
1818
    if (ret != 0)
9✔
1819
        goto error;
×
1820

1821
    tpm_rsa_key_parms_len = memconcat(&tpm_rsa_key_parms,
18✔
1822
                                      (unsigned char[]){
9✔
1823
                                          AS4BE(2048), AS4BE(2), AS4BE(0)
1824
                                      }, (size_t)12,
1825
                                      NULL);
1826
    if (tpm_rsa_key_parms_len < 0) {
9✔
1827
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1828
        goto error;
×
1829
    }
1830

1831
    tpm_key_parms_len = memconcat(&tpm_key_parms,
18✔
1832
                                  (unsigned char[]){
9✔
1833
                                      AS4BE(TPM_ALG_RSA),
1834
                                      AS2BE(TPM_ES_RSAESOAEP_SHA1_MGF1),
1835
                                      AS2BE(TPM_SS_NONE),
1836
                                      AS4BE(tpm_rsa_key_parms_len)}, (size_t)12,
9✔
1837
                                  tpm_rsa_key_parms, tpm_rsa_key_parms_len,
1838
                                  NULL);
1839
    if (tpm_key_parms_len < 0) {
9✔
1840
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1841
        goto error;
×
1842
    }
1843

1844
    tpm_key12_len = memconcat(&tpm_key12,
18✔
1845
                              (unsigned char[]){
9✔
1846
                                  AS2BE(TPM_TAG_KEY12), AS2BE(0),
1847
                                  AS2BE(TPM_KEY_STORAGE), AS4BE(0), TPM_AUTH_ALWAYS
1848
                              }, (size_t)11,
1849
                              tpm_key_parms, tpm_key_parms_len,
1850
                              (unsigned char[]){AS4BE(0), AS4BE(0), AS4BE(0)}, (size_t)12,
9✔
1851
                              NULL);
1852
    if (tpm_key12_len < 0) {
9✔
1853
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1854
        goto error;
×
1855
    }
1856

1857
    req_len = concat(req, sizeof(req),
18✔
1858
                     &hdr, sizeof(hdr),
1859
                     (unsigned char[]){AS2BE(TPM_PID_OWNER), AS4BE(enc_owner_auth_len)}, (size_t)6,
9✔
1860
                     enc_owner_auth, enc_owner_auth_len,
1861
                     (unsigned char[]){AS4BE(enc_srk_auth_len)}, (size_t)4,
9✔
1862
                     enc_srk_auth, enc_srk_auth_len,
1863
                     tpm_key12, tpm_key12_len,
1864
                     NULL);
1865
    if (req_len < 0) {
9✔
1866
        logerr(self->logfile, "Internal error in %s: req is too small\n");
×
1867
        goto error;
×
1868
    }
1869
    SHA1(&req[6], req_len - 6, in_param_digest);
9✔
1870

1871
    in_auth_setup_params_len = memconcat(&in_auth_setup_params,
9✔
1872
                                         nonce_even, sizeof(nonce_even),
1873
                                         nonce_odd, sizeof(nonce_odd),
1874
                                         &continue_auth_session, (size_t)1,
1875
                                         NULL);
1876
    if (in_auth_setup_params_len < 0) {
9✔
1877
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1878
        goto error;
×
1879
    }
1880

1881
    macinput_len = memconcat(&macinput,
9✔
1882
                             in_param_digest, sizeof(in_param_digest),
1883
                             in_auth_setup_params, in_auth_setup_params_len,
1884
                             NULL);
1885
    if (macinput_len < 0) {
9✔
1886
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1887
        goto error;
×
1888
    }
1889

1890
    HMAC(sha1, ownerpass_digest, SHA_DIGEST_LENGTH, macinput, macinput_len,
9✔
1891
         owner_auth, &owner_auth_len);
1892

1893
    len = concat(&req[req_len], sizeof(req) - req_len,
18✔
1894
                 (unsigned char[]){AS4BE(auth_handle)}, (size_t)4,
9✔
1895
                 nonce_odd, sizeof(nonce_odd),
1896
                 &continue_auth_session, (size_t)1,
1897
                 owner_auth, owner_auth_len,
1898
                 NULL);
1899
    if (len < 0) {
9✔
1900
        logerr(self->logfile, "Internal error in %s: req is too small\n");
×
1901
        goto error;
×
1902
    }
1903
    req_len += len;
9✔
1904

1905
    trh = (struct tpm_req_header *)req; /* old gcc type-punned pointer */
9✔
1906
    trh->size = htobe32(req_len);
9✔
1907

1908
    ret = transfer(self, req, req_len, "TPM_TakeOwnership", FALSE,
9✔
1909
                   NULL, NULL, TPM_DURATION_LONG);
1910

1911
error:
9✔
1912
    EVP_PKEY_free(pkey);
9✔
1913
    EVP_PKEY_CTX_free(ctx);
9✔
1914
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1915
    BN_free(exp);
9✔
1916
    BN_free(mod);
9✔
1917
#endif
1918
    return ret;
9✔
1919

1920
error_free_bn:
×
1921
    BN_free(exp);
×
1922
    BN_free(mod);
×
1923

1924
#if OPENSSL_VERSION_NUMBER < 0x30000000L
1925
error_free_pkey_and_rsa:
1926
    RSA_free(rsakey);
1927
error_free_pkey:
1928
#else
1929
    EVP_PKEY_CTX_free(ctx);
×
1930
#endif
1931
    EVP_PKEY_free(pkey);
×
1932

1933
    return 1;
×
1934
}
1935

1936
static int swtpm_tpm12_nv_define_space(struct swtpm *self, uint32_t nvindex,
27✔
1937
                                       uint32_t nvindexattrs, size_t size)
1938
{
1939
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_DEFINE_SPACE);
27✔
1940
    g_autofree unsigned char *pcr_info_short = NULL;
54✔
1941
    ssize_t pcr_info_short_len;
27✔
1942
    g_autofree unsigned char *nv_data_public = NULL;
27✔
1943
    ssize_t nv_data_public_len;
27✔
1944
    g_autofree unsigned char *req = NULL;
27✔
1945
    ssize_t req_len;
27✔
1946
    unsigned char zeroes[SHA_DIGEST_LENGTH] = {0, };
27✔
1947

1948
    pcr_info_short_len = memconcat(&pcr_info_short,
54✔
1949
                                   (unsigned char[]){AS2BE(3), 0, 0, 0, TPM_LOC_ALL}, (size_t)6,
27✔
1950
                                   zeroes, sizeof(zeroes),
1951
                                   NULL);
1952
    if (pcr_info_short_len < 0) {
27✔
1953
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1954
        return 1;
×
1955
    }
1956

1957
    nv_data_public_len = memconcat(&nv_data_public,
54✔
1958
                                   (unsigned char[]){
27✔
1959
                                       AS2BE(TPM_TAG_NV_DATA_PUBLIC), AS4BE(nvindex)
27✔
1960
                                   }, (size_t)6,
1961
                                   pcr_info_short, pcr_info_short_len,
1962
                                   pcr_info_short, pcr_info_short_len,
1963
                                   (unsigned char[]){
27✔
1964
                                       AS2BE(TPM_TAG_NV_ATTRIBUTES), AS4BE(nvindexattrs),
27✔
1965
                                       0, 0, 0, AS4BE(size)
27✔
1966
                                   }, (size_t)13,
1967
                                   NULL);
1968
    if (nv_data_public_len < 0) {
27✔
1969
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1970
        return 1;
×
1971
    }
1972

1973
    req_len = memconcat(&req,
27✔
1974
                        &hdr, sizeof(hdr),
1975
                        nv_data_public, nv_data_public_len,
1976
                        zeroes, sizeof(zeroes),
1977
                        NULL);
1978
    if (req_len < 0) {
27✔
1979
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1980
        return 1;
×
1981
    }
1982

1983
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
27✔
1984

1985
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE,
27✔
1986
                    NULL, NULL, TPM_DURATION_SHORT);
1987
}
1988

1989
static int swtpm_tpm12_nv_write_value(struct swtpm *self, uint32_t nvindex,
15✔
1990
                                      const unsigned char *data, size_t data_len)
1991
{
1992
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_WRITE_VALUE);
15✔
1993
    g_autofree unsigned char *req = NULL;
30✔
1994
    ssize_t req_len;
15✔
1995

1996
    req_len = memconcat(&req,
30✔
1997
                        &hdr, sizeof(hdr),
1998
                        (unsigned char[]){AS4BE(nvindex), AS4BE(0), AS4BE(data_len)}, (size_t)12,
15✔
1999
                        data, data_len,
2000
                        NULL);
2001
    if (req_len < 0) {
15✔
2002
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
2003
        return 1;
×
2004
    }
2005

2006
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
15✔
2007

2008
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE,
15✔
2009
                    NULL, NULL, TPM_DURATION_SHORT);
2010
}
2011

2012
/* Write the EK Certificate into NVRAM */
2013
static int swtpm_tpm12_write_ek_cert_nvram(struct swtpm *self,
8✔
2014
                                           const unsigned char *data, size_t data_len)
2015
{
2016
    uint32_t nvindex = TPM_NV_INDEX_EKCERT | TPM_NV_INDEX_D_BIT;
8✔
2017
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
8✔
2018
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
2019
    if (ret != 0)
8✔
2020
        return 1;
2021

2022
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
8✔
2023
    if (ret != 0)
8✔
2024
        return 1;
×
2025

2026
    return 0;
2027
}
2028

2029
/* Write the Platform Certificate into NVRAM */
2030
static int swtpm_tpm12_write_platform_cert_nvram(struct swtpm *self,
7✔
2031
                                                 const unsigned char *data, size_t data_len)
2032
{
2033
    uint32_t nvindex = TPM_NV_INDEX_PLATFORMCERT | TPM_NV_INDEX_D_BIT;
7✔
2034
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
7✔
2035
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
2036
    if (ret != 0)
7✔
2037
        return 1;
2038

2039
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
7✔
2040
    if (ret != 0)
7✔
2041
        return 1;
×
2042

2043
    return 0;
2044
}
2045

2046
static int swtpm_tpm12_nv_lock(struct swtpm *self)
12✔
2047
{
2048
    return swtpm_tpm12_nv_define_space(self, TPM_NV_INDEX_LOCK, 0, 0);
12✔
2049
}
2050

2051
static const struct swtpm12_ops swtpm_tpm12_ops = {
2052
    .run_swtpm_bios = swtpm_tpm12_run_swtpm_bios,
2053
    .create_endorsement_key_pair = swptm_tpm12_create_endorsement_keypair,
2054
    .take_ownership = swtpm_tpm12_take_ownership,
2055
    .write_ek_cert_nvram = swtpm_tpm12_write_ek_cert_nvram,
2056
    .write_platform_cert_nvram = swtpm_tpm12_write_platform_cert_nvram,
2057
    .nv_lock = swtpm_tpm12_nv_lock,
2058
};
2059

2060
static void swtpm_init(struct swtpm *swtpm,
141✔
2061
                       gchar **swtpm_exec_l, const gchar *state_path,
2062
                       const gchar *keyopts, const gchar *logfile,
2063
                       int *fds_to_pass, size_t n_fds_to_pass,
2064
                       gboolean is_tpm2, const gchar *json_profile,
2065
                       int json_profile_fd,
2066
                       const gchar *profile_remove_disabled_param)
2067
{
2068
    swtpm->cops = &swtpm_cops;
141✔
2069
    swtpm->swtpm_exec_l = swtpm_exec_l;
141✔
2070
    swtpm->state_path = state_path;
141✔
2071
    swtpm->keyopts = keyopts;
141✔
2072
    swtpm->logfile = logfile;
141✔
2073
    swtpm->fds_to_pass = fds_to_pass;
141✔
2074
    swtpm->n_fds_to_pass = n_fds_to_pass;
141✔
2075
    swtpm->is_tpm2 = is_tpm2;
141✔
2076
    swtpm->json_profile = json_profile;
141✔
2077
    swtpm->json_profile_fd = json_profile_fd;
141✔
2078
    swtpm->profile_remove_disabled_param = profile_remove_disabled_param;
141✔
2079

2080
    swtpm->pid = -1;
141✔
2081
    swtpm->ctrl_fds[0] = swtpm->ctrl_fds[1] = -1;
141✔
2082
    swtpm->data_fds[0] = swtpm->data_fds[1] = -1;
141✔
2083
}
2084

2085
struct swtpm12 *swtpm12_new(gchar **swtpm_exec_l, const gchar *state_path,
26✔
2086
                            const gchar *keyopts, const gchar *logfile,
2087
                            int *fds_to_pass, size_t n_fds_to_pass)
2088
{
2089
    struct swtpm12 *swtpm12 = g_malloc0(sizeof(struct swtpm12));
26✔
2090

2091
    swtpm_init(&swtpm12->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
26✔
2092
               fds_to_pass, n_fds_to_pass, FALSE, NULL, 0, NULL);
2093
    swtpm12->ops = &swtpm_tpm12_ops;
26✔
2094

2095
    return swtpm12;
26✔
2096
}
2097

2098
struct swtpm2 *swtpm2_new(gchar **swtpm_exec_l, const gchar *state_path,
115✔
2099
                         const gchar *keyopts, const gchar *logfile,
2100
                         int *fds_to_pass, size_t n_fds_to_pass,
2101
                         const gchar *json_profile, int json_profile_fd,
2102
                         const gchar *profile_remove_disabled_param)
2103
{
2104
    struct swtpm2 *swtpm2 = g_malloc0(sizeof(struct swtpm2));
115✔
2105

2106
    swtpm_init(&swtpm2->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
115✔
2107
               fds_to_pass, n_fds_to_pass, TRUE, json_profile, json_profile_fd,
2108
               profile_remove_disabled_param);
2109
    swtpm2->ops = &swtpm_tpm2_ops;
115✔
2110

2111
    return swtpm2;
115✔
2112
}
2113

2114
void swtpm_free(struct swtpm *swtpm) {
141✔
2115
    if (!swtpm)
141✔
2116
        return;
2117
    g_free(swtpm);
141✔
2118
}
2119

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