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

stefanberger / swtpm / #2868

28 Aug 2025 01:09PM UTC coverage: 72.884% (-0.03%) from 72.913%
#2868

push

travis-ci

web-flow
Merge dae95deb6 into a7761d168

7499 of 10289 relevant lines covered (72.88%)

10412.81 hits per line

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

82.96
/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)
299✔
66
{
67
    if (all)
299✔
68
        SWTPM_CLOSE(self->data_fds[0]);
152✔
69
    SWTPM_CLOSE(self->data_fds[1]);
299✔
70

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

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

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

105
    argv = concat_arrays((const char **)self->swtpm_exec_l,
302✔
106
                         (const gchar*[]){
151✔
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)
151✔
117
        argv = concat_arrays(argv, (const gchar*[]){"--tpm2", NULL}, TRUE);
125✔
118

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

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

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

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

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

162
    argv = concat_arrays(argv, (const gchar*[]){
151✔
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;
151✔
176
    if (gl_LOGFILE) {
151✔
177
        flags |= G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
87✔
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
    }
151✔
183

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

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

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

215
error_no_pidfile:
151✔
216
    return ret;
151✔
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)
148✔
221
{
222
    unsigned c;
148✔
223
    gboolean ended = FALSE;
148✔
224

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

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

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

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

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

271
    if (use_ctrl) {
1,422✔
272
        sockfd = self->ctrl_fds[0];
345✔
273
        offset = 0;
345✔
274
    } else {
275
        sockfd = self->data_fds[0];
1,077✔
276
        offset = 6;
1,077✔
277
    }
278

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

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

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

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

318
    if (respbuffer && respbuffer_len) {
1,419✔
319
        /* give caller response even if command failed */
320
        *respbuffer_len = min((size_t)resplen, respbuffer_size);
440✔
321
        memcpy(respbuffer, resp, *respbuffer_len);
440✔
322
    }
323

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

332
    return 0;
333
}
334

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

340
    return transfer(self, &cmd, sizeof(cmd), "CMD_SHUTDOWN", TRUE,
144✔
341
                    NULL, NULL, CMD_DURATION_SHORT);
342
}
343

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

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

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

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

370
    return 0;
198✔
371

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

375
    return 1;
×
376
}
377

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

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

393
/*
394
 * TPM 2 support
395
 */
396

397
#define TPM2_ST_NO_SESSIONS  0x8001
398
#define TPM2_ST_SESSIONS     0x8002
399

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

410
#define TPM2_SU_CLEAR        0x0000
411

412
#define TPM2_RH_OWNER        0x40000001
413
#define TPM2_RS_PW           0x40000009
414
#define TPM2_RH_ENDORSEMENT  0x4000000b
415
#define TPM2_RH_PLATFORM     0x4000000c
416

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

431
#define TPM2_CAP_PCRS     0x00000005
432

433
#define TPM2_ECC_NIST_P384 0x0004
434

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

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

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

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

465
#define TPM2_DURATION_SHORT     2000 /* ms */
466
#define TPM2_DURATION_MEDIUM    7500 /* ms */
467
#define TPM2_DURATION_LONG     15000 /* ms */
468

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

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

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

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

497
static const struct bank_to_name {
498
    uint16_t hashAlg;
499
    const char *name;
500
} banks_to_names[] = {
501
    {TPM2_ALG_SHA1, "sha1"},
502
    {TPM2_ALG_SHA256, "sha256"},
503
    {TPM2_ALG_SHA384, "sha384"},
504
    {TPM2_ALG_SHA512, "sha512"},
505
    {TPM2_ALG_SM3, "sm3-256"},
506
    {TPM2_ALG_SHA3_256, "sha3-256"},
507
    {TPM2_ALG_SHA3_384, "sha3-384"},
508
    {TPM2_ALG_SHA3_512, "sha3-512"},
509
    {0, NULL},
510
};
511

512
/* function prototypes */
513
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
514
                                        const unsigned char *symkeydata, size_t symkeydata_len,
515
                                        const unsigned char *authpolicy, size_t authpolicy_len,
516
                                        unsigned int rsa_keysize, gboolean havenonce, size_t off,
517
                                        uint32_t *curr_handle,
518
                                        unsigned char *ektemplate, size_t *ektemplate_len,
519
                                        gchar **ekparam, const gchar **key_description);
520

521
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
522
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
523
                                  const char *purpose);
524

525
/* Given a hash algo identifier, return the name of the hash bank */
526
static const char *get_name_for_bank(uint16_t hashAlg) {
422✔
527
    size_t i;
422✔
528

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

536
/* Give the name of a hash bank, return its algo identifier */
537
static uint16_t get_hashalg_by_bankname(const char *name) {
420✔
538
    size_t i;
420✔
539

540
    for (i = 0; banks_to_names[i].name; i++) {
1,053✔
541
        if (strcmp(banks_to_names[i].name, name) == 0)
1,053✔
542
            return banks_to_names[i].hashAlg;
420✔
543
    }
544
    return 0;
545
}
546

547
/* Do an SU_CLEAR shutdown of the TPM 2 */
548
static int swtpm_tpm2_shutdown(struct swtpm *self)
117✔
549
{
550
    struct tpm2_shutdown_req {
117✔
551
        struct tpm_req_header hdr;
552
        uint16_t shutdownType;
553
    } __attribute__((packed)) req = {
117✔
554
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_SHUTDOWN),
117✔
555
        .shutdownType = htobe16(TPM2_SU_CLEAR)
117✔
556
    };
557

558
    return transfer(self, &req, sizeof(req), "TPM2_Shutdown", FALSE,
117✔
559
                    NULL, NULL, TPM2_DURATION_SHORT);
560
}
561

562
/* Get all available PCR banks */
563
static int swtpm_tpm2_get_all_pcr_banks(struct swtpm *self, gchar ***all_pcr_banks)
118✔
564
{
565
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, 0, TPM2_CC_GETCAPABILITY);
118✔
566
    g_autofree unsigned char *req = NULL;
236✔
567
    ssize_t req_len;
118✔
568
    unsigned char tpmresp[256];
118✔
569
    size_t tpmresp_len = sizeof(tpmresp);
118✔
570
    uint16_t count, bank;
118✔
571
    const char *name;
118✔
572
    uint8_t length;
118✔
573
    size_t offset;
118✔
574
    size_t i;
118✔
575
    int ret;
118✔
576

577
    req_len = memconcat(&req,
236✔
578
                        &hdr, sizeof(hdr),
579
                        (unsigned char[]){AS4BE(TPM2_CAP_PCRS), AS4BE(0), AS4BE(64)}, (size_t)12,
118✔
580
                        NULL);
581
    if (req_len < 0) {
118✔
582
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
583
        return 1;
×
584
    }
585
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
118✔
586

587
    ret = transfer(self, req, req_len, "TPM2_GetCapability", FALSE,
118✔
588
                   tpmresp, &tpmresp_len, TPM2_DURATION_MEDIUM);
589
    if (ret != 0)
118✔
590
        return 1;
591

592
    *all_pcr_banks = NULL;
118✔
593

594
    if (tpmresp_len < 17 + sizeof(count))
118✔
595
        goto err_too_short;
×
596
    memcpy(&count, &tpmresp[17], sizeof(count));
118✔
597
    count = be16toh(count);
118✔
598

599
    /* unreasonable number of PCR banks ? */
600
    if (count > 20)
118✔
601
        goto err_num_pcrbanks;
×
602

603
    *all_pcr_banks = g_malloc0(sizeof(char *) * (count + 1));
118✔
604

605
    offset = 19;
118✔
606

607
    for (i = 0; i < count; i++) {
540✔
608
        gchar *n;
422✔
609

610
        if (tpmresp_len < offset + sizeof(bank))
422✔
611
            goto err_too_short;
×
612
        memcpy(&bank, &tpmresp[offset], sizeof(bank));
422✔
613
        bank = be16toh(bank);
422✔
614

615
        if (tpmresp_len < offset + 2 + sizeof(length))
422✔
616
            goto err_too_short;
×
617
        length = tpmresp[offset + 2];
422✔
618

619
        name = get_name_for_bank(bank);
422✔
620
        if (name != NULL)
422✔
621
            n = g_strdup(name);
422✔
622
        else
623
            n = g_strdup_printf("%02x", bank);
×
624

625
        (*all_pcr_banks)[i] = n;
422✔
626

627
        offset += 2 + 1 + length;
422✔
628
    }
629
    return 0;
630

631
err_num_pcrbanks:
×
632
    logerr(self->logfile, "Unreasonable number of PCR banks (%u) returned.\n", count);
×
633
    goto err_exit;
×
634

635
err_too_short:
×
636
    logerr(self->logfile, "Response from TPM2_GetCapability is too short!\n");
×
637

638
err_exit:
×
639
    g_strfreev(*all_pcr_banks);
×
640
    *all_pcr_banks = NULL;
×
641

642
    return 1;
×
643
}
644

645
/* Activate all user-chosen PCR banks and deactivate all others */
646
static int swtpm_tpm2_set_active_pcr_banks(struct swtpm *self, gchar **pcr_banks,
118✔
647
                                           gchar **all_pcr_banks, gchar ***active)
648
{
649
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_PCR_ALLOCATE);
118✔
650
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
118✔
651
    unsigned char pcrselects[6 * 10]; // supports up to 10 PCR banks
118✔
652
    ssize_t pcrselects_len = 0;
118✔
653
    size_t count = 0;
118✔
654
    size_t idx, j;
118✔
655
    uint16_t hashAlg;
118✔
656
    g_autofree unsigned char *req = NULL;
236✔
657
    ssize_t req_len, len;
118✔
658
    int ret;
118✔
659
    uint64_t activated_mask = 0;
118✔
660

661
    for (idx = 0; pcr_banks[idx] != NULL; idx++)
242✔
662
        ;
663
    *active = g_malloc0(sizeof(char *) * (idx + 1));
118✔
664

665
    for (idx = 0; pcr_banks[idx] != NULL; idx++) {
242✔
666
        hashAlg = 0;
232✔
667
        // Is user-chosen pcr_banks[idx] available?
668
        for (j = 0; all_pcr_banks[j] != NULL; j++) {
232✔
669
            if (strcmp(pcr_banks[idx], all_pcr_banks[j]) == 0) {
231✔
670
                hashAlg = get_hashalg_by_bankname(pcr_banks[idx]);
123✔
671
                break;
123✔
672
            }
673
        }
674
        if (hashAlg != 0 && (activated_mask & ((uint64_t)1 << j)) == 0) {
124✔
675
            (*active)[count] = g_strdup(pcr_banks[idx]);
123✔
676
            len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
246✔
677
                         (unsigned char[]){AS2BE(hashAlg), 3, 0xff, 0xff, 0xff} , (size_t)6,
123✔
678
                         NULL);
679
            if (len < 0) {
123✔
680
                logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
681
                return 1;
×
682
            }
683
            pcrselects_len += len;
123✔
684
            count++;
123✔
685
            activated_mask |= ((uint64_t)1 << j);
123✔
686
        }
687
    }
688

689
    if (count == 0) {
118✔
690
        logerr(self->logfile,
1✔
691
               "No PCR banks could be allocated. None of the selected algorithms are supported.\n");
692
        goto error;
1✔
693
    }
694

695
    // disable all the other ones not chosen by the user
696
    for (idx = 0; all_pcr_banks[idx] != NULL; idx++) {
537✔
697
        gboolean found = FALSE;
733✔
698

699
        for (j = 0; pcr_banks[j] != NULL; j++) {
733✔
700
            if (strcmp(pcr_banks[j], all_pcr_banks[idx]) == 0) {
436✔
701
                found = TRUE;
702
                break;
703
            }
704
        }
705
        if (found)
420✔
706
            continue;
123✔
707

708
        /* not found, so not chosen by user */
709
        hashAlg = get_hashalg_by_bankname(all_pcr_banks[idx]);
297✔
710

711
        len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len,
594✔
712
                     (unsigned char[]){AS2BE(hashAlg), 3, 0, 0, 0}, (size_t)6,
297✔
713
                     NULL);
714
        if (len < 0) {
297✔
715
            logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__);
×
716
            goto error;
×
717
        }
718
        pcrselects_len += len;
297✔
719
        count++;
297✔
720
    }
721

722
    req_len = memconcat(&req,
234✔
723
                        &hdr, sizeof(hdr),
724
                        (unsigned char[]){
117✔
725
                             AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))
726
                        }, (size_t)8,
727
                        &authblock, sizeof(authblock),
728
                        (unsigned char[]){AS4BE(count)}, (size_t)4,
117✔
729
                        pcrselects, pcrselects_len,
730
                        NULL);
731
    if (req_len < 0) {
117✔
732
        logerr(self->logfile, "Internal error in %s: req is too small\n", __func__);
×
733
        goto error;
×
734
    }
735
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
117✔
736

737
    ret = transfer(self, req, req_len, "TPM2_PCR_Allocate", FALSE,
117✔
738
                   NULL, NULL, TPM2_DURATION_SHORT);
739
    if (ret != 0)
117✔
740
        goto error;
×
741

742
    return 0;
743

744
error:
1✔
745
    g_strfreev(*active);
1✔
746
    *active = NULL;
1✔
747

748
    return 1;
1✔
749
}
750

751
static int swtpm_tpm2_flushcontext(struct swtpm *self, uint32_t handle)
4✔
752
{
753
    struct tpm2_flushcontext_req {
4✔
754
        struct tpm_req_header hdr;
755
        uint32_t flushHandle;
756
    } __attribute__((packed)) req = {
4✔
757
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_FLUSHCONTEXT),
4✔
758
        .flushHandle = htobe32(handle),
4✔
759
    };
760

761
    return transfer(self, &req, sizeof(req), "TPM2_FlushContext", FALSE,
4✔
762
                    NULL, NULL, TPM2_DURATION_SHORT);
763
}
764

765
/* Make object at the curr_handler permanent with the perm_handle */
766
static int swtpm_tpm2_evictcontrol(struct swtpm *self, uint32_t curr_handle, uint32_t perm_handle)
96✔
767
{
768
    struct tpm2_evictcontrol_req {
96✔
769
        struct tpm_req_header hdr;
770
        uint32_t auth;
771
        uint32_t objectHandle;
772
        uint32_t authblockLen;
773
        struct tpm2_authblock authblock;
774
        uint32_t persistentHandle;
775
    } __attribute__((packed)) req = {
96✔
776
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, sizeof(req), TPM2_CC_EVICTCONTROL),
96✔
777
        .auth = htobe32(TPM2_RH_OWNER),
96✔
778
        .objectHandle = htobe32(curr_handle),
96✔
779
        .authblockLen = htobe32(sizeof(req.authblock)),
96✔
780
        .authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW),
96✔
781
        .persistentHandle = htobe32(perm_handle),
96✔
782
    };
783

784
    return transfer(self, &req, sizeof(req), "TPM2_EvictControl", FALSE,
96✔
785
                    NULL, NULL, TPM2_DURATION_SHORT);
786
}
787

788
/* Create an RSA EK */
789
static int swtpm_tpm2_createprimary_ek_rsa(struct swtpm *self, unsigned int rsa_keysize,
46✔
790
                                           gboolean allowsigning, gboolean decryption,
791
                                           uint32_t *curr_handle,
792
                                           unsigned char *ektemplate, size_t *ektemplate_len,
793
                                           gchar **ekparam, const gchar **key_description)
794
{
795
    unsigned char authpolicy[48];
46✔
796
    size_t authpolicy_len;
46✔
797
    unsigned char symkeydata[6];
46✔
798
    size_t symkeydata_len;
46✔
799
    unsigned int keyflags;
46✔
800
    unsigned int symkeylen;
46✔
801
    gboolean havenonce;
46✔
802
    size_t addlen, off;
46✔
803

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

833
    if (allowsigning && decryption) {
46✔
834
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
835
        // adminWithPolicy, sign, decrypt
836
        keyflags |= 0x000600b2;
7✔
837
        // symmetric: TPM_ALG_NULL
838
        symkeydata_len = 2;
7✔
839
        memcpy(symkeydata, ((unsigned char[]) {AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
7✔
840
        off = 72 + addlen;
7✔
841
    } else if (allowsigning) {
39✔
842
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
843
        // adminWithPolicy, sign
844
        keyflags |= 0x000400b2;
17✔
845
        // symmetric: TPM_ALG_NULL
846
        symkeydata_len = 2;
17✔
847
        memcpy(symkeydata, ((unsigned char[]) {AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
17✔
848
        off = 72 + addlen;
17✔
849
    } else {
850
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
851
        // adminWithPolicy, restricted, decrypt
852
        keyflags |= 0x000300b2;
22✔
853
        // symmetric: TPM_ALG_AES, 128bit or 256bit, TPM_ALG_CFB
854
        symkeydata_len = 6;
22✔
855
        memcpy(symkeydata,
22✔
856
               ((unsigned char[]) {AS2BE(TPM2_ALG_AES), AS2BE(symkeylen), AS2BE(TPM2_ALG_CFB)}),
22✔
857
               symkeydata_len);
858
        off = 76 + addlen;
22✔
859
    }
860

861
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_ENDORSEMENT, keyflags,
46✔
862
                                        symkeydata, symkeydata_len,
863
                                        authpolicy, authpolicy_len, rsa_keysize,
864
                                        havenonce, off, curr_handle,
865
                                        ektemplate, ektemplate_len, ekparam, key_description);
866
}
867

868
/* Create an RSA key with the given parameters */
869
static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
49✔
870
                                        const unsigned char *symkeydata, size_t symkeydata_len,
871
                                        const unsigned char *authpolicy, size_t authpolicy_len,
872
                                        unsigned int rsa_keysize, gboolean havenonce, size_t off,
873
                                        uint32_t *curr_handle,
874
                                        unsigned char *ektemplate, size_t *ektemplate_len,
875
                                        gchar **ekparam, const gchar **key_description)
876
{
877
    const unsigned char *nonce;
49✔
878
    size_t nonce_len;
49✔
879
    uint16_t hashalg;
49✔
880
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY);
49✔
881
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
49✔
882
    g_autofree unsigned char *public = NULL;
98✔
883
    ssize_t public_len;
49✔
884
    g_autofree unsigned char *createprimary = NULL;
49✔
885
    ssize_t createprimary_len;
49✔
886
    int ret;
49✔
887
    unsigned char tpmresp[2048];
49✔
888
    size_t tpmresp_len = sizeof(tpmresp);
49✔
889
    uint16_t modlen;
49✔
890

891
    if (rsa_keysize == 2048) {
49✔
892
        nonce = NONCE_RSA2048;
28✔
893
        nonce_len = sizeof(NONCE_RSA2048);
28✔
894
        hashalg = TPM2_ALG_SHA256;
28✔
895
        if (key_description)
28✔
896
            *key_description = "rsa2048";
27✔
897
    } else if (rsa_keysize == 3072) {
21✔
898
        if (!havenonce) {
13✔
899
           nonce = NONCE_EMPTY;
900
           nonce_len = sizeof(NONCE_EMPTY);
901
        } else {
902
           nonce = NONCE_RSA3072;
1✔
903
           nonce_len = sizeof(NONCE_RSA3072);
1✔
904
        }
905
        hashalg = TPM2_ALG_SHA384;
13✔
906
        if (key_description)
13✔
907
            *key_description = "rsa3072";
12✔
908
    } else if (rsa_keysize == 4096) {
8✔
909
        if (!havenonce) {
8✔
910
           nonce = NONCE_EMPTY;
911
           nonce_len = sizeof(NONCE_EMPTY);
912
        } else {
913
           nonce = NONCE_RSA4096;
1✔
914
           nonce_len = sizeof(NONCE_RSA4096);
1✔
915
        }
916
        hashalg = TPM2_ALG_SHA384;
8✔
917
        if (key_description)
8✔
918
            *key_description = "rsa4096";
7✔
919
    } else {
920
        logerr(self->logfile, "Internal error in %s: unsupported RSA keysize %d.\n",
×
921
               __func__, rsa_keysize);
922
        return 1;
×
923
    }
924

925
    public_len =
49✔
926
        memconcat(&public,
98✔
927
                  (unsigned char[]) {
49✔
928
                      AS2BE(TPM2_ALG_RSA), AS2BE(hashalg),
929
                      AS4BE(keyflags), AS2BE(authpolicy_len)
49✔
930
                  }, (size_t)10,
931
                  authpolicy, authpolicy_len,
932
                  symkeydata, symkeydata_len,
933
                  (unsigned char[]) {
49✔
934
                      AS2BE(TPM2_ALG_NULL), AS2BE(rsa_keysize), AS4BE(0)
49✔
935
                  }, (size_t)8,
936
                  nonce, nonce_len,
937
                  NULL);
938
    if (public_len < 0) {
49✔
939
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
940
        return 1;
×
941
    }
942
    if (ektemplate) {
49✔
943
        if (*ektemplate_len < (size_t)public_len) {
46✔
944
            logerr(self->logfile, "Internal error in %s: Need %zu bytes for ektemplate (rsa) but got only %zu\n",
×
945
                   __func__, public_len, *ektemplate_len);
946
            return 1;
×
947
        }
948
        memcpy(ektemplate, public, public_len);
46✔
949
        *ektemplate_len = public_len;
46✔
950
    }
951

952
    createprimary_len =
49✔
953
        memconcat(&createprimary,
98✔
954
                  &hdr, sizeof(hdr),
955
                  (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8,
49✔
956
                  &authblock, sizeof(authblock),
957
                  (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8,
49✔
958
                  public, public_len,
959
                  (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
49✔
960
                  NULL);
961
    if (createprimary_len < 0) {
49✔
962
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
963
        return 1;
×
964
    }
965
    ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len);
49✔
966

967
    ret = transfer(self, createprimary, createprimary_len, "TPM2_CreatePrimary(RSA)", FALSE,
49✔
968
                   tpmresp, &tpmresp_len, TPM2_DURATION_LONG);
969
    if (ret != 0) {
49✔
970
        if (tpmresp_len >= sizeof(struct tpm_resp_header) &&
×
971
            be32toh(((struct tpm_resp_header *)tpmresp)->errcode) == 0x2c4) {
×
972
            /*
973
             * Error may appear when key size is not supported by profile:
974
             * value is out of range or is not correct for the context Parameter number 2
975
             */
976
            logerr(self->logfile,
×
977
                   ">> Is RSA-%u supported by the profile? RSA-4096 needs 'default-v2'.<<\n",
978
                   rsa_keysize);
979
        }
980
        return 1;
×
981
    }
982

983
    if (curr_handle) {
49✔
984
        if (tpmresp_len < 10 + sizeof(*curr_handle))
49✔
985
            goto err_too_short;
×
986
        memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle));
49✔
987
        *curr_handle = be32toh(*curr_handle);
49✔
988
    }
989

990
    if (tpmresp_len < off + sizeof(modlen))
49✔
991
         goto err_too_short;
×
992
    memcpy(&modlen, &tpmresp[off], sizeof(modlen));
49✔
993
    modlen = be16toh(modlen);
49✔
994
    if (modlen != rsa_keysize >> 3) {
49✔
995
        logerr(self->logfile, "Internal error in %s: Getting modulus from wrong offset %zu\n",
×
996
               __func__, off);
997
        return 1;
×
998
    }
999
    if (ekparam) {
49✔
1000
        if (tpmresp_len < off + 2 + modlen)
46✔
1001
            goto err_too_short;
×
1002
        *ekparam = print_as_hex(&tpmresp[off + 2], modlen);
46✔
1003
    }
1004

1005
    return 0;
1006

1007
err_too_short:
×
1008
    logerr(self->logfile, "Response from TPM2_CreatePrimary(RSA) is too short!\n");
×
1009
    return 1;
×
1010
}
1011

1012
/* Create an ECC key with the given parameters */
1013
static int swtpm_tpm2_createprimary_ecc(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags,
47✔
1014
                                        const unsigned char *symkeydata, size_t symkeydata_len,
1015
                                        const unsigned char *authpolicy, size_t authpolicy_len,
1016
                                        const unsigned char *schemedata, size_t schemedata_len,
1017
                                        unsigned short curveid, unsigned short hashalg,
1018
                                        const unsigned char *nonce, size_t nonce_len,
1019
                                        size_t off, uint32_t *curr_handle,
1020
                                        unsigned char *ektemplate, size_t *ektemplate_len,
1021
                                        gchar **ekparam, const gchar **key_description)
1022
{
1023
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY);
47✔
1024
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
47✔
1025
    g_autofree unsigned char *public = NULL;
94✔
1026
    ssize_t public_len;
47✔
1027
    g_autofree unsigned char *createprimary = NULL;
47✔
1028
    ssize_t createprimary_len;
47✔
1029
    int ret;
47✔
1030
    unsigned char tpmresp[2048];
47✔
1031
    size_t tpmresp_len = sizeof(tpmresp);
47✔
1032
    size_t off2;
47✔
1033
    uint16_t exp_ksize, ksize1, ksize2;
47✔
1034
    const char *cid;
47✔
1035

1036
    public_len =
47✔
1037
        memconcat(&public,
94✔
1038
                  (unsigned char[]){
47✔
1039
                      AS2BE(TPM2_ALG_ECC), AS2BE(hashalg), AS4BE(keyflags), AS2BE(authpolicy_len)
47✔
1040
                  }, (size_t)10,
1041
                  authpolicy, authpolicy_len,
1042
                  symkeydata, symkeydata_len,
1043
                  schemedata, schemedata_len,
1044
                  nonce, nonce_len,
1045
                  nonce, nonce_len,
1046
                  NULL);
1047
    if (public_len < 0) {
47✔
1048
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1049
        return 1;
×
1050
    }
1051
    if (ektemplate) {
47✔
1052
        if (*ektemplate_len < (size_t)public_len) {
46✔
1053
            logerr(self->logfile, "Internal error: Need %zu bytes for ektemplate (ecc) but got only %zu\n",
×
1054
                   public_len, ektemplate_len);
1055
            return 1;
×
1056
        }
1057
        memcpy(ektemplate, public, public_len);
46✔
1058
        *ektemplate_len = public_len;
46✔
1059
    }
1060

1061
    createprimary_len =
47✔
1062
        memconcat(&createprimary,
94✔
1063
                  &hdr, sizeof(hdr),
1064
                  (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8,
47✔
1065
                  &authblock, sizeof(authblock),
1066
                  (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8,
47✔
1067
                  public, public_len,
1068
                  (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
47✔
1069
                  NULL);
1070
    if (createprimary_len < 0) {
47✔
1071
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1072
        return 1;
×
1073
    }
1074
    ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len);
47✔
1075

1076
    ret = transfer(self, createprimary, createprimary_len, "TPM2_CreatePrimary(ECC)", FALSE,
47✔
1077
                   tpmresp, &tpmresp_len, TPM2_DURATION_LONG);
1078
    if (ret != 0)
47✔
1079
        return 1;
1080
    if (curr_handle) {
47✔
1081
        if (tpmresp_len < 10 + sizeof(*curr_handle))
47✔
1082
            goto err_too_short;
×
1083
        memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle));
47✔
1084
        *curr_handle = be32toh(*curr_handle);
47✔
1085
    }
1086

1087
    if (curveid == TPM2_ECC_NIST_P384) {
47✔
1088
        exp_ksize = 48;
47✔
1089
        cid = "secp384r1";
47✔
1090
        if (key_description)
47✔
1091
            *key_description = cid;
46✔
1092
    } else {
1093
        logerr(self->logfile, "Unknown curveid 0x%x\n", curveid);
×
1094
        return 1;
×
1095
    }
1096

1097
    if (tpmresp_len < off + sizeof(ksize1))
47✔
1098
        goto err_too_short;
×
1099
    memcpy(&ksize1, &tpmresp[off], sizeof(ksize1));
47✔
1100
    ksize1 = be16toh(ksize1);
47✔
1101
    off2 = off + 2 + ksize1;
47✔
1102

1103
    if (tpmresp_len < off2 + sizeof(ksize2))
47✔
1104
        goto err_too_short;
×
1105
    memcpy(&ksize2, &tpmresp[off2], sizeof(ksize2));
47✔
1106
    ksize2 = be16toh(ksize2);
47✔
1107

1108
    if (ksize1 != exp_ksize || ksize2 != exp_ksize) {
47✔
1109
        logerr(self->logfile, "ECC: Getting key parameters from wrong offset\n");
×
1110
        return 1;
×
1111
    }
1112

1113
    if (ekparam) {
47✔
1114
        unsigned char *xparam = &tpmresp[off + 2];
46✔
1115
        unsigned char *yparam = &tpmresp[off2 + 2];
46✔
1116
        if (tpmresp_len < off + 2 + ksize1 || tpmresp_len < off2 + 2 + ksize2)
46✔
1117
            goto err_too_short;
×
1118
        g_autofree gchar *xparam_str = print_as_hex(xparam, ksize1);
92✔
1119
        g_autofree gchar *yparam_str = print_as_hex(yparam, ksize2);
92✔
1120

1121
        *ekparam = g_strdup_printf("x=%s,y=%s,id=%s", xparam_str, yparam_str, cid);
46✔
1122
    }
1123

1124
    return 0;
1125

1126
err_too_short:
×
1127
    logerr(self->logfile, "Response from TPM2_CreatePrimary(ECC) is too short!\n");
×
1128
    return 1;
×
1129
}
1130

1131
static int swtpm_tpm2_createprimary_spk_ecc_nist_p384(struct swtpm *self,
1✔
1132
                                                      uint32_t *curr_handle)
1133
{
1134
    // keyflags: fixedTPM, fixedParent, sensitiveDataOrigin, userWithAuth
1135
    //           noDA, restricted, decrypt
1136
    unsigned int keyflags = 0x00030472;
1✔
1137
    const unsigned char authpolicy[0] = { };
1✔
1138
    size_t authpolicy_len = sizeof(authpolicy);
1✔
1139
    const unsigned char symkeydata[] = {AS2BE(TPM2_ALG_AES), AS2BE(256), AS2BE(TPM2_ALG_CFB)};
1✔
1140
    size_t symkeydata_len = sizeof(symkeydata);
1✔
1141
    const unsigned char schemedata[] = {
1✔
1142
        AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P384), AS2BE(TPM2_ALG_NULL)
1143
    };
1144
    size_t schemedata_len = sizeof(schemedata);
1✔
1145
    size_t off = 42;
1✔
1146

1147
    /* per "TCG TPM v2.0 Provisioning Guidance v1.0" page 37
1148
     * -> "Ek Credential Profile 2.0" rev.14 section 2.1.5.2:
1149
     * template for NIST P256 uses 2 identical 32-byte all-zero nonces
1150
     * -> Use two 48-byte all-zero nonces for NIST P384.
1151
     */
1152

1153
    return swtpm_tpm2_createprimary_ecc(self, TPM2_RH_OWNER, keyflags, symkeydata, symkeydata_len,
1✔
1154
                                        authpolicy, authpolicy_len, schemedata, schemedata_len,
1155
                                        TPM2_ECC_NIST_P384, TPM2_ALG_SHA384,
1156
                                        NONCE_ECC_384, sizeof(NONCE_ECC_384), off, curr_handle,
1157
                                        NULL, 0, NULL, NULL);
1158
}
1159

1160
static int swtpm_tpm2_createprimary_spk_rsa(struct swtpm *self, unsigned int rsa_keysize,
3✔
1161
                                            uint32_t *curr_handle)
1162
{
1163
    // keyflags: fixedTPM, fixedParent, sensitiveDataOrigin, userWithAuth
1164
    //           noDA, restricted, decrypt
1165
    unsigned int keyflags = 0x00030472;
3✔
1166
    const unsigned char authpolicy[0] = { };
3✔
1167
    size_t authpolicy_len = sizeof(authpolicy);
3✔
1168
    unsigned short symkeylen = 0;
3✔
1169
    unsigned char symkeydata[6];
3✔
1170
    size_t symkeydata_len;
3✔
1171
    size_t off = 44;
3✔
1172

1173
    if (rsa_keysize == 2048)
3✔
1174
        symkeylen = 128;
1175
    else if (rsa_keysize == 3072 || rsa_keysize == 4096)
2✔
1176
        symkeylen = 256;
2✔
1177

1178
    symkeydata_len = 6;
3✔
1179
    memcpy(symkeydata,
3✔
1180
           ((unsigned char[]) {AS2BE(TPM2_ALG_AES), AS2BE(symkeylen), AS2BE(TPM2_ALG_CFB)}),
3✔
1181
           symkeydata_len);
1182

1183
    return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_OWNER, keyflags,
3✔
1184
                                        symkeydata, symkeydata_len,
1185
                                        authpolicy, authpolicy_len, rsa_keysize, TRUE,
1186
                                        off, curr_handle, NULL, 0, NULL, NULL);
1187
}
1188

1189
/* Create either an ECC or RSA storage primary key (deprecated) */
1190
static int swtpm_tpm2_create_spk(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize)
4✔
1191
{
1192
    int ret;
4✔
1193
    uint32_t curr_handle;
4✔
1194

1195
    if (isecc)
4✔
1196
        ret = swtpm_tpm2_createprimary_spk_ecc_nist_p384(self, &curr_handle);
1✔
1197
    else
1198
        ret = swtpm_tpm2_createprimary_spk_rsa(self, rsa_keysize, &curr_handle);
3✔
1199

1200
    if (ret != 0)
4✔
1201
        return 1;
1202

1203
    ret = swtpm_tpm2_evictcontrol(self, curr_handle, TPM2_SPK_HANDLE);
4✔
1204
    if (ret == 0)
4✔
1205
        logit(self->logfile,
4✔
1206
              "Successfully created storage primary key with handle 0x%x.\n", TPM2_SPK_HANDLE);
1207

1208
    ret = swtpm_tpm2_flushcontext(self, curr_handle);
4✔
1209
    if (ret != 0) {
4✔
1210
        logerr(self->logfile, "Could not flush storage primary key.\n");
×
1211
        ret = 1;
×
1212
    }
1213

1214
    return ret;
1215
}
1216

1217
/* Create an ECC EK key that may be allowed to sign and/or decrypt */
1218
static int swtpm_tpm2_createprimary_ek_ecc_nist_p384(struct swtpm *self, gboolean allowsigning,
46✔
1219
                                                     gboolean decryption, uint32_t *curr_handle,
1220
                                                     unsigned char *ektemplate, size_t *ektemplate_len,
1221
                                                     gchar **ekparam, const char **key_description)
1222
{
1223
    unsigned char authpolicy[48]= {
46✔
1224
        0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC, 0x53, 0xD8, 0x82, 0xBC,
1225
        0xF5, 0xFD, 0x3A, 0x1A, 0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4,
1226
        0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA, 0xCB, 0x47, 0xBA, 0x09,
1227
        0x69, 0x96, 0x46, 0x15, 0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12
1228
    };
1229
    const unsigned char schemedata[] = {
46✔
1230
        AS2BE(TPM2_ALG_NULL), AS2BE(TPM2_ECC_NIST_P384), AS2BE(TPM2_ALG_NULL)
1231
    };
1232
    size_t schemedata_len = sizeof(schemedata);
46✔
1233
    size_t authpolicy_len = 48;
46✔
1234
    unsigned char symkeydata[6];
46✔
1235
    size_t symkeydata_len;
46✔
1236
    unsigned int keyflags;
46✔
1237
    size_t off;
46✔
1238
    int ret;
46✔
1239

1240
    if (allowsigning && decryption) {
46✔
1241
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1242
        // userWithAuth, adminWithPolicy, sign, decrypt
1243
        keyflags = 0x000600f2;
7✔
1244
        // symmetric: TPM_ALG_NULL
1245
        symkeydata_len = 2;
7✔
1246
        memcpy(symkeydata, ((unsigned char[]){AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
7✔
1247
        off = 86;
7✔
1248
    } else if (allowsigning) {
39✔
1249
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1250
        // userWithAuth, adminWithPolicy, sign
1251
        keyflags = 0x000400f2;
17✔
1252
        // symmetric: TPM_ALG_NULL
1253
        symkeydata_len = 2;
17✔
1254
        memcpy(symkeydata, ((unsigned char[]){AS2BE(TPM2_ALG_NULL)}), symkeydata_len);
17✔
1255
        off = 86;
17✔
1256
    } else {
1257
        // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1258
        // userWithAuth, adminWithPolicy, restricted, decrypt
1259
        keyflags = 0x000300f2;
22✔
1260
        // symmetric: TPM_ALG_AES, 256bit, TPM_ALG_CFB
1261
        symkeydata_len = 6;
22✔
1262
        memcpy(symkeydata,
22✔
1263
               ((unsigned char[]){ AS2BE(TPM2_ALG_AES), AS2BE(256), AS2BE(TPM2_ALG_CFB)}),
22✔
1264
               symkeydata_len);
1265
        off = 90;
22✔
1266
    }
1267

1268
    ret = swtpm_tpm2_createprimary_ecc(self, TPM2_RH_ENDORSEMENT, keyflags,
46✔
1269
                                       symkeydata, symkeydata_len,
1270
                                       authpolicy, authpolicy_len,
1271
                                       schemedata, schemedata_len,
1272
                                       TPM2_ECC_NIST_P384, TPM2_ALG_SHA384,
1273
                                       NONCE_EMPTY, sizeof(NONCE_EMPTY), off, curr_handle,
1274
                                       ektemplate, ektemplate_len, ekparam, key_description);
1275
    if (ret != 0)
46✔
1276
       logerr(self->logfile, "%s failed\n", __func__);
×
1277

1278
    return ret;
46✔
1279
}
1280

1281
/* Create an ECC or RSA EK */
1282
static int swtpm_tpm2_create_ek(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize,
92✔
1283
                                gboolean allowsigning, gboolean decryption, gboolean lock_nvram,
1284
                                gchar **ekparam, const  gchar **key_description)
1285
{
1286
    uint32_t tpm2_ek_handle, nvindex, curr_handle;
92✔
1287
    const char *keytype;
92✔
1288
    int ret;
92✔
1289
    unsigned char ektemplate[512];
92✔
1290
    size_t ektemplate_len = sizeof(ektemplate);
92✔
1291

1292
    if (isecc) {
92✔
1293
        tpm2_ek_handle = TPM2_EK_ECC_SECP384R1_HANDLE;
1294
        keytype = "ECC";
1295
        nvindex = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE;
1296
    } else {
1297
        if (rsa_keysize == 2048) {
46✔
1298
            tpm2_ek_handle = TPM2_EK_RSA_HANDLE;
1299
            keytype = "RSA 2048";
1300
            nvindex = TPM2_NV_INDEX_RSA2048_EKTEMPLATE;
1301
        } else if (rsa_keysize == 3072) {
19✔
1302
            tpm2_ek_handle = TPM2_EK_RSA3072_HANDLE;
1303
            keytype = "RSA 3072";
1304
            nvindex = TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE;
1305
        } else if (rsa_keysize == 4096) {
7✔
1306
            tpm2_ek_handle = TPM2_EK_RSA4096_HANDLE;
1307
            keytype = "RSA 4096";
1308
            nvindex = TPM2_NV_INDEX_RSA4096_HI_EKTEMPLATE;
1309
        } else {
1310
            logerr(self->logfile, "Internal error: Unsupported RSA keysize %u.\n", rsa_keysize);
×
1311
            return 1;
×
1312
        }
1313
    }
1314
    if (isecc)
92✔
1315
        ret = swtpm_tpm2_createprimary_ek_ecc_nist_p384(self, allowsigning, decryption, &curr_handle,
46✔
1316
                                                        ektemplate, &ektemplate_len, ekparam,
1317
                                                        key_description);
1318
    else
1319
        ret = swtpm_tpm2_createprimary_ek_rsa(self, rsa_keysize, allowsigning, decryption, &curr_handle,
46✔
1320
                                              ektemplate, &ektemplate_len, ekparam, key_description);
1321

1322
    if (ret == 0)
92✔
1323
        ret = swtpm_tpm2_evictcontrol(self, curr_handle, tpm2_ek_handle);
92✔
1324
    if (ret != 0) {
92✔
1325
        logerr(self->logfile, "create_ek failed: 0x%x\n", ret);
×
1326
        return 1;
×
1327
    }
1328

1329
    logit(self->logfile,
92✔
1330
          "Successfully created %s EK with handle 0x%x.\n", keytype, tpm2_ek_handle);
1331

1332
    if (allowsigning) {
92✔
1333
        uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE | \
48✔
1334
                TPMA_NV_AUTHREAD | \
1335
                TPMA_NV_OWNERREAD | \
1336
                TPMA_NV_PPREAD | \
1337
                TPMA_NV_PPWRITE | \
1338
                TPMA_NV_NO_DA | \
1339
                TPMA_NV_WRITEDEFINE;
1340
        ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, ektemplate, ektemplate_len,
48✔
1341
                                     lock_nvram, "EK template");
1342
        if (ret == 0)
48✔
1343
            logit(self->logfile,
48✔
1344
                  "Successfully created NVRAM area 0x%x for %s EK template.\n",
1345
                  nvindex, keytype);
1346
    }
1347

1348
    return ret;
1349
}
1350

1351
static int swtpm_tpm2_nvdefinespace(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
165✔
1352
                                    uint16_t data_len)
1353
{
1354
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_DEFINESPACE);
165✔
1355
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
165✔
1356
    g_autofree unsigned char *nvpublic = NULL;
330✔
1357
    ssize_t nvpublic_len;
165✔
1358
    g_autofree unsigned char *req = NULL;
165✔
1359
    ssize_t req_len;
165✔
1360

1361
    nvpublic_len = memconcat(&nvpublic,
330✔
1362
                             (unsigned char[]){
165✔
1363
                                 AS4BE(nvindex), AS2BE(TPM2_ALG_SHA256), AS4BE(nvindexattrs),
165✔
1364
                                 AS2BE(0), AS2BE(data_len)}, (size_t)14,
1365
                             NULL);
1366
    if (nvpublic_len < 0) {
165✔
1367
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1368
        return 1;
×
1369
    }
1370

1371
    req_len = memconcat(&req,
330✔
1372
                        &hdr, sizeof(hdr),
1373
                        (unsigned char[]){AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))}, (size_t)8,
165✔
1374
                        &authblock, sizeof(authblock),
1375
                        (unsigned char[]){AS2BE(0), AS2BE(nvpublic_len)}, (size_t)4,
165✔
1376
                        nvpublic, nvpublic_len,
1377
                        NULL);
1378
    if (req_len < 0) {
165✔
1379
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1380
        return 1;
×
1381
    }
1382

1383
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
165✔
1384

1385
    return transfer(self, req, req_len, "TPM2_NV_DefineSpace", FALSE,
165✔
1386
                    NULL, NULL, TPM2_DURATION_SHORT);
1387
}
1388

1389
/* Write the data into the given NVIndex */
1390
static int swtpm_tpm2_nv_write(struct swtpm *self, uint32_t nvindex,
165✔
1391
                               const unsigned char *data, size_t data_len)
1392
{
1393
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITE);
165✔
1394
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
165✔
1395
    g_autofree unsigned char *req = NULL;
330✔
1396
    ssize_t req_len;
165✔
1397
    size_t offset = 0, txlen;
165✔
1398
    int ret;
165✔
1399

1400
    while (offset < data_len) {
334✔
1401
        txlen = min(data_len - offset, 1024);
169✔
1402

1403
        g_free(req);
169✔
1404
        req_len = memconcat(&req,
338✔
1405
                            &hdr, sizeof(hdr),
1406
                            (unsigned char[]){
169✔
1407
                                AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
169✔
1408
                            }, (size_t)12,
1409
                            &authblock, sizeof(authblock),
1410
                            (unsigned char[]){AS2BE(txlen)}, (size_t)2,
169✔
1411
                            &data[offset], txlen,
1412
                            (unsigned char[]){AS2BE(offset)}, (size_t)2,
169✔
1413
                            NULL);
1414
        if (req_len < 0) {
169✔
1415
            logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1416
            return 1;
×
1417
        }
1418
        ((struct tpm_req_header *)req)->size = htobe32(req_len);
169✔
1419

1420
        ret = transfer(self, req, req_len, "TPM2_NV_Write", FALSE,
169✔
1421
                       NULL, NULL, TPM2_DURATION_SHORT);
1422
        if (ret != 0)
169✔
1423
            return 1;
1424

1425
        offset += txlen;
169✔
1426
    }
1427
    return 0;
1428
}
1429

1430
static int swtpm_tpm2_nv_writelock(struct swtpm *self, uint32_t nvindex)
12✔
1431
{
1432
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITELOCK);
12✔
1433
    struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW);
12✔
1434
    g_autofree unsigned char *req;
24✔
1435
    ssize_t req_len;
12✔
1436

1437
    req_len = memconcat(&req,
24✔
1438
                        &hdr, sizeof(hdr),
1439
                        (unsigned char[]){
12✔
1440
                           AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock))
12✔
1441
                        }, (size_t)12,
1442
                        &authblock, sizeof(authblock),
1443
                        NULL);
1444
    if (req_len < 0) {
12✔
1445
        logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__);
×
1446
        return 1;
×
1447
    }
1448

1449
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
12✔
1450

1451
    return transfer(self, req, req_len, "TPM2_NV_WriteLock", FALSE,
12✔
1452
                    NULL, NULL, TPM2_DURATION_SHORT);
1453
}
1454

1455
static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs,
165✔
1456
                                  const unsigned char *data, size_t data_len, gboolean lock_nvram,
1457
                                  const char *certtype)
1458
{
1459
    int ret = swtpm_tpm2_nvdefinespace(self, nvindex, nvindexattrs, data_len);
165✔
1460
    if (ret != 0) {
165✔
1461
        logerr(self->logfile, "Could not create NVRAM area 0x%x for %s.\n", nvindex, certtype);
×
1462
        return 1;
×
1463
    }
1464

1465
    ret = swtpm_tpm2_nv_write(self, nvindex, data, data_len);
165✔
1466
    if (ret != 0) {
165✔
1467
        logerr(self->logfile,
×
1468
               "Could not write %s into NVRAM area 0x%x.\n", certtype, nvindex);
1469
        return 1;
×
1470
    }
1471

1472
    if (lock_nvram) {
165✔
1473
        ret = swtpm_tpm2_nv_writelock(self, nvindex);
12✔
1474
        if (ret != 0) {
12✔
1475
            logerr(self->logfile, "Could not lock EK template NVRAM area 0x%x.\n", nvindex);
×
1476
            return 1;
×
1477
        }
1478
    }
1479

1480
    return 0;
1481
}
1482

1483
static int swtpm_tpm2_write_cert_nvram(struct swtpm *self, uint32_t nvindex,
117✔
1484
                                       uint32_t nvindexattrs,
1485
                                       const unsigned char *data, size_t data_len,
1486
                                       gboolean lock_nvram, const char *keytype,
1487
                                       const char *certtype)
1488
{
1489
    int ret;
117✔
1490

1491
    ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, data, data_len, lock_nvram,
117✔
1492
                                 certtype);
1493
    if (ret == 0)
117✔
1494
        logit(self->logfile,
117✔
1495
              "Successfully created NVRAM area 0x%x for %s%s.\n",
1496
              nvindex, keytype, certtype);
1497

1498
    return ret;
117✔
1499
}
1500

1501
/* Write the platform certificate into an NVRAM area */
1502
static int swtpm_tpm2_write_ek_cert_nvram(struct swtpm *self, gboolean isecc,
78✔
1503
                                           unsigned int rsa_keysize, gboolean lock_nvram,
1504
                                           const unsigned char *data, size_t data_len)
1505
{
1506
    uint32_t nvindex = 0;
78✔
1507
    g_autofree gchar *keytype = NULL;
156✔
1508
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
78✔
1509
            TPMA_NV_AUTHREAD |
1510
            TPMA_NV_OWNERREAD |
1511
            TPMA_NV_PPREAD |
1512
            TPMA_NV_PPWRITE |
1513
            TPMA_NV_NO_DA |
1514
            TPMA_NV_WRITEDEFINE;
1515

1516
    if (!isecc) {
78✔
1517
        if (rsa_keysize == 2048)
39✔
1518
            nvindex = TPM2_NV_INDEX_RSA2048_EKCERT;
1519
        else if (rsa_keysize == 3072)
16✔
1520
            nvindex = TPM2_NV_INDEX_RSA3072_HI_EKCERT;
1521
        else if (rsa_keysize == 4096)
6✔
1522
            nvindex = TPM2_NV_INDEX_RSA4096_HI_EKCERT;
6✔
1523
        keytype = g_strdup_printf("RSA %d ", rsa_keysize);
39✔
1524
    } else {
1525
        nvindex = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT;
39✔
1526
        keytype = g_strdup("ECC ");
39✔
1527
    }
1528

1529
    return swtpm_tpm2_write_cert_nvram(self, nvindex, nvindexattrs, data, data_len,
78✔
1530
                                       lock_nvram, keytype, "EK certificate");
1531
}
1532

1533
static int swtpm_tpm2_write_platform_cert_nvram(struct swtpm *self, gboolean lock_nvram,
39✔
1534
                                                const unsigned char *data, size_t data_len)
1535
{
1536
    uint32_t nvindex = TPM2_NV_INDEX_PLATFORMCERT;
39✔
1537
    uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE |
39✔
1538
            TPMA_NV_AUTHREAD |
1539
            TPMA_NV_OWNERREAD |
1540
            TPMA_NV_PPREAD |
1541
            TPMA_NV_PPWRITE |
1542
            TPMA_NV_NO_DA |
1543
            TPMA_NV_WRITEDEFINE;
1544

1545
    return swtpm_tpm2_write_cert_nvram(self, nvindex, nvindexattrs, data, data_len,
39✔
1546
                                       lock_nvram, "", "platform certificate");
1547
}
1548

1549
static char *swtpm_tpm2_get_active_profile(struct swtpm *self)
115✔
1550
{
1551
    gchar *result = NULL;
115✔
1552

1553
    if (do_cmd_get_info(self, SWTPM_INFO_ACTIVE_PROFILE, &result))
115✔
1554
        return NULL;
1555
    return result;
112✔
1556
}
1557

1558
static const struct swtpm2_ops swtpm_tpm2_ops = {
1559
    .shutdown = swtpm_tpm2_shutdown,
1560
    .create_spk = swtpm_tpm2_create_spk,
1561
    .create_ek = swtpm_tpm2_create_ek,
1562
    .get_all_pcr_banks = swtpm_tpm2_get_all_pcr_banks,
1563
    .set_active_pcr_banks = swtpm_tpm2_set_active_pcr_banks,
1564
    .write_ek_cert_nvram = swtpm_tpm2_write_ek_cert_nvram,
1565
    .write_platform_cert_nvram = swtpm_tpm2_write_platform_cert_nvram,
1566
    .get_active_profile = swtpm_tpm2_get_active_profile,
1567
};
1568

1569
/*
1570
 * TPM 1.2 support
1571
 */
1572
#define TPM_TAG_RQU_COMMAND       0x00c1
1573
#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
1574

1575
#define TPM_ORD_OIAP                     0x0000000A
1576
#define TPM_ORD_TAKE_OWNERSHIP           0x0000000D
1577
#define TPM_ORD_PHYSICAL_ENABLE          0x0000006F
1578
#define TPM_ORD_PHYSICAL_SET_DEACTIVATED 0x00000072
1579
#define TPM_ORD_NV_DEFINE_SPACE          0x000000CC
1580
#define TPM_ORD_NV_WRITE_VALUE           0x000000CD
1581
#define TSC_ORD_PHYSICAL_PRESENCE        0x4000000A
1582

1583
#define TPM_ST_CLEAR 0x0001
1584

1585
#define TPM_PHYSICAL_PRESENCE_CMD_ENABLE  0x0020
1586
#define TPM_PHYSICAL_PRESENCE_PRESENT     0x0008
1587

1588
#define TPM_ALG_RSA 0x00000001
1589

1590
#define TPM_KEY_STORAGE 0x0011
1591

1592
#define TPM_AUTH_ALWAYS 0x01
1593

1594
#define TPM_PID_OWNER  0x0005
1595

1596
#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003
1597
#define TPM_SS_NONE 0x0001
1598

1599
#define TPM_TAG_PCR_INFO_LONG   0x0006
1600
#define TPM_TAG_NV_ATTRIBUTES   0x0017
1601
#define TPM_TAG_NV_DATA_PUBLIC  0x0018
1602
#define TPM_TAG_KEY12           0x0028
1603

1604
#define TPM_LOC_ZERO   0x01
1605
#define TPM_LOC_ALL    0x1f
1606

1607
#define TPM_NV_INDEX_D_BIT        0x10000000
1608
#define TPM_NV_INDEX_EKCERT       0xF000
1609
#define TPM_NV_INDEX_PLATFORMCERT 0xF002
1610

1611
#define TPM_NV_INDEX_LOCK 0xFFFFFFFF
1612

1613
#define TPM_NV_PER_OWNERREAD   0x00020000
1614
#define TPM_NV_PER_OWNERWRITE  0x00000002
1615

1616
#define TPM_ET_OWNER 0x02
1617
#define TPM_ET_NV    0x0b
1618

1619
#define TPM_KH_EK    0x40000006
1620

1621
#define TPM_DURATION_SHORT     2000  /* ms */
1622
#define TPM_DURATION_MEDIUM    7500  /* ms */
1623
#define TPM_DURATION_LONG     15000  /* ms */
1624

1625
static int swtpm_tpm12_tsc_physicalpresence(struct swtpm *self, uint16_t physicalpresence)
52✔
1626
{
1627
    struct tpm12_tsc_physicalpresence {
52✔
1628
        struct tpm_req_header hdr;
1629
        uint16_t pp;
1630
    } req = {
52✔
1631
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TSC_ORD_PHYSICAL_PRESENCE),
52✔
1632
        .pp = htobe16(physicalpresence),
52✔
1633
    };
1634

1635
    /* use medium duration to avoid t/o on busy system */
1636
    return transfer(self, &req, sizeof(req), "TSC_PhysicalPresence", FALSE,
52✔
1637
                    NULL, NULL, TPM_DURATION_MEDIUM);
1638
}
1639

1640
static int swtpm_tpm12_physical_enable(struct swtpm *self)
26✔
1641
{
1642
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_ENABLE);
26✔
1643

1644
    return transfer(self, &req, sizeof(req), "TPM_PhysicalEnable", FALSE,
26✔
1645
                    NULL, NULL, TPM_DURATION_SHORT);
1646
}
1647

1648
static int swtpm_tpm12_physical_set_deactivated(struct swtpm *self, uint8_t state)
26✔
1649
{
1650
    struct tpm12_tsc_physical_set_deactivated {
26✔
1651
        struct tpm_req_header hdr;
1652
        uint8_t state;
1653
    } req = {
26✔
1654
        .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_SET_DEACTIVATED),
26✔
1655
        .state = state,
1656
    };
1657

1658
    return transfer(self, &req, sizeof(req), "TSC_PhysicalSetDeactivated", FALSE,
26✔
1659
                    NULL, NULL, TPM_DURATION_SHORT);
1660
}
1661

1662
/* Initialize the TPM1.2 */
1663
static int swtpm_tpm12_run_swtpm_bios(struct swtpm *self)
26✔
1664
{
1665
    if (swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_CMD_ENABLE) ||
52✔
1666
        swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_PRESENT) ||
52✔
1667
        swtpm_tpm12_physical_enable(self) ||
52✔
1668
        swtpm_tpm12_physical_set_deactivated(self, 0))
26✔
1669
        return 1;
×
1670

1671
    return 0;
1672
}
1673

1674
static int swptm_tpm12_create_endorsement_keypair(struct swtpm *self,
19✔
1675
                                                  gchar **pubek, size_t *pubek_len)
1676
{
1677
    unsigned char req[] = {
19✔
1678
        0x00, 0xc1, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x78, 0x38, 0xf0, 0x30, 0x81, 0x07, 0x2b,
1679
        0x0c, 0xa9, 0x10, 0x98, 0x08, 0xc0, 0x4B, 0x05, 0x11, 0xc9, 0x50, 0x23, 0x52, 0xc4, 0x00, 0x00,
1680
        0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1681
        0x00, 0x02, 0x00, 0x00, 0x00, 0x00
1682
    };
1683
    unsigned char tpmresp[512];
19✔
1684
    size_t tpmresp_len = sizeof(tpmresp);
19✔
1685
    uint32_t length;
19✔
1686
    int ret;
19✔
1687

1688
    ret = transfer(self, &req, sizeof(req), "TPM_CreateEndorsementKeyPair", FALSE,
19✔
1689
                   &tpmresp, &tpmresp_len, TPM_DURATION_LONG);
1690
    if (ret != 0)
19✔
1691
        return 1;
1692

1693
    if (tpmresp_len < 34 + sizeof(length))
19✔
1694
        goto err_too_short;
×
1695
    memcpy(&length, &tpmresp[34], sizeof(length));
19✔
1696
    length = be32toh(length);
19✔
1697
    if (length != 256) {
19✔
1698
        logerr(self->logfile, "Offset to EK Public key is wrong.\n");
×
1699
        return 1;
×
1700
    }
1701

1702
    *pubek_len = 256;
19✔
1703
    if (tpmresp_len < 38 + *pubek_len)
19✔
1704
        goto err_too_short;
×
1705
    *pubek = g_malloc(256);
19✔
1706
    memcpy(*pubek, &tpmresp[38], *pubek_len);
19✔
1707

1708
    return 0;
19✔
1709

1710
err_too_short:
×
1711
    logerr(self->logfile, "Response from TPM_CreateEndorsementKeyPair is too short!\n");
×
1712
    return 1;
×
1713
}
1714

1715
/* Create an OIAP session */
1716
static int swtpm_tpm12_oiap(struct swtpm *self, uint32_t *authhandle, unsigned char nonce_even[SHA_DIGEST_LENGTH])
9✔
1717
{
1718
    struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_OIAP);
9✔
1719
    unsigned char tpmresp[64];
9✔
1720
    size_t tpmresp_len = sizeof(tpmresp);
9✔
1721
    int ret;
9✔
1722

1723
    ret = transfer(self, &req, sizeof(req), "TPM_OIAP", FALSE,
9✔
1724
                   &tpmresp, &tpmresp_len, TPM_DURATION_SHORT);
1725
    if (ret != 0)
9✔
1726
        return ret;
1727

1728
    if (tpmresp_len < 10 + sizeof(*authhandle) || tpmresp_len < 14 + SHA_DIGEST_LENGTH)
9✔
1729
        goto err_too_short;
×
1730
    memcpy(authhandle, &tpmresp[10], sizeof(*authhandle));
9✔
1731
    *authhandle = be32toh(*authhandle);
9✔
1732
    memcpy(nonce_even, &tpmresp[14], SHA_DIGEST_LENGTH);
9✔
1733

1734
    return 0;
9✔
1735

1736
err_too_short:
×
1737
    logerr(self->logfile, "Response from TPM_OIAP is too short!\n");
×
1738
    return 1;
×
1739
}
1740

1741
static int swtpm_tpm12_take_ownership(struct swtpm *self, const unsigned char ownerpass_digest[SHA_DIGEST_LENGTH],
9✔
1742
                                      const unsigned char srkpass_digest[SHA_DIGEST_LENGTH],
1743
                                      const unsigned char *pubek, size_t pubek_len)
1744
{
1745
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_AUTH1_COMMAND, 0, TPM_ORD_TAKE_OWNERSHIP);
9✔
1746
    EVP_PKEY *pkey = NULL;
9✔
1747
    EVP_PKEY_CTX *ctx = NULL;
9✔
1748
    BIGNUM *exp = BN_new();
9✔
1749
    BIGNUM *mod = NULL;
9✔
1750
#if OPENSSL_VERSION_NUMBER < 0x30000000L
1751
    RSA *rsakey = RSA_new();
1752
#endif
1753
    int ret = 1;
9✔
1754
    const EVP_MD *sha1 = EVP_sha1();
9✔
1755
    g_autofree unsigned char *enc_owner_auth = g_malloc(pubek_len);
9✔
1756
    size_t enc_owner_auth_len = pubek_len;
9✔
1757
    g_autofree unsigned char *enc_srk_auth = g_malloc(pubek_len);
18✔
1758
    size_t enc_srk_auth_len = pubek_len;
9✔
1759
    uint32_t auth_handle;
9✔
1760
    unsigned char nonce_even[SHA_DIGEST_LENGTH];
9✔
1761
    unsigned char nonce_odd[SHA_DIGEST_LENGTH] = {1, 2, 3, 4, 5, 6, };
9✔
1762
    g_autofree unsigned char *tpm_rsa_key_parms = NULL;
9✔
1763
    ssize_t tpm_rsa_key_parms_len;
9✔
1764
    g_autofree unsigned char *tpm_key_parms = NULL;
9✔
1765
    ssize_t tpm_key_parms_len;
9✔
1766
    g_autofree unsigned char *tpm_key12 = NULL;
9✔
1767
    ssize_t tpm_key12_len;
9✔
1768
    g_autofree unsigned char *in_auth_setup_params = NULL;
9✔
1769
    ssize_t in_auth_setup_params_len;
9✔
1770
    g_autofree unsigned char *macinput = NULL;
9✔
1771
    ssize_t macinput_len;
9✔
1772
    unsigned char in_param_digest[SHA_DIGEST_LENGTH];
9✔
1773
    unsigned char owner_auth[SHA_DIGEST_LENGTH];
9✔
1774
    unsigned int owner_auth_len = sizeof(owner_auth);
9✔
1775
    uint8_t continue_auth_session = 0;
9✔
1776
    unsigned char req[1024];
9✔
1777
    ssize_t req_len, len;
9✔
1778
    struct tpm_req_header *trh;
9✔
1779

1780
    mod = BN_bin2bn((const unsigned char *)pubek, pubek_len, NULL);
9✔
1781
    if (exp == NULL || mod == NULL ||
18✔
1782
        BN_hex2bn(&exp, "10001") == 0) {
9✔
1783
        logerr(self->logfile, "Could not create public RSA key!\n");
×
1784
        goto error_free_bn;
×
1785
    }
1786

1787
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1788
    ctx = EVP_PKEY_CTX_new_from_name(NULL, "rsa", NULL);
9✔
1789
    if (ctx != NULL) {
9✔
1790
        OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
9✔
1791
        OSSL_PARAM *params;
9✔
1792

1793
        if (bld == NULL ||
18✔
1794
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, exp) != 1 ||
18✔
1795
            OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, mod) != 1 ||
9✔
1796
            (params = OSSL_PARAM_BLD_to_param(bld)) == NULL) {
9✔
1797
            OSSL_PARAM_BLD_free(bld);
×
1798
            goto error_free_bn;
×
1799
        }
1800
        OSSL_PARAM_BLD_free(bld);
9✔
1801

1802
        if (EVP_PKEY_fromdata_init(ctx) != 1 ||
18✔
1803
            EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) != 1) {
9✔
1804
            logerr(self->logfile, "Could not set pkey parameters!\n");
×
1805
            OSSL_PARAM_free(params);
×
1806
            goto error_free_bn;
×
1807
        }
1808
        OSSL_PARAM_free(params);
9✔
1809

1810
        EVP_PKEY_CTX_free(ctx);
9✔
1811
    } else {
1812
        logerr(self->logfile, "Could not create key creation context!\n");
×
1813
        goto error_free_bn;
×
1814
    }
1815
    ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
9✔
1816
    if (ctx == NULL)
9✔
1817
        goto error_free_bn;
×
1818
#else
1819
    pkey = EVP_PKEY_new();
1820
    if (pkey == NULL) {
1821
        logerr(self->logfile, "Could not allocate pkey!\n");
1822
        goto error_free_bn;
1823
    }
1824

1825
# if OPENSSL_VERSION_NUMBER < 0x10100000
1826
    rsakey->n = mod;
1827
    rsakey->e = exp;
1828
# else
1829
    if (RSA_set0_key(rsakey, mod, exp, NULL) != 1) {
1830
        logerr(self->logfile, "Could not create public RSA key!\n");
1831
        goto error_free_bn;
1832
    }
1833
# endif
1834
    if (EVP_PKEY_assign_RSA(pkey, rsakey) != 1) {
1835
        logerr(self->logfile, "Could not create public RSA key!\n");
1836
        goto error_free_pkey_and_rsa;
1837
    }
1838

1839
    ctx = EVP_PKEY_CTX_new(pkey, NULL);
1840
    if (ctx == NULL)
1841
        goto error_free_pkey;
1842
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
1843

1844
    if (EVP_PKEY_encrypt_init(ctx) < 1 ||
18✔
1845
        EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) < 1 ||
18✔
1846
        EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sha1) < 1 ||
18✔
1847
        EVP_PKEY_CTX_set_rsa_oaep_md(ctx, sha1) < 1 ||
18✔
1848
        EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, g_strdup("TCPA"), 4) < 1 ||
18✔
1849
        EVP_PKEY_encrypt(ctx, enc_owner_auth, &enc_owner_auth_len,
9✔
1850
                         ownerpass_digest, SHA_DIGEST_LENGTH) < 1||
9✔
1851
        EVP_PKEY_encrypt(ctx, enc_srk_auth, &enc_srk_auth_len,
9✔
1852
                         srkpass_digest, SHA_DIGEST_LENGTH) < 1) {
1853
        logerr(self->logfile, "Internal error in %s: encryption failed\n", __func__);
×
1854
        goto error;
×
1855
    }
1856
    ret = swtpm_tpm12_oiap(self, &auth_handle, nonce_even);
9✔
1857
    if (ret != 0)
9✔
1858
        goto error;
×
1859

1860
    tpm_rsa_key_parms_len = memconcat(&tpm_rsa_key_parms,
18✔
1861
                                      (unsigned char[]){
9✔
1862
                                          AS4BE(2048), AS4BE(2), AS4BE(0)
1863
                                      }, (size_t)12,
1864
                                      NULL);
1865
    if (tpm_rsa_key_parms_len < 0) {
9✔
1866
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1867
        goto error;
×
1868
    }
1869

1870
    tpm_key_parms_len = memconcat(&tpm_key_parms,
18✔
1871
                                  (unsigned char[]){
9✔
1872
                                      AS4BE(TPM_ALG_RSA),
1873
                                      AS2BE(TPM_ES_RSAESOAEP_SHA1_MGF1),
1874
                                      AS2BE(TPM_SS_NONE),
1875
                                      AS4BE(tpm_rsa_key_parms_len)}, (size_t)12,
9✔
1876
                                  tpm_rsa_key_parms, tpm_rsa_key_parms_len,
1877
                                  NULL);
1878
    if (tpm_key_parms_len < 0) {
9✔
1879
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1880
        goto error;
×
1881
    }
1882

1883
    tpm_key12_len = memconcat(&tpm_key12,
18✔
1884
                              (unsigned char[]){
9✔
1885
                                  AS2BE(TPM_TAG_KEY12), AS2BE(0),
1886
                                  AS2BE(TPM_KEY_STORAGE), AS4BE(0), TPM_AUTH_ALWAYS
1887
                              }, (size_t)11,
1888
                              tpm_key_parms, tpm_key_parms_len,
1889
                              (unsigned char[]){AS4BE(0), AS4BE(0), AS4BE(0)}, (size_t)12,
9✔
1890
                              NULL);
1891
    if (tpm_key12_len < 0) {
9✔
1892
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1893
        goto error;
×
1894
    }
1895

1896
    req_len = concat(req, sizeof(req),
18✔
1897
                     &hdr, sizeof(hdr),
1898
                     (unsigned char[]){AS2BE(TPM_PID_OWNER), AS4BE(enc_owner_auth_len)}, (size_t)6,
9✔
1899
                     enc_owner_auth, enc_owner_auth_len,
1900
                     (unsigned char[]){AS4BE(enc_srk_auth_len)}, (size_t)4,
9✔
1901
                     enc_srk_auth, enc_srk_auth_len,
1902
                     tpm_key12, tpm_key12_len,
1903
                     NULL);
1904
    if (req_len < 0) {
9✔
1905
        logerr(self->logfile, "Internal error in %s: req is too small\n");
×
1906
        goto error;
×
1907
    }
1908
    SHA1(&req[6], req_len - 6, in_param_digest);
9✔
1909

1910
    in_auth_setup_params_len = memconcat(&in_auth_setup_params,
9✔
1911
                                         nonce_even, sizeof(nonce_even),
1912
                                         nonce_odd, sizeof(nonce_odd),
1913
                                         &continue_auth_session, (size_t)1,
1914
                                         NULL);
1915
    if (in_auth_setup_params_len < 0) {
9✔
1916
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1917
        goto error;
×
1918
    }
1919

1920
    macinput_len = memconcat(&macinput,
9✔
1921
                             in_param_digest, sizeof(in_param_digest),
1922
                             in_auth_setup_params, in_auth_setup_params_len,
1923
                             NULL);
1924
    if (macinput_len < 0) {
9✔
1925
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1926
        goto error;
×
1927
    }
1928

1929
    HMAC(sha1, ownerpass_digest, SHA_DIGEST_LENGTH, macinput, macinput_len,
9✔
1930
         owner_auth, &owner_auth_len);
1931

1932
    len = concat(&req[req_len], sizeof(req) - req_len,
18✔
1933
                 (unsigned char[]){AS4BE(auth_handle)}, (size_t)4,
9✔
1934
                 nonce_odd, sizeof(nonce_odd),
1935
                 &continue_auth_session, (size_t)1,
1936
                 owner_auth, owner_auth_len,
1937
                 NULL);
1938
    if (len < 0) {
9✔
1939
        logerr(self->logfile, "Internal error in %s: req is too small\n");
×
1940
        goto error;
×
1941
    }
1942
    req_len += len;
9✔
1943

1944
    trh = (struct tpm_req_header *)req; /* old gcc type-punned pointer */
9✔
1945
    trh->size = htobe32(req_len);
9✔
1946

1947
    ret = transfer(self, req, req_len, "TPM_TakeOwnership", FALSE,
9✔
1948
                   NULL, NULL, TPM_DURATION_LONG);
1949

1950
error:
9✔
1951
    EVP_PKEY_free(pkey);
9✔
1952
    EVP_PKEY_CTX_free(ctx);
9✔
1953
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1954
    BN_free(exp);
9✔
1955
    BN_free(mod);
9✔
1956
#endif
1957
    return ret;
9✔
1958

1959
error_free_bn:
×
1960
    BN_free(exp);
×
1961
    BN_free(mod);
×
1962

1963
#if OPENSSL_VERSION_NUMBER < 0x30000000L
1964
error_free_pkey_and_rsa:
1965
    RSA_free(rsakey);
1966
error_free_pkey:
1967
#else
1968
    EVP_PKEY_CTX_free(ctx);
×
1969
#endif
1970
    EVP_PKEY_free(pkey);
×
1971

1972
    return 1;
×
1973
}
1974

1975
static int swtpm_tpm12_nv_define_space(struct swtpm *self, uint32_t nvindex,
27✔
1976
                                       uint32_t nvindexattrs, size_t size)
1977
{
1978
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_DEFINE_SPACE);
27✔
1979
    g_autofree unsigned char *pcr_info_short = NULL;
54✔
1980
    ssize_t pcr_info_short_len;
27✔
1981
    g_autofree unsigned char *nv_data_public = NULL;
27✔
1982
    ssize_t nv_data_public_len;
27✔
1983
    g_autofree unsigned char *req = NULL;
27✔
1984
    ssize_t req_len;
27✔
1985
    unsigned char zeroes[SHA_DIGEST_LENGTH] = {0, };
27✔
1986

1987
    pcr_info_short_len = memconcat(&pcr_info_short,
54✔
1988
                                   (unsigned char[]){AS2BE(3), 0, 0, 0, TPM_LOC_ALL}, (size_t)6,
27✔
1989
                                   zeroes, sizeof(zeroes),
1990
                                   NULL);
1991
    if (pcr_info_short_len < 0) {
27✔
1992
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
1993
        return 1;
×
1994
    }
1995

1996
    nv_data_public_len = memconcat(&nv_data_public,
54✔
1997
                                   (unsigned char[]){
27✔
1998
                                       AS2BE(TPM_TAG_NV_DATA_PUBLIC), AS4BE(nvindex)
27✔
1999
                                   }, (size_t)6,
2000
                                   pcr_info_short, pcr_info_short_len,
2001
                                   pcr_info_short, pcr_info_short_len,
2002
                                   (unsigned char[]){
27✔
2003
                                       AS2BE(TPM_TAG_NV_ATTRIBUTES), AS4BE(nvindexattrs),
27✔
2004
                                       0, 0, 0, AS4BE(size)
27✔
2005
                                   }, (size_t)13,
2006
                                   NULL);
2007
    if (nv_data_public_len < 0) {
27✔
2008
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
2009
        return 1;
×
2010
    }
2011

2012
    req_len = memconcat(&req,
27✔
2013
                        &hdr, sizeof(hdr),
2014
                        nv_data_public, nv_data_public_len,
2015
                        zeroes, sizeof(zeroes),
2016
                        NULL);
2017
    if (req_len < 0) {
27✔
2018
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
2019
        return 1;
×
2020
    }
2021

2022
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
27✔
2023

2024
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE,
27✔
2025
                    NULL, NULL, TPM_DURATION_SHORT);
2026
}
2027

2028
static int swtpm_tpm12_nv_write_value(struct swtpm *self, uint32_t nvindex,
15✔
2029
                                      const unsigned char *data, size_t data_len)
2030
{
2031
    struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_WRITE_VALUE);
15✔
2032
    g_autofree unsigned char *req = NULL;
30✔
2033
    ssize_t req_len;
15✔
2034

2035
    req_len = memconcat(&req,
30✔
2036
                        &hdr, sizeof(hdr),
2037
                        (unsigned char[]){AS4BE(nvindex), AS4BE(0), AS4BE(data_len)}, (size_t)12,
15✔
2038
                        data, data_len,
2039
                        NULL);
2040
    if (req_len < 0) {
15✔
2041
        logerr(self->logfile, "Internal error in %s: out of memory\n");
×
2042
        return 1;
×
2043
    }
2044

2045
    ((struct tpm_req_header *)req)->size = htobe32(req_len);
15✔
2046

2047
    return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE,
15✔
2048
                    NULL, NULL, TPM_DURATION_SHORT);
2049
}
2050

2051
/* Write the EK Certificate into NVRAM */
2052
static int swtpm_tpm12_write_ek_cert_nvram(struct swtpm *self,
8✔
2053
                                           const unsigned char *data, size_t data_len)
2054
{
2055
    uint32_t nvindex = TPM_NV_INDEX_EKCERT | TPM_NV_INDEX_D_BIT;
8✔
2056
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
8✔
2057
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
2058
    if (ret != 0)
8✔
2059
        return 1;
2060

2061
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
8✔
2062
    if (ret != 0)
8✔
2063
        return 1;
×
2064

2065
    return 0;
2066
}
2067

2068
/* Write the Platform Certificate into NVRAM */
2069
static int swtpm_tpm12_write_platform_cert_nvram(struct swtpm *self,
7✔
2070
                                                 const unsigned char *data, size_t data_len)
2071
{
2072
    uint32_t nvindex = TPM_NV_INDEX_PLATFORMCERT | TPM_NV_INDEX_D_BIT;
7✔
2073
    int ret = swtpm_tpm12_nv_define_space(self, nvindex,
7✔
2074
                                          TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len);
2075
    if (ret != 0)
7✔
2076
        return 1;
2077

2078
    ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len);
7✔
2079
    if (ret != 0)
7✔
2080
        return 1;
×
2081

2082
    return 0;
2083
}
2084

2085
static int swtpm_tpm12_nv_lock(struct swtpm *self)
12✔
2086
{
2087
    return swtpm_tpm12_nv_define_space(self, TPM_NV_INDEX_LOCK, 0, 0);
12✔
2088
}
2089

2090
static const struct swtpm12_ops swtpm_tpm12_ops = {
2091
    .run_swtpm_bios = swtpm_tpm12_run_swtpm_bios,
2092
    .create_endorsement_key_pair = swptm_tpm12_create_endorsement_keypair,
2093
    .take_ownership = swtpm_tpm12_take_ownership,
2094
    .write_ek_cert_nvram = swtpm_tpm12_write_ek_cert_nvram,
2095
    .write_platform_cert_nvram = swtpm_tpm12_write_platform_cert_nvram,
2096
    .nv_lock = swtpm_tpm12_nv_lock,
2097
};
2098

2099
static void swtpm_init(struct swtpm *swtpm,
151✔
2100
                       gchar **swtpm_exec_l, const gchar *state_path,
2101
                       const gchar *keyopts, const gchar *logfile,
2102
                       int *fds_to_pass, size_t n_fds_to_pass,
2103
                       gboolean is_tpm2, const gchar *json_profile,
2104
                       int json_profile_fd,
2105
                       const gchar *profile_remove_disabled_param)
2106
{
2107
    swtpm->cops = &swtpm_cops;
151✔
2108
    swtpm->swtpm_exec_l = swtpm_exec_l;
151✔
2109
    swtpm->state_path = state_path;
151✔
2110
    swtpm->keyopts = keyopts;
151✔
2111
    swtpm->logfile = logfile;
151✔
2112
    swtpm->fds_to_pass = fds_to_pass;
151✔
2113
    swtpm->n_fds_to_pass = n_fds_to_pass;
151✔
2114
    swtpm->is_tpm2 = is_tpm2;
151✔
2115
    swtpm->json_profile = json_profile;
151✔
2116
    swtpm->json_profile_fd = json_profile_fd;
151✔
2117
    swtpm->profile_remove_disabled_param = profile_remove_disabled_param;
151✔
2118

2119
    swtpm->pid = -1;
151✔
2120
    swtpm->ctrl_fds[0] = swtpm->ctrl_fds[1] = -1;
151✔
2121
    swtpm->data_fds[0] = swtpm->data_fds[1] = -1;
151✔
2122
}
2123

2124
struct swtpm12 *swtpm12_new(gchar **swtpm_exec_l, const gchar *state_path,
26✔
2125
                            const gchar *keyopts, const gchar *logfile,
2126
                            int *fds_to_pass, size_t n_fds_to_pass)
2127
{
2128
    struct swtpm12 *swtpm12 = g_malloc0(sizeof(struct swtpm12));
26✔
2129

2130
    swtpm_init(&swtpm12->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
26✔
2131
               fds_to_pass, n_fds_to_pass, FALSE, NULL, 0, NULL);
2132
    swtpm12->ops = &swtpm_tpm12_ops;
26✔
2133

2134
    return swtpm12;
26✔
2135
}
2136

2137
struct swtpm2 *swtpm2_new(gchar **swtpm_exec_l, const gchar *state_path,
125✔
2138
                         const gchar *keyopts, const gchar *logfile,
2139
                         int *fds_to_pass, size_t n_fds_to_pass,
2140
                         const gchar *json_profile, int json_profile_fd,
2141
                         const gchar *profile_remove_disabled_param)
2142
{
2143
    struct swtpm2 *swtpm2 = g_malloc0(sizeof(struct swtpm2));
125✔
2144

2145
    swtpm_init(&swtpm2->swtpm, swtpm_exec_l, state_path, keyopts, logfile,
125✔
2146
               fds_to_pass, n_fds_to_pass, TRUE, json_profile, json_profile_fd,
2147
               profile_remove_disabled_param);
2148
    swtpm2->ops = &swtpm_tpm2_ops;
125✔
2149

2150
    return swtpm2;
125✔
2151
}
2152

2153
void swtpm_free(struct swtpm *swtpm) {
151✔
2154
    if (!swtpm)
151✔
2155
        return;
2156
    g_free(swtpm);
151✔
2157
}
2158

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