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

stefanberger / swtpm / #2950

21 Apr 2026 05:02PM UTC coverage: 73.771% (-0.03%) from 73.799%
#2950

push

travis-ci

web-flow
Merge 6ef52fde2 into ac8cf58b2

44 of 80 new or added lines in 1 file covered. (55.0%)

318 existing lines in 2 files now uncovered.

7892 of 10698 relevant lines covered (73.77%)

10060.42 hits per line

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

78.74
/src/swtpm_setup/swtpm_setup.c
1
/* SPDX-License-Identifier: BSD-3-Clause */
2
/*
3
 * swtpm_setup.c: Tool to simulate TPM 1.2 & TPM 2 manufacturing
4
 *
5
 * Author: Stefan Berger, stefanb@linux.ibm.com
6
 *
7
 * Copyright (c) IBM Corporation, 2021 - 2026
8
 */
9

10
#include "config.h"
11

12
#include <errno.h>
13
#include <getopt.h>
14
#include <grp.h>
15
#include <limits.h>
16
#include <pwd.h>
17
#include <stdbool.h>
18
#include <stdlib.h>
19
#include <stdio.h>
20
#include <string.h>
21
#include <unistd.h>
22
#include <sys/stat.h>
23
#include <fcntl.h>
24
#include <sys/types.h>
25
#include <sys/wait.h>
26

27
#include <glib.h>
28
#include <glib/gstdio.h>
29
#include <glib/gprintf.h>
30

31
#include <glib-object.h>
32
#include <json-glib/json-glib.h>
33

34
#include <libtpms/tpm_nvfilename.h>
35

36
#include "profile.h"
37
#include "swtpm.h"
38
#include "swtpm_conf.h"
39
#include "swtpm_utils.h"
40
#include "swtpm_setup_utils.h"
41

42
#include <openssl/sha.h>
43

44
/* default values for passwords */
45
#define DEFAULT_OWNER_PASSWORD "ooo"
46
#define DEFAULT_SRK_PASSWORD   "sss"
47

48
#define SETUP_CREATE_EK_F           (1 << 0)
49
#define SETUP_TAKEOWN_F             (1 << 1)
50
#define SETUP_EK_CERT_F             (1 << 2)
51
#define SETUP_PLATFORM_CERT_F       (1 << 3)
52
#define SETUP_LOCK_NVRAM_F          (1 << 4)
53
#define SETUP_SRKPASS_ZEROS_F       (1 << 5)
54
#define SETUP_OWNERPASS_ZEROS_F     (1 << 6)
55
#define SETUP_STATE_OVERWRITE_F     (1 << 7)
56
#define SETUP_STATE_NOT_OVERWRITE_F (1 << 8)
57
#define SETUP_TPM2_F                (1 << 9)
58
#define SETUP_ALLOW_SIGNING_F       (1 << 10)
59
#define SETUP_TPM2_ECC_F            (1 << 11)
60
#define SETUP_CREATE_SPK_F          (1 << 12)
61
#define SETUP_DISPLAY_RESULTS_F     (1 << 13)
62
#define SETUP_DECRYPTION_F          (1 << 14)
63
#define SETUP_WRITE_EK_CERT_FILES_F (1 << 15)
64
#define SETUP_RECONFIGURE_F         (1 << 16)
65
#define SETUP_RSA_KEYSIZE_BY_USER_F (1 << 17)
66

67
/* default configuration file */
68
#define SWTPM_SETUP_CONF "swtpm_setup.conf"
69

70
/* Default logging goes to stderr */
71
gchar *gl_LOGFILE = NULL;
72

73
#define DEFAULT_RSA_KEYSIZE 2048
74

75
#define DEFAULT_EK1KEYALGO "rsa2048"
76
#define DEFAULT_EK2KEYALGO "ecc_nist_p384"
77

78
static const struct flag_to_certfile {
79
    unsigned long flag;
80
    const char *filename;
81
    const char *type;
82
} flags_to_certfiles[] = {
83
    {.flag = SETUP_EK_CERT_F      , .filename = "ek.cert",       .type = "ek" },
84
    {.flag = SETUP_PLATFORM_CERT_F, .filename = "platform.cert", .type = "platform" },
85
    {.flag = 0,                     .filename = NULL,            .type = NULL},
86
};
87

88
static const struct {
89
    const char *name;
90
    enum keyalgo keyalgo;
91
    unsigned int keyalgo_param;
92
} keyalgo_choices[] = {
93
    { .name = "rsa2048"      , .keyalgo = KEYALGO_RSA, .keyalgo_param = 2048 },
94
    { .name = "rsa3072"      , .keyalgo = KEYALGO_RSA, .keyalgo_param = 3072 },
95
    { .name = "rsa4096"      , .keyalgo = KEYALGO_RSA, .keyalgo_param = 4096 },
96
    { .name = "ecc_nist_p384", .keyalgo = KEYALGO_ECC, .keyalgo_param = TPM2_ECC_NIST_P384 },
97
    { .name = "secp384r1"    , .keyalgo = KEYALGO_ECC, .keyalgo_param = TPM2_ECC_NIST_P384 },
98
    { .name = "ecc_nist_p256", .keyalgo = KEYALGO_ECC, .keyalgo_param = TPM2_ECC_NIST_P256 },
99
    { .name = "secp256r1"    , .keyalgo = KEYALGO_ECC, .keyalgo_param = TPM2_ECC_NIST_P256 },
100
    { .name = "ecc_nist_p521", .keyalgo = KEYALGO_ECC, .keyalgo_param = TPM2_ECC_NIST_P521 },
101
    { .name = "secp521r1"    , .keyalgo = KEYALGO_ECC, .keyalgo_param = TPM2_ECC_NIST_P521 },
102
};
103

104
/* initialize the path of the config_file */
105
static int init(gchar **config_file)
192✔
106
{
107
    const gchar *configdir = g_get_user_config_dir();
192✔
108

109
    *config_file = g_build_filename(configdir, SWTPM_SETUP_CONF, NULL);
192✔
110
    if (access(*config_file, R_OK) != 0) {
192✔
111
        g_free(*config_file);
192✔
112
        *config_file = g_build_filename(SYSCONFDIR, SWTPM_SETUP_CONF, NULL);
192✔
113
    }
114

115
    return 0;
192✔
116
}
117

118
/* Get the spec and attributes parameters from swtpm */
119
static int tpm_get_specs_and_attributes(struct swtpm *swtpm, gchar ***params)
104✔
120
{
121
    int ret;
104✔
122
    g_autofree gchar *json = NULL;
208✔
123
    JsonParser *jp = NULL;
104✔
124
    GError *error = NULL;
104✔
125
    JsonReader *jr = NULL;
104✔
126
    JsonNode *root;
104✔
127
    static const struct parse_rule {
104✔
128
         const char *node1;
129
         const char *node2;
130
         gboolean is_int;
131
         const char *optname;
132
    } parser_rules[7] = {
133
         {"TPMSpecification", "family", FALSE, "--tpm-spec-family"},
134
         {"TPMSpecification", "level", TRUE, "--tpm-spec-level"},
135
         {"TPMSpecification", "revision", TRUE, "--tpm-spec-revision"},
136
         {"TPMAttributes", "manufacturer", FALSE, "--tpm-manufacturer"},
137
         {"TPMAttributes", "model", FALSE, "--tpm-model"},
138
         {"TPMAttributes", "version", FALSE, "--tpm-version"},
139
         {NULL, NULL, FALSE, NULL},
140
    };
141
    size_t idx;
104✔
142

143
    ret = swtpm->cops->ctrl_get_tpm_specs_and_attrs(swtpm, &json);
104✔
144
    if (ret != 0) {
104✔
UNCOV
145
        logerr(gl_LOGFILE, "Could not get the TPM spec and attribute parameters.\n");
×
UNCOV
146
        return 1;
×
147
    }
148

149
    jp = json_parser_new();
104✔
150

151
    if (!json_parser_load_from_data(jp, json, -1, &error)) {
104✔
UNCOV
152
        logerr(gl_LOGFILE, "JSON parser failed: %s\n", error->message);
×
UNCOV
153
        g_error_free(error);
×
UNCOV
154
        goto error;
×
155
    }
156

157
    *params = NULL;
104✔
158
    root = json_parser_get_root(jp);
104✔
159

160
    for (idx = 0; parser_rules[idx].node1 != NULL; idx++) {
832✔
161
        jr = json_reader_new(root);
624✔
162
        if (json_reader_read_member(jr, parser_rules[idx].node1) &&
1,248✔
163
            json_reader_read_member(jr, parser_rules[idx].node2)) {
624✔
164
            gchar *str;
624✔
165

166
            if (parser_rules[idx].is_int)
624✔
167
                str = g_strdup_printf("%ld", (long)json_reader_get_int_value(jr));
208✔
168
            else
169
                str = g_strdup(json_reader_get_string_value(jr));
416✔
170

171
            *params = concat_varrays(*params,
1,872✔
172
                                    (gchar*[]){
624✔
173
                                        g_strdup(parser_rules[idx].optname),
1,248✔
174
                                        str,
175
                                        NULL
176
                                    }, TRUE);
177
        } else {
UNCOV
178
            logerr(gl_LOGFILE, "Could not find [%s][%s] in '%s'\n",
×
UNCOV
179
                   parser_rules[idx].node1, parser_rules[idx].node2, json);
×
UNCOV
180
            ret = 1;
×
UNCOV
181
            break;
×
182
        }
183
        g_object_unref(jr);
624✔
184
        jr = NULL;
624✔
185
    }
186

UNCOV
187
    if (ret) {
×
UNCOV
188
        g_strfreev(*params);
×
UNCOV
189
        *params = NULL;
×
UNCOV
190
        g_object_unref(jr);
×
191
    }
192
error:
104✔
193
    g_object_unref(jp);
104✔
194

195
    return ret;
104✔
196
}
197

198
/* Call an external tool to create the certificates */
199
static int call_create_certs(unsigned long flags, unsigned int cert_flags,
104✔
200
                             const gchar *configfile, const gchar *certsdir,
201
                             const gchar *ekparam, const gchar *vmid, struct swtpm *swtpm)
202
{
203
    gchar **config_file_lines = NULL; /* must free */
104✔
204
    g_autofree gchar *create_certs_tool = NULL;
208✔
205
    g_autofree gchar *create_certs_tool_config = NULL;
104✔
206
    g_autofree gchar *create_certs_tool_options = NULL;
104✔
207
    g_autofree const gchar **cmd = NULL;
104✔
208
    gchar **params = NULL; /* must free */
104✔
209
    g_autofree gchar *prgname = NULL;
104✔
210
    gboolean success;
104✔
211
    gint exit_status;
104✔
212
    size_t idx, j;
104✔
213
    gchar *s;
104✔
214
    int ret;
104✔
215

216
    ret = tpm_get_specs_and_attributes(swtpm, &params);
104✔
217
    if (ret != 0)
104✔
UNCOV
218
        goto error;
×
219

220
    ret = read_file_lines(configfile, &config_file_lines);
104✔
221
    if (ret != 0)
104✔
UNCOV
222
        goto error;
×
223

224
    create_certs_tool = get_config_value(config_file_lines, "create_certs_tool");
104✔
225
    create_certs_tool_config = get_config_value(config_file_lines, "create_certs_tool_config");
104✔
226
    create_certs_tool_options = get_config_value(config_file_lines, "create_certs_tool_options");
104✔
227

228
    ret = 0;
104✔
229

230
    if (create_certs_tool != NULL) {
104✔
231
        g_autofree gchar *create_certs_tool_path = g_find_program_in_path(create_certs_tool);
208✔
232
        if (create_certs_tool_path == NULL) {
104✔
UNCOV
233
            logerr(gl_LOGFILE, "Could not find %s in PATH.\n", create_certs_tool);
×
UNCOV
234
            ret = 1;
×
UNCOV
235
            goto error;
×
236
        }
237

238
        if (flags & SETUP_TPM2_F) {
104✔
239
            params = concat_varrays(params,
192✔
240
                                (gchar*[]){
96✔
241
                                    g_strdup("--tpm2"),
96✔
242
                                    NULL
243
                                }, TRUE);
244
        }
245
        cmd = concat_arrays((const gchar*[]) {
104✔
246
                                create_certs_tool_path,
247
                                "--type", "_",  /* '_' must be at index '2' ! */
248
                                "--ek", ekparam,
249
                                "--dir", certsdir,
250
                                NULL
251
                            }, NULL, FALSE);
252

253
        if (flags & SETUP_ALLOW_SIGNING_F) {
104✔
254
            cmd = concat_arrays(cmd, (const gchar*[]){"--allow-signing", NULL}, TRUE);
42✔
255
            /* once --allow-signing is passed we need to pass --decryption also */
256
            if (flags & SETUP_DECRYPTION_F)
42✔
257
                cmd = concat_arrays(cmd, (const gchar*[]){"--decryption", NULL}, TRUE);
14✔
258
        }
259
        if (gl_LOGFILE != NULL)
104✔
260
            cmd = concat_arrays(cmd, (const gchar*[]){"--logfile", gl_LOGFILE, NULL}, TRUE);
17✔
261
        if (vmid != NULL)
104✔
262
            cmd = concat_arrays(cmd, (const gchar*[]){"--vmid", vmid, NULL}, TRUE);
75✔
263
        cmd = concat_arrays(cmd, (const char **)params, TRUE);
104✔
264
        if (create_certs_tool_config != NULL)
104✔
265
            cmd = concat_arrays(cmd, (const gchar*[]){"--configfile", create_certs_tool_config, NULL}, TRUE);
17✔
266
        if (create_certs_tool_options != NULL)
104✔
267
            cmd = concat_arrays(cmd, (const gchar*[]){"--optsfile", create_certs_tool_options, NULL}, TRUE);
17✔
268

269
        s = g_strrstr(create_certs_tool, G_DIR_SEPARATOR_S);
104✔
270
        if (s)
104✔
271
            prgname = strdup(&s[1]);
17✔
272
        else
273
            prgname = strdup(create_certs_tool);
87✔
274

275
        for (idx = 0; flags_to_certfiles[idx].filename != NULL; idx++) {
312✔
276
            if (cert_flags & flags_to_certfiles[idx].flag) {
208✔
277
                g_autofree gchar *standard_output = NULL;
160✔
278
                g_autofree gchar *standard_error = NULL;
160✔
279
                GError *error = NULL;
160✔
280
                gchar **lines;
160✔
281

282
                cmd[2] = (gchar *)flags_to_certfiles[idx].type; /* replaces the "_" above */
160✔
283

284
                s = g_strjoinv(" ", (char **)cmd);
160✔
285
                logit(gl_LOGFILE, "  Invoking %s\n", s);
160✔
286
                g_free(s);
160✔
287

288
                success = spawn_sync(NULL, cmd, NULL, 0, NULL, NULL,
160✔
289
                                     &standard_output, &standard_error, &exit_status, &error);
290
                if (!success) {
160✔
UNCOV
291
                    logerr(gl_LOGFILE, "An error occurred running %s: %s\n",
×
UNCOV
292
                           create_certs_tool, error->message);
×
UNCOV
293
                    g_error_free(error);
×
UNCOV
294
                    ret = 1;
×
UNCOV
295
                    break;
×
296
                } else if (exit_status != 0) {
160✔
297
                    logerr(gl_LOGFILE, "%s exit with status %d: %s\n",
×
298
                           prgname, WEXITSTATUS(exit_status), standard_error);
×
299
                    ret = 1;
×
300
                    break;
×
301
                }
302

303
                lines = g_strsplit(standard_output, "\n", -1);
160✔
304
                for (j = 0; lines[j] != NULL; j++) {
320✔
305
                    if (strlen(lines[j]) > 0)
×
UNCOV
306
                        logit(gl_LOGFILE, "%s: %s\n", prgname, lines[j]);
×
307
                }
308
                g_strfreev(lines);
160✔
309

310
                SWTPM_G_FREE(standard_output);
160✔
311
                SWTPM_G_FREE(standard_error);
160✔
312
            }
313
        }
314
    }
315

UNCOV
316
error:
×
317
    g_strfreev(config_file_lines);
104✔
318
    g_strfreev(params);
104✔
319

320
    return ret;
104✔
321
}
322

323
static char *create_certfile_name(const gchar *user_certsdir,
17✔
324
                                  const gchar *key_type,
325
                                  const gchar *key_description)
326
{
327
    g_autofree gchar *filename = g_strdup_printf("%s-%s.crt", key_type, key_description);
17✔
328

329
    return g_strjoin(G_DIR_SEPARATOR_S, user_certsdir, filename, NULL);
17✔
330
}
331

332
/*
333
 * Remove the cert file unless the user wants a copy of it.
334
 */
335
static int certfile_move_or_delete(unsigned long flags, gboolean preserve, const gchar *certfile,
160✔
336
                                   const gchar *user_certsdir, const gchar *key_type,
337
                                   const gchar *key_description)
338
{
339
    g_autofree gchar *content = NULL;
320✔
340
    g_autofree gchar *cf = NULL;
160✔
341
    gsize content_length;
160✔
342
    GError *error = NULL;
160✔
343
    size_t offset = 0;
160✔
344

345
    if (preserve && (flags & SETUP_WRITE_EK_CERT_FILES_F) && user_certsdir != NULL) {
160✔
346
        if (!g_file_get_contents(certfile, &content, &content_length, &error))
17✔
UNCOV
347
            goto error;
×
348

349
        cf = create_certfile_name(user_certsdir, key_type, key_description);
17✔
350
        if (!(flags & SETUP_TPM2_F)) {
17✔
351
            /* A TPM 1.2 certificate has a 7 byte header at the beginning
352
             * that we now remove */
353
            if (content_length >= 8)
1✔
354
                offset = 7;
17✔
355
        }
356
        if (!g_file_set_contents(cf, &content[offset], content_length - offset,
17✔
357
                                 &error))
UNCOV
358
            goto error;
×
359
        if (g_chmod(cf, S_IRUSR | S_IWUSR | S_IRGRP) < 0) {
17✔
UNCOV
360
            logerr(gl_LOGFILE, "Failed to chmod file '%s': %s\n", cf, strerror(errno));
×
UNCOV
361
            goto error_unlink;
×
362
        }
363
    }
364
    unlink(certfile);
160✔
365

366
    return 0;
160✔
367

UNCOV
368
error:
×
UNCOV
369
    logerr(gl_LOGFILE, "%s\n", error->message);
×
UNCOV
370
    g_error_free(error);
×
371

UNCOV
372
error_unlink:
×
373
    unlink(certfile);
×
374

375
    return 1;
×
376
}
377

378
static int read_certificate_file(const gchar *certsdir, const gchar *filename,
160✔
379
                                 gchar **filecontent, gsize *filecontent_len,
380
                                 gchar **certfile)
381
{
382
    *certfile = g_strjoin(G_DIR_SEPARATOR_S, certsdir, filename, NULL);
160✔
383

384
    return read_file(*certfile, filecontent, filecontent_len);
160✔
385
}
386

387
/*
388
 * Read the certificate from the file where swtpm_cert left it.
389
 * Write the file into the TPM's NVRAM and, if the user wants it,
390
 * copy it into a user-provided directory.
391
 */
392
static int tpm2_persist_certificate(unsigned long flags, const gchar *certsdir,
145✔
393
                                    const struct flag_to_certfile *ftc,
394
                                    enum keyalgo keyalgo, unsigned int keyalgo_param,
395
                                    struct swtpm2 *swtpm2, const gchar *user_certsdir,
396
                                    const gchar *key_type, const gchar *key_description)
397
{
398
    g_autofree gchar *filecontent = NULL;
290✔
399
    g_autofree gchar *certfile = NULL;
145✔
400
    gsize filecontent_len;
145✔
401
    int ret;
145✔
402

403
    ret = read_certificate_file(certsdir, ftc->filename,
145✔
404
                                &filecontent, &filecontent_len, &certfile);
405
    if (ret != 0)
145✔
UNCOV
406
        goto error_unlink;
×
407

408
    if (ftc->flag == SETUP_EK_CERT_F) {
145✔
409
        ret = swtpm2->ops->write_ek_cert_nvram(&swtpm2->swtpm,
96✔
410
                                     keyalgo, keyalgo_param,
411
                                     !!(flags & SETUP_LOCK_NVRAM_F),
96✔
412
                                     (const unsigned char*)filecontent, filecontent_len);
413
    } else {
414
        ret = swtpm2->ops->write_platform_cert_nvram(&swtpm2->swtpm,
49✔
415
                                     !!(flags & SETUP_LOCK_NVRAM_F),
49✔
416
                                     (const unsigned char *)filecontent, filecontent_len);
417
    }
418

419
    if (ret != 0)
145✔
UNCOV
420
        goto error_unlink;
×
421

422
    return certfile_move_or_delete(flags, !!(ftc->flag & SETUP_EK_CERT_F),
145✔
423
                                   certfile, user_certsdir,
424
                                   key_type, key_description);
425

UNCOV
426
error_unlink:
×
UNCOV
427
    unlink(certfile);
×
UNCOV
428
    return 1;
×
429
}
430

431
/* Create EK and certificate for a TPM 2 */
432
static int tpm2_create_ek_and_cert(unsigned long flags, const gchar *config_file,
242✔
433
                                   const gchar *certsdir, const gchar *vmid,
434
                                   enum keyalgo keyalgo, unsigned int keyalgo_param,
435
                                   struct swtpm2 *swtpm2, const gchar *user_certsdir)
436
{
437
    const char *key_description = "";
242✔
438
    g_autofree gchar *ekparam = NULL;
484✔
439
    unsigned long cert_flags;
242✔
440
    const gchar *key_type;
242✔
441
    size_t idx;
242✔
442
    int ret;
242✔
443

444
    if (flags & SETUP_CREATE_EK_F) {
242✔
445
        ret = swtpm2->ops->create_ek(&swtpm2->swtpm, keyalgo, keyalgo_param,
220✔
446
                                     !!(flags & SETUP_ALLOW_SIGNING_F),
110✔
447
                                     !!(flags & SETUP_DECRYPTION_F),
110✔
448
                                     !!(flags & SETUP_LOCK_NVRAM_F),
110✔
449
                                     &ekparam, &key_description);
450
        if (ret != 0)
110✔
451
            return 1;
452
    }
453

454
    /* Only look at ek and platform certs here */
455
    cert_flags = flags & (SETUP_EK_CERT_F | SETUP_PLATFORM_CERT_F);
242✔
456
    if (cert_flags) {
242✔
457
        ret = call_create_certs(flags, cert_flags, config_file, certsdir, ekparam,
96✔
458
                                vmid, &swtpm2->swtpm);
459
        if (ret != 0)
96✔
460
            return 1;
461

462
        for (idx = 0; flags_to_certfiles[idx].filename; idx++) {
288✔
463
            if (cert_flags & flags_to_certfiles[idx].flag) {
192✔
464
                key_type = flags_to_certfiles[idx].flag & SETUP_EK_CERT_F ? "ek" : "";
145✔
465

466
                ret = tpm2_persist_certificate(flags, certsdir, &flags_to_certfiles[idx],
145✔
467
                                               keyalgo, keyalgo_param, swtpm2,
468
                                               user_certsdir, key_type, key_description);
469
                if (ret)
145✔
470
                    return 1;
471
            }
472
        }
473
    }
474

475
    return 0;
476
}
477

478
/* Create endorsement keys and certificates for a TPM 2 */
479
static int tpm2_create_eks_and_certs(unsigned long flags, const gchar *config_file,
122✔
480
                                     const gchar *certsdir, const gchar *vmid,
481
                                     enum keyalgo ek1keyalgo, unsigned int ek1keyalgo_param,
482
                                     enum keyalgo ek2keyalgo, unsigned int ek2keyalgo_param,
483
                                     struct swtpm2 *swtpm2, const gchar *user_certsdir)
484
{
485
     int ret;
122✔
486

487
     ret = tpm2_create_ek_and_cert(flags, config_file, certsdir, vmid, ek1keyalgo,
122✔
488
                                   ek1keyalgo_param, swtpm2, user_certsdir);
489
     if (ret != 0)
122✔
490
         return 1;
491

492
     /* two keys the same -- create only one */
493
     if (ek1keyalgo_param == ek2keyalgo_param && ek1keyalgo == ek2keyalgo)
122✔
494
         return 0;
495

496
     /* platform cert only with EK1 */
497
     flags &= ~SETUP_PLATFORM_CERT_F;
120✔
498
     return tpm2_create_ek_and_cert(flags, config_file, certsdir, vmid, ek2keyalgo,
120✔
499
                                    ek2keyalgo_param, swtpm2, user_certsdir);
500
}
501

502
/* Get the default PCR banks from the config file and if nothing can
503
   be found there use the DEFAULT_PCR_BANKS #define.
504
 */
505
static gchar *get_default_pcr_banks(gchar *const *config_file_lines)
154✔
506
{
507
    gchar *pcr_banks;
154✔
508

509
    pcr_banks = get_config_value(config_file_lines, "active_pcr_banks");
154✔
510
    if (pcr_banks)
154✔
511
        g_strstrip(pcr_banks);
27✔
512
    if (pcr_banks == NULL || strlen(pcr_banks) == 0) {
27✔
513
        g_free(pcr_banks);
127✔
514
        pcr_banks = g_strdup(DEFAULT_PCR_BANKS);
127✔
515
    }
516
    return pcr_banks;
154✔
517
}
518

519
/* Get the default RSA keysize from the config file */
520
static gchar *get_default_rsa_keysize(gchar *const *config_file_lines)
105✔
521
{
522
    gchar *rsa_keysize;
105✔
523

524
    rsa_keysize = get_config_value(config_file_lines, "rsa_keysize");
105✔
525
    if (rsa_keysize)
105✔
526
        g_strstrip(rsa_keysize);
6✔
527
    if (rsa_keysize == NULL || strlen(rsa_keysize) == 0) {
6✔
528
        g_free(rsa_keysize);
99✔
529
        rsa_keysize = g_strdup_printf("%d", DEFAULT_RSA_KEYSIZE);
99✔
530
    }
531
    return rsa_keysize;
105✔
532
}
533

534
/* Get the default profile from the config file */
535
static gchar *get_default_profile(gchar *const *config_file_lines)
46✔
536
{
537
    gchar *profile;
46✔
538

539
    profile = get_config_value(config_file_lines, "profile");
46✔
540
    if (profile)
46✔
541
        g_strstrip(profile);
16✔
542
    return profile;
46✔
543
}
544

545
/* If available, open the default profile and return its file descriptor */
546
static int get_default_profile_fd(gchar *const *config_file_lines)
46✔
547
{
548
    g_autofree gchar *profile_file = NULL;
92✔
549
    int fd;
46✔
550

551
    profile_file = get_config_value(config_file_lines, "profile_file");
46✔
552
    if (!profile_file)
46✔
553
        return -1;
554

UNCOV
555
    fd = open(profile_file, O_RDONLY);
×
UNCOV
556
    if (fd < 0) {
×
UNCOV
557
        logerr(gl_LOGFILE, "Could not read default profile '%s': %s",
×
UNCOV
558
               profile_file, strerror(errno));
×
UNCOV
559
        return -2;
×
560
    }
561
    return fd;
562
}
563

564
/* Activate the given list of PCR banks. If pcr_banks is '-' then leave
565
 * the configuration as-is.
566
 */
567
static int tpm2_activate_pcr_banks(struct swtpm2 *swtpm2,
128✔
568
                                   const gchar *pcr_banks)
569
{
570
    g_autofree gchar *active_pcr_banks_join = NULL;
256✔
571
    g_autofree gchar *all_pcr_banks_join = NULL;
128✔
572
    g_auto(GStrv) active_pcr_banks = NULL;
128✔
573
    g_auto(GStrv) all_pcr_banks = NULL;
128✔
574
    g_auto(GStrv) pcr_banks_l = NULL;
128✔
575
    struct swtpm *swtpm = &swtpm2->swtpm;
128✔
576
    int ret = 0;
128✔
577

578
    if (g_str_equal(pcr_banks, "-"))
128✔
579
        return 0;
580

581
    ret = swtpm2->ops->get_all_pcr_banks(swtpm, &all_pcr_banks);
128✔
582
    if (ret != 0)
128✔
583
        return ret;
584

585
    pcr_banks_l = g_strsplit(pcr_banks, ",", -1);
128✔
586
    ret = swtpm2->ops->set_active_pcr_banks(swtpm, pcr_banks_l, all_pcr_banks,
128✔
587
                                            &active_pcr_banks);
588
    if (ret != 0)
128✔
589
        return ret;
590

591
    active_pcr_banks_join = g_strjoinv(",", active_pcr_banks);
127✔
592
    all_pcr_banks_join = g_strjoinv(",", all_pcr_banks);
127✔
593
    logit(gl_LOGFILE, "Successfully activated PCR banks %s among %s.\n",
127✔
594
          active_pcr_banks_join, all_pcr_banks_join);
595

596
    return 0;
127✔
597
}
598

599
static int log_active_profile(struct swtpm2 *swtpm2)
129✔
600
{
601
    g_autofree gchar *profile = NULL;
258✔
602
    char *tmp;
129✔
603

604
    profile = swtpm2->ops->get_active_profile(&swtpm2->swtpm);
129✔
605
    if (!profile) {
129✔
606
        logerr(gl_LOGFILE, "Could not get active profile.\n");
7✔
607
        return 1;
7✔
608
    }
609
    /* Strip out surrounding '{"ActiveProfile":<to display>} */
610
    tmp = strrchr(profile, '}');
122✔
611
    if (!tmp)
122✔
UNCOV
612
        goto malformatted;
×
613
    *tmp = 0;
122✔
614

615
    tmp = strchr(profile, ':');
122✔
616
    if (!tmp)
122✔
617
        goto malformatted;
×
618

619
    logit(gl_LOGFILE, "Active profile: %s\n", tmp + 1);
122✔
620
    return 0;
122✔
621

622
malformatted:
×
UNCOV
623
    logerr(gl_LOGFILE, "Malformatted active profile");
×
UNCOV
624
    return 1;
×
625
}
626

627
/* Simulate manufacturing a TPM 2: create keys and certificates */
628
static int init_tpm2(unsigned long flags, gchar **swtpm_prg_l, const gchar *config_file,
135✔
629
                     const gchar *tpm2_state_path, const gchar *vmid, const gchar *pcr_banks,
630
                     const gchar *swtpm_keyopt, int *fds_to_pass, size_t n_fds_to_pass,
631
                     enum keyalgo ek1keyalgo, unsigned int ek1keyalgo_param,
632
                     enum keyalgo ek2keyalgo, unsigned int ek2keyalgo_param,
633
                     const gchar *certsdir, const gchar *user_certsdir,
634
                     const gchar *json_profile,
635
                     int json_profile_fd, const gchar *profile_remove_disabled_param)
636
{
637
    unsigned int keyalgo_param;
135✔
638
    struct swtpm2 *swtpm2;
135✔
639
    enum keyalgo keyalgo;
135✔
640
    struct swtpm *swtpm;
135✔
641
    int ret;
135✔
642

643
    swtpm2 = swtpm2_new(swtpm_prg_l, tpm2_state_path, swtpm_keyopt, gl_LOGFILE,
135✔
644
                        fds_to_pass, n_fds_to_pass, json_profile, json_profile_fd,
645
                        profile_remove_disabled_param);
646
    if (swtpm2 == NULL)
135✔
647
        return 1;
648
    swtpm = &swtpm2->swtpm;
135✔
649

650
    ret = swtpm->cops->start(swtpm);
135✔
651
    if (ret != 0) {
135✔
UNCOV
652
        logerr(gl_LOGFILE, "Could not start the TPM 2.\n");
×
UNCOV
653
        goto error;
×
654
    }
655

656
    if (!(flags & SETUP_RECONFIGURE_F)) {
135✔
657
        ret = log_active_profile(swtpm2);
129✔
658
        if (ret)
129✔
659
            goto error;
7✔
660

661
        if ((flags & SETUP_CREATE_SPK_F)) {
122✔
662
            if ((flags & SETUP_TPM2_ECC_F)) {
11✔
663
                keyalgo = KEYALGO_ECC;
664
                keyalgo_param = TPM2_ECC_NIST_P384;
665
            } else {
666
                keyalgo = KEYALGO_RSA;
9✔
667
                keyalgo_param = 3072;
9✔
668
            }
669
            ret = swtpm2->ops->create_spk(swtpm, keyalgo, keyalgo_param);
11✔
670
            if (ret != 0)
11✔
UNCOV
671
                goto destroy;
×
672
        }
673

674
        ret = tpm2_create_eks_and_certs(flags, config_file, certsdir, vmid,
122✔
675
                                        ek1keyalgo, ek1keyalgo_param,
676
                                        ek2keyalgo, ek2keyalgo_param,
677
                                        swtpm2, user_certsdir);
678
        if (ret != 0)
122✔
UNCOV
679
            goto destroy;
×
680
    }
681

682
    ret = tpm2_activate_pcr_banks(swtpm2, pcr_banks);
128✔
683
    if (ret != 0)
128✔
684
        goto destroy;
1✔
685

686
    ret = swtpm2->ops->shutdown(swtpm);
127✔
687

688
destroy:
128✔
689
    swtpm->cops->destroy(swtpm);
128✔
690

691
error:
135✔
692
    swtpm_free(swtpm);
135✔
693

694
    return ret;
135✔
695
}
696

697
/* Create the owner password digest */
698
static void tpm12_get_ownerpass_digest(unsigned long flags, const gchar *ownerpass,
9✔
699
                                       unsigned char ownerpass_digest[SHA_DIGEST_LENGTH])
700
{
701
    const gchar zeros[SHA_DIGEST_LENGTH]= {0, };
9✔
702
    size_t len;
9✔
703

704
    if (ownerpass == NULL) {
9✔
705
        if (flags & SETUP_OWNERPASS_ZEROS_F) {
2✔
706
            ownerpass = zeros;
707
            len = sizeof(zeros);
708
        } else {
UNCOV
709
            ownerpass = DEFAULT_OWNER_PASSWORD;
×
UNCOV
710
            len = strlen(ownerpass);
×
711
        }
712
    } else {
713
        len = strlen(ownerpass);
7✔
714
    }
715
    SHA1((const unsigned char *)ownerpass, len, ownerpass_digest);
9✔
716
}
9✔
717

718
/* Create the SRK password digest */
719
static void tpm12_get_srkpass_digest(unsigned long flags, const gchar *srkpass,
9✔
720
                                     unsigned char srkpass_digest[SHA_DIGEST_LENGTH])
721
{
722
    const gchar zeros[SHA_DIGEST_LENGTH]= {0, };
9✔
723
    size_t len;
9✔
724

725
    if (srkpass == NULL) {
9✔
726
        if (flags & SETUP_SRKPASS_ZEROS_F) {
2✔
727
            srkpass = zeros;
728
            len = sizeof(zeros);
729
        } else {
UNCOV
730
            srkpass = DEFAULT_SRK_PASSWORD;
×
UNCOV
731
            len = strlen(srkpass);
×
732
        }
733
    } else {
734
        len = strlen(srkpass);
7✔
735
    }
736
    SHA1((const unsigned char *)srkpass, len, srkpass_digest);
9✔
737
}
9✔
738

739
/* Take ownership of a TPM 1.2 */
740
static int tpm12_take_ownership(unsigned long flags, const gchar *ownerpass,
9✔
741
                                const gchar *srkpass, gchar *pubek, size_t pubek_len,
742
                                struct swtpm12 *swtpm12)
743
{
744
    unsigned char ownerpass_digest[SHA_DIGEST_LENGTH];
9✔
745
    unsigned char srkpass_digest[SHA_DIGEST_LENGTH];
9✔
746

747
    tpm12_get_ownerpass_digest(flags, ownerpass, ownerpass_digest);
9✔
748
    tpm12_get_srkpass_digest(flags, srkpass, srkpass_digest);
9✔
749

750
    return swtpm12->ops->take_ownership(&swtpm12->swtpm, ownerpass_digest, srkpass_digest,
9✔
751
                                        (const unsigned char *)pubek, pubek_len);
752
}
753

754
/* Create the certificates for a TPM 1.2 */
755
static int tpm12_create_certs(unsigned long flags, const gchar *config_file,
8✔
756
                              const gchar *certsdir, const gchar *ekparam,
757
                              const gchar *vmid, struct swtpm12 *swtpm12,
758
                              const gchar *user_certsdir)
759
{
760
    g_autofree gchar *filecontent = NULL;
16✔
761
    g_autofree gchar *certfile = NULL;
8✔
762
    unsigned int cert_flags;
8✔
763
    const gchar *key_type;
8✔
764
    gsize filecontent_len;
8✔
765
    size_t idx;
8✔
766
    int ret;
8✔
767

768
    /* TPM 1.2 only has ek and platform certs */
769
    cert_flags = flags & (SETUP_EK_CERT_F | SETUP_PLATFORM_CERT_F);
8✔
770

771
    ret = call_create_certs(flags, cert_flags, config_file, certsdir, ekparam,
8✔
772
                            vmid, &swtpm12->swtpm);
773
    if (ret != 0)
8✔
774
        return 1;
775

776
    for (idx = 0; flags_to_certfiles[idx].filename; idx++) {
24✔
777
        if (cert_flags & flags_to_certfiles[idx].flag) {
16✔
778
            SWTPM_G_FREE(filecontent);
15✔
779
            SWTPM_G_FREE(certfile);
15✔
780

781
            ret = read_certificate_file(certsdir, flags_to_certfiles[idx].filename,
15✔
782
                                        &filecontent, &filecontent_len, &certfile);
783
            if (ret != 0)
15✔
784
                return 1;
785

786
            if (flags_to_certfiles[idx].flag == SETUP_EK_CERT_F) {
15✔
787
                ret = swtpm12->ops->write_ek_cert_nvram(&swtpm12->swtpm,
8✔
788
                                                (const unsigned char*)filecontent, filecontent_len);
789
                if (ret == 0)
8✔
790
                    logit(gl_LOGFILE, "Successfully created NVRAM area for EK certificate.\n");
8✔
791
            } else {
792
                ret = swtpm12->ops->write_platform_cert_nvram(&swtpm12->swtpm,
7✔
793
                                                  (const unsigned char*)filecontent, filecontent_len);
794
                if (ret == 0)
7✔
795
                    logit(gl_LOGFILE, "Successfully created NVRAM area for Platform certificate.\n");
7✔
796
            }
797

798
            if (ret != 0) {
15✔
UNCOV
799
                unlink(certfile);
×
UNCOV
800
                return 1;
×
801
            }
802

803
            key_type = flags_to_certfiles[idx].flag & SETUP_EK_CERT_F ? "ek" : "";
15✔
804

805
            if (certfile_move_or_delete(flags, !!(flags_to_certfiles[idx].flag & SETUP_EK_CERT_F),
15✔
806
                                        certfile, user_certsdir, key_type, "rsa2048") != 0)
807
                return 1;
808
        }
809
    }
810

811
    return 0;
812
}
813

814
/* Simulate manufacturing a TPM 1.2: create keys and certificate and possibly take ownership */
815
static int init_tpm(unsigned long flags, gchar **swtpm_prg_l, const gchar *config_file,
26✔
816
                    const gchar *tpm_state_path, const gchar *ownerpass, const gchar *srkpass,
817
                    const gchar *vmid, const gchar *swtpm_keyopt,
818
                    int *fds_to_pass, size_t n_fds_to_pass, const gchar *certsdir,
819
                    const gchar *user_certsdir)
820
{
821
    struct swtpm12 *swtpm12;
26✔
822
    struct swtpm *swtpm;
26✔
823
    g_autofree gchar *pubek = NULL;
52✔
824
    size_t pubek_len = 0;
26✔
825
    int ret = 1;
26✔
826

827
    swtpm12 = swtpm12_new(swtpm_prg_l, tpm_state_path, swtpm_keyopt, gl_LOGFILE,
26✔
828
                          fds_to_pass, n_fds_to_pass);
829
    if (swtpm12 == NULL)
26✔
830
        return 1;
831
    swtpm = &swtpm12->swtpm;
26✔
832

833
    ret = swtpm->cops->start(swtpm);
26✔
834
    if (ret != 0) {
26✔
UNCOV
835
        logerr(gl_LOGFILE, "Could not start the TPM 1.2.\n");
×
UNCOV
836
        goto error;
×
837
    }
838

839
    ret = swtpm12->ops->run_swtpm_bios(swtpm);
26✔
840
    if (ret != 0)
26✔
841
         goto destroy;
×
842

843
    if ((flags & SETUP_CREATE_EK_F)) {
26✔
844
        ret = swtpm12->ops->create_endorsement_key_pair(swtpm, &pubek, &pubek_len);
19✔
845
        if (ret != 0)
19✔
846
            goto destroy;
×
847

848
        logit(gl_LOGFILE, "Successfully created EK.\n");
19✔
849

850
        /* can only take owernship if created an EK */
851
        if ((flags & SETUP_TAKEOWN_F)) {
19✔
852
            ret = tpm12_take_ownership(flags, ownerpass, srkpass, pubek, pubek_len, swtpm12);
9✔
853
            if (ret != 0)
9✔
UNCOV
854
                goto destroy;
×
855

856
            logit(gl_LOGFILE, "Successfully took ownership of the TPM.\n");
9✔
857
        }
858

859
        /* can only create EK cert if created an EK */
860
        if ((flags & SETUP_EK_CERT_F)) {
19✔
861
            g_autofree gchar *ekparam = print_as_hex((unsigned char *)pubek, pubek_len);
16✔
862

863
            ret = tpm12_create_certs(flags, config_file, certsdir, ekparam, vmid, swtpm12,
8✔
864
                                     user_certsdir);
865
            if (ret != 0)
8✔
UNCOV
866
                goto destroy;
×
867
        }
868
    }
869

870
    if ((flags & SETUP_LOCK_NVRAM_F)) {
26✔
871
        ret = swtpm12->ops->nv_lock(swtpm);
12✔
872
        if (ret == 0)
12✔
873
            logit(gl_LOGFILE, "Successfully locked NVRAM access.\n");
12✔
874
    }
875

876
destroy:
14✔
877
    swtpm->cops->destroy(swtpm);
26✔
878

879
error:
26✔
880
    swtpm_free(swtpm);
26✔
881

882
    return ret;
26✔
883
}
884

885
/* Check whether we are allowed to overwrite existing state.
886
 * This function returns 2 if the state exists but flag is set to not to overwrite it,
887
 * 0 in case we can overwrite it, 1 if the state exists.
888
 */
889
static int check_state_overwrite(const gchar **swtpm_prg_l, unsigned int flags,
161✔
890
                                 const char *tpm_state_path)
891
{
892
    gboolean success;
161✔
893
    g_autofree gchar *standard_output = NULL;
322✔
894
    int exit_status = 0;
161✔
895
    g_autoptr(GError) error = NULL;
161✔
896
    g_autofree const gchar **argv = NULL;
161✔
897
    g_autofree gchar *statearg = g_strdup_printf("backend-uri=%s", tpm_state_path);
322✔
898
    g_autofree gchar *logop = NULL;
161✔
899
    g_autofree const gchar **my_argv = NULL;
161✔
900

901
    my_argv = concat_arrays((const gchar*[]) {
161✔
902
                                "--print-states",
903
                                "--tpmstate",
904
                                statearg,
905
                                NULL
906
                            }, NULL, FALSE);
907

908
    if (flags & SETUP_TPM2_F)
161✔
909
        my_argv = concat_arrays(my_argv, (const gchar*[]) { "--tpm2", NULL }, TRUE);
132✔
910

911
    if (gl_LOGFILE != NULL) {
161✔
912
        logop = g_strdup_printf("file=%s", gl_LOGFILE);
90✔
913
        my_argv = concat_arrays(my_argv, (const gchar*[]){"--log", logop, NULL}, TRUE);
90✔
914
    }
915

916
    argv = concat_arrays(swtpm_prg_l, my_argv, FALSE);
161✔
917

918
    success = spawn_sync(NULL, argv, NULL, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL,
161✔
919
                         &standard_output, NULL, &exit_status, &error);
920
    if (!success) {
161✔
UNCOV
921
        logerr(gl_LOGFILE, "Could not start swtpm '%s': %s\n", swtpm_prg_l[0], error->message);
×
UNCOV
922
        return 1;
×
923
    }
924

925
    if (exit_status != 0) {
161✔
926
        logerr(gl_LOGFILE, "%s exit with status %d: %s\n",
×
927
               swtpm_prg_l[0], exit_status, standard_output);
UNCOV
928
        return 1;
×
929
    }
930

931
    if (g_strstr_len(standard_output, -1, TPM_PERMANENT_ALL_NAME) != NULL) {
161✔
932
        /* State file exists */
933
        if (flags & SETUP_STATE_NOT_OVERWRITE_F) {
77✔
934
            logit(gl_LOGFILE, "Not overwriting existing state file.\n");
2✔
935
            return 2;
2✔
936
        }
937
        if (flags & SETUP_STATE_OVERWRITE_F)
75✔
938
            return 0;
939
        logerr(gl_LOGFILE, "Found existing TPM state '%s'.\n", TPM_PERMANENT_ALL_NAME);
3✔
940
        return 1;
3✔
941
    }
942

943
    return 0;
944
}
945

946
static void versioninfo(void)
2✔
947
{
948
    printf("TPM emulator setup tool version %d.%d.%d\n",
2✔
949
           SWTPM_VER_MAJOR, SWTPM_VER_MINOR, SWTPM_VER_MICRO);
950
}
2✔
951

952
static void usage(const char *prgname, const char *default_config_file)
1✔
953
{
954
    versioninfo();
1✔
955
    printf(
1✔
956
        "Usage: %s [options]\n"
957
        "\n"
958
        "The following options are supported:\n"
959
        "\n"
960
        "--runas <user>   : Run this program under the given user's account.\n"
961
        "\n"
962
        "--tpm-state <dir>: Path where the TPM's state will be written to;\n"
963
        "                   this is a mandatory argument. Prefix with dir:// to\n"
964
        "                   use directory backend, or file:// to use linear file.\n"
965
        "\n"
966
        "--tpmstate <dir> : This is an alias for --tpm-state <dir>.\n"
967
        "\n"
968
        "--tpm '<path-to-executable> socket'\n"
969
        "                 : Path to the TPM executable; this is an optional argument and\n"
970
        "                   by default 'swtpm' in the PATH is used.\n"
971
        "\n"
972
        "--swtpm_ioctl <executable>\n"
973
        "                 : Path to the swtpm_ioctl executable; this is deprecated\n"
974
        "                   argument.\n"
975
        "\n"
976
        "--tpm2           : Setup a TPM 2; by default a TPM 1.2 is setup.\n"
977
        "\n"
978
        "--createek       : Create the EK; for a TPM 2 an RSA and ECC EK will be\n"
979
        "                   created\n"
980
        "\n"
981
        "--allow-signing  : Create an EK that can be used for signing;\n"
982
        "                   this option requires --tpm2.\n"
983
        "                   Note: Careful, this option will create a non-standard EK!\n"
984
        "\n"
985
        "--decryption     : Create an EK that can be used for key encipherment;\n"
986
        "                   this is the default unless --allow-signing is given;\n"
987
        "                   this option requires --tpm2.\n"
988
        "\n"
989
        "--ecc            : This option allows to create a TPM 2's ECC key as storage\n"
990
        "                   primary key; a TPM 2 always gets an RSA and an ECC EK key.\n"
991
        "\n"
992
        "--ek1keyalgo     : Choice of the 1st EK's key algorithm; default is %s\n"
993
        "                   choices: rsa2048, rsa3072, rsa4096, ecc_nist_p384\n"
994
        "\n"
995
        "--ek2keyalgo     : Choice of the 2nd EK's key algorithm; default is %s\n"
996
        "                   choices: same as for --ek1keyalgo\n"
997
        "\n"
998
        "--take-ownership : Take ownership; this option implies --createek\n"
999
        "  --ownerpass  <password>\n"
1000
        "                 : Provide custom owner password; default is %s\n"
1001
        "  --owner-well-known:\n"
1002
        "                 : Use an owner password of 20 zero bytes\n"
1003
        "  --srkpass <password>\n"
1004
        "                 : Provide custom SRK password; default is %s\n"
1005
        "  --srk-well-known:\n"
1006
        "                 : Use an SRK password of 20 zero bytes\n"
1007
        "--create-ek-cert : Create an EK certificate; this implies --createek\n"
1008
        "\n"
1009
        "--create-platform-cert\n"
1010
        "                 : Create a platform certificate; this implies --create-ek-cert\n"
1011
        "\n"
1012
        "--create-spk     : Create storage primary key; this requires --tpm2; deprecated\n"
1013
        "\n"
1014
        "--lock-nvram     : Lock NVRAM access\n"
1015
        "\n"
1016
        "--display        : At the end display as much info as possible about the\n"
1017
        "                   configuration of the TPM\n"
1018
        "\n"
1019
        "--config <config file>\n"
1020
        "                 : Path to configuration file; default is %s\n"
1021
        "\n"
1022
        "--logfile <logfile>\n"
1023
        "                 : Path to log file; default is logging to stderr\n"
1024
        "\n"
1025
        "--keyfile <keyfile>\n"
1026
        "                 : Path to a key file containing the encryption key for the\n"
1027
        "                   TPM to encrypt its persistent state with. The content\n"
1028
        "                   must be a 32 hex digit number representing a 128bit AES key.\n"
1029
        "                   This parameter will be passed to the TPM using\n"
1030
        "                   '--key file=<file>'.\n"
1031
        "\n"
1032
        "--keyfile-fd <fd>: Like --keyfile but a file descriptor is given to read the\n"
1033
        "                   encryption key from.\n"
1034
        "\n"
1035
        "--pwdfile <pwdfile>\n"
1036
        "                 : Path to a file containing a passphrase from which the\n"
1037
        "                   TPM will derive the 128bit AES key. The passphrase can be\n"
1038
        "                   32 bytes long.\n"
1039
        "                   This parameter will be passed to the TPM using\n"
1040
        "                   '--key pwdfile=<file>'.\n"
1041
        "\n"
1042
        "--pwdfile-fd <fd>: Like --pwdfile but a file descriptor is given to to read\n"
1043
        "                   the passphrase from.\n"
1044
        "\n"
1045
        "--cipher <cipher>: The cipher to use; either aes-128-cbc or aes-256-cbc;\n"
1046
        "                   the default is aes-128-cbc; the same cipher must be\n"
1047
        "                   used on the swtpm command line\n"
1048
        "\n"
1049
        "--overwrite      : Overwrite existing TPM state by re-initializing it; if this\n"
1050
        "                   option is not given, this program will return an error if\n"
1051
        "                   existing state is detected\n"
1052
        "\n"
1053
        "--not-overwrite  : Do not overwrite existing TPM state but silently end\n"
1054
        "\n"
1055
        "--vmid <vm id>   : Unique (VM) identifier to use as common name in certificate\n"
1056
        "\n"
1057
        "--pcr-banks <banks>\n"
1058
        "                 : Set of PCR banks to activate. Provide a comma separated list\n"
1059
        "                   like 'sha1,sha256'. '-' to skip and leave all banks active.\n"
1060
        "                   Default: %s\n"
1061
        "\n"
1062
        "--rsa-keysize <keysize>\n"
1063
        "                 : The RSA key size of the 1st EK key; 3072 and 4096 bits may\n"
1064
        "                   be supported if libtpms supports it. This option is ignored\n"
1065
        "                   if --ek1keyalgo is used.\n"
1066
        "                   Default: %u\n"
1067
        "\n"
1068
        "--write-ek-cert-files <directory>\n"
1069
        "                 : Write EK cert files into the given directory\n"
1070
        "\n"
1071
        "--tcsd-system-ps-file <file>\n"
1072
        "                 : This option is deprecated and has no effect.\n"
1073
        "\n"
1074
        "--print-capabilities\n"
1075
        "                 : Print JSON formatted capabilities added after v0.1 and exit.\n"
1076
        "\n"
1077
        "--create-config-files [[overwrite][,root]]\n"
1078
        "                 : Create swtpm_setup and swtpm-localca config files for a\n"
1079
        "                   user account.\n"
1080
        "                   overwrite: overwrite any existing files\n"
1081
        "                   root: allow to create files under root's home directory\n"
1082
        "                   skip-if-exist: if any file exists exit without error\n"
1083
        "\n"
1084
        "--reconfigure    : Reconfigure an existing swtpm by reusing existing state.\n"
1085
        "                   The active PCR banks can be changed but no new keys will\n"
1086
        "                   be created.\n"
1087
        "\n"
1088
        "--profile <json-profile>\n"
1089
        "                 : Configure swtpm with the given profile.\n"
1090
        "\n"
1091
        "--profile-name <profile name | built-in profile name>\n"
1092
        "                 : Search for a profile with the <name>.json in distro and\n"
1093
        "                   local directories; if not found try it as a built-in.\n"
1094
        "\n"
1095
        "--profile-file <file>\n"
1096
        "                 : Configure swtpm with a profile read from the given file.\n"
1097
        "\n"
1098
        "--profile-file-fd <fd>\n"
1099
        "                 : Configure swtpm with a profile read from a file descriptor.\n"
1100
        "\n"
1101
        "--profile-remove-disabled check|fips-host\n"
1102
        "                 : Instruct swtpm to remove algorithms that may be disabled by\n"
1103
        "                   FIPS mode on the host from 'custom' profile.\n"
1104
        "                   check: algorithms are tested.\n"
1105
        "                   fips-host: no testing.\n"
1106
        "\n"
1107
        "--print-profiles : Display all local and distro-provided profile as well as\n"
1108
        "                   the ones built into libtpms and exit.\n"
1109
        "\n"
1110
        "--version        : Display version and exit\n"
1111
        "\n"
1112
        "--help,-h        : Display this help screen\n\n",
1113
            prgname,
1114
            DEFAULT_EK1KEYALGO,
1115
            DEFAULT_EK2KEYALGO,
1116
            DEFAULT_OWNER_PASSWORD,
1117
            DEFAULT_SRK_PASSWORD,
1118
            default_config_file,
1119
            DEFAULT_PCR_BANKS,
1120
            DEFAULT_RSA_KEYSIZE
1121
        );
1122
}
1✔
1123

1124
static int get_swtpm_capabilities(const gchar **swtpm_prg_l, gboolean is_tpm2,
427✔
1125
                                  gchar **standard_output)
1126
{
1127
    const gchar *my_argv[] = { "--print-capabilities", is_tpm2 ? "--tpm2" : NULL, NULL };
427✔
1128
    g_autofree gchar *standard_error = NULL;
854✔
1129
    g_autofree gchar *logop = NULL;
427✔
1130
    g_autoptr(GError) error = NULL;
427✔
1131
    g_autofree const gchar **argv = NULL;
427✔
1132
    int exit_status = 0;
427✔
1133
    gboolean success;
427✔
1134
    int ret = 1;
427✔
1135

1136
    argv = concat_arrays(swtpm_prg_l, my_argv, FALSE);
427✔
1137

1138
    if (gl_LOGFILE != NULL) {
427✔
1139
        logop = g_strdup_printf("file=%s", gl_LOGFILE);
257✔
1140
        argv = concat_arrays(argv, (const gchar*[]){"--log", logop, NULL}, TRUE);
257✔
1141
    }
1142

1143
    success = spawn_sync(NULL, argv, NULL, 0, NULL, NULL,
427✔
1144
                         standard_output, &standard_error, &exit_status, &error);
1145
    if (!success) {
427✔
UNCOV
1146
        logerr(gl_LOGFILE, "Could not start swtpm '%s': %s\n", swtpm_prg_l[0], error->message);
×
UNCOV
1147
        goto error;
×
1148
    }
1149
    if (exit_status != 0) {
427✔
1150
        /* possible: failure to access log file */
1151
        logerr(gl_LOGFILE, "Failed to run swtpm '%s': %s\n", swtpm_prg_l[0], standard_error);
×
1152
        goto error;
×
1153
    }
1154
    ret = 0;
1155

1156
error:
427✔
1157
    return ret;
427✔
1158
}
1159

1160
static int get_supported_tpm_versions(const gchar **swtpm_prg_l, gboolean *swtpm_has_tpm12,
179✔
1161
                                      gboolean *swtpm_has_tpm2)
1162
{
1163
    g_autofree gchar *standard_output = NULL;
358✔
1164
    int ret;
179✔
1165

1166
    ret = get_swtpm_capabilities(swtpm_prg_l, FALSE, &standard_output);
179✔
1167
    if (ret)
179✔
1168
        return ret;
1169

1170
    *swtpm_has_tpm12 = g_strstr_len(standard_output, -1, "\"tpm-1.2\"") != NULL;
179✔
1171
    *swtpm_has_tpm2 = g_strstr_len(standard_output, -1, "\"tpm-2.0\"") != NULL;
179✔
1172

1173
    return 0;
179✔
1174
}
1175

1176
/* Get the support RSA key sizes.
1177
 *  This function returns an array of ints like the following
1178
 *  - [ 1024, 2048, 3072, 4096 ]
1179
 *  - [] (empty array, indicating only 2048 bit RSA keys are supported)
1180
 */
1181
static int get_rsa_keysizes(unsigned long flags, const gchar **swtpm_prg_l,
144✔
1182
                            unsigned int **keysizes, size_t *n_keysizes)
1183
{
1184
    g_autofree gchar *standard_output = NULL;
288✔
1185
    const gchar *needle = "\"rsa-keysize-";
144✔
1186
    unsigned int keysize;
144✔
1187
    int ret = 1;
144✔
1188
    char *p;
144✔
1189
    int n;
144✔
1190

1191
    *n_keysizes = 0;
144✔
1192

1193
    if (flags & SETUP_TPM2_F) {
144✔
1194
        ret = get_swtpm_capabilities(swtpm_prg_l, TRUE, &standard_output);
144✔
1195
        if (ret)
144✔
UNCOV
1196
            goto error;
×
1197

1198
        p = standard_output;
144✔
1199
        /* A crude way of parsing the json output just looking for "rsa-keysize-%u" */
1200
        while ((p = g_strstr_len(p, -1, needle)) != NULL) {
720✔
1201
            p += strlen(needle);
576✔
1202
            n = sscanf(p, "%u\"", &keysize);
576✔
1203
            if (n == 1) {
576✔
1204
                *keysizes = g_realloc(*keysizes, (*n_keysizes + 1) * sizeof(unsigned int));
576✔
1205
                (*keysizes)[*n_keysizes] = keysize;
576✔
1206
                (*n_keysizes)++;
576✔
1207
            }
1208
        }
1209
    }
1210
    ret = 0;
1211

1212
error:
144✔
1213
    return ret;
144✔
1214
}
1215

1216
/* Return the RSA key size capabilities in a NULL-terminated array */
1217
static int get_rsa_keysize_caps(unsigned long flags, const gchar **swtpm_prg_l,
9✔
1218
                                gchar ***keysize_strs)
1219
{
1220
    unsigned int *keysizes = NULL;
9✔
1221
    size_t n_keysizes = 0;
9✔
1222
    size_t i, j;
9✔
1223
    int ret = get_rsa_keysizes(flags, swtpm_prg_l, &keysizes, &n_keysizes);
9✔
1224
    if (ret)
9✔
1225
        return ret;
1226

1227
    *keysize_strs = g_malloc0(sizeof(char *) * (n_keysizes + 1));
9✔
1228
    for (i = 0, j = 0; i < n_keysizes; i++) {
45✔
1229
        if (keysizes[i] >= 2048)
36✔
1230
            (*keysize_strs)[j++] = g_strdup_printf("tpm2-rsa-keysize-%u", keysizes[i]);
27✔
1231
    }
1232

1233
    g_free(keysizes);
9✔
1234

1235
    return 0;
9✔
1236
}
1237

1238
static bool is_rsa_keysize_supported(unsigned long flags, unsigned int rsa_keysize,
135✔
1239
                                     gchar **swtpm_prg_l)
1240
{
1241
    g_autofree unsigned int *keysizes = NULL;
270✔
1242
    gboolean found = FALSE;
135✔
1243
    size_t n_keysizes;
135✔
1244
    size_t i;
135✔
1245
    int ret;
135✔
1246

1247
    ret = get_rsa_keysizes(flags, (const char **)swtpm_prg_l, &keysizes, &n_keysizes);
135✔
1248
    if (ret)
135✔
1249
        return false;
1250

1251
    for (i = 0; i < n_keysizes && !found; i++)
438✔
1252
        found = (keysizes[i] == rsa_keysize);
303✔
1253
    if (!found && rsa_keysize != 2048) {
135✔
UNCOV
1254
        logerr(gl_LOGFILE, "%u bit RSA keys are not supported by libtpms.\n", rsa_keysize);
×
UNCOV
1255
        return false;
×
1256
    }
1257
    return true;
1258
}
1259

1260
/* Parse the rsa_keysize_str and check that it contains a supported size */
1261
static unsigned int parse_rsa_keysize(unsigned long flags, char **rsa_keysize_str,
125✔
1262
                                      gchar **swtpm_prg_l)
1263
{
1264
    unsigned int *keysizes = NULL;
125✔
1265
    unsigned int rsa_keysize;
125✔
1266
    size_t n_keysizes;
125✔
1267
    int ret;
125✔
1268

1269
    if (strcmp(*rsa_keysize_str, "max") == 0) {
125✔
UNCOV
1270
        ret = get_rsa_keysizes(flags, (const char **)swtpm_prg_l, &keysizes, &n_keysizes);
×
UNCOV
1271
        if (ret)
×
1272
            return 0;
UNCOV
1273
        g_free(*rsa_keysize_str);
×
UNCOV
1274
        if (n_keysizes > 0) {
×
1275
            /* last one is the biggest one */
1276
            *rsa_keysize_str = g_strdup_printf("%u", keysizes[n_keysizes - 1]);
×
1277
        } else {
1278
            *rsa_keysize_str = g_strdup("2048");
×
1279
        }
UNCOV
1280
        g_free(keysizes);
×
1281
    }
1282

1283
    if (strcmp(*rsa_keysize_str, "2048") == 0 ||
125✔
1284
        strcmp(*rsa_keysize_str, "3072") == 0 ||
19✔
1285
        strcmp(*rsa_keysize_str, "4096") == 0) {
7✔
1286

1287
        rsa_keysize = strtoull(*rsa_keysize_str, NULL, 10);
125✔
1288

1289
        if (!is_rsa_keysize_supported(flags, rsa_keysize, swtpm_prg_l))
125✔
1290
            return 0;
1291
        return rsa_keysize;
1292
    }
1293

UNCOV
1294
    logit(gl_LOGFILE, "Unsupported RSA key size %s.\n", *rsa_keysize_str);
×
UNCOV
1295
    return 0;
×
1296
}
1297

1298
static int validate_json_profile(const gchar **swtpm_prg_l, const char *json_profile)
95✔
1299
{
1300
    g_autofree gchar *standard_output = NULL;
190✔
1301
    int ret;
95✔
1302

1303
    ret = get_swtpm_capabilities(swtpm_prg_l, TRUE, &standard_output);
95✔
1304
    if (ret)
95✔
1305
        return ret;
1306

1307
    return check_json_profile(standard_output, json_profile);
95✔
1308
}
1309

1310
/* Print the JSON object of swtpm_setup's capabilities */
1311
static int print_capabilities(const char **swtpm_prg_l, gboolean swtpm_has_tpm12,
9✔
1312
                              gboolean swtpm_has_tpm2)
1313
{
1314
    g_autofree gchar *standard_output = NULL;
18✔
1315
    g_autofree gchar *param = g_strdup("");
18✔
1316
    g_autofree gchar *profile_list = NULL;
9✔
1317
    gchar **profile_names = NULL;
9✔
1318
    gchar **keysize_strs = NULL;
9✔
1319
    gchar *tmp;
9✔
1320
    size_t i;
9✔
1321
    int ret = 0;
9✔
1322

1323
    ret = get_rsa_keysize_caps(SETUP_TPM2_F, swtpm_prg_l, &keysize_strs);
9✔
1324
    if (ret)
9✔
1325
        return 1;
1326

1327
    for (i = 0; keysize_strs[i] != NULL; i++) {
36✔
1328
        tmp = g_strdup_printf("%s, \"%s\"", param, keysize_strs[i]);
27✔
1329
        g_free(param);
27✔
1330
        param = tmp;
27✔
1331
    }
1332

1333
    if (swtpm_has_tpm2) {
9✔
1334
        ret = get_swtpm_capabilities(swtpm_prg_l, TRUE, &standard_output);
9✔
1335
        if (ret)
9✔
UNCOV
1336
            goto error;
×
1337
        ret = get_profile_names(standard_output, &profile_names);
9✔
1338
        if (ret)
9✔
UNCOV
1339
            goto error;
×
1340

1341
        if (g_strv_length(profile_names) > 0) {
9✔
1342
            tmp = g_strjoinv("\", \"", profile_names);
9✔
1343
            profile_list = g_strdup_printf(" \"%s\" ", tmp);
9✔
1344
            g_free(tmp);
9✔
1345
        }
1346
    }
1347

1348
    printf("{ \"type\": \"swtpm_setup\", "
9✔
1349
           "\"features\": [ %s%s\"cmdarg-keyfile-fd\", \"cmdarg-pwdfile-fd\", \"tpm12-not-need-root\""
1350
           ", \"cmdarg-write-ek-cert-files\", \"cmdarg-create-config-files\""
1351
           ", \"cmdarg-reconfigure-pcr-banks\""
1352
           "%s"
1353
           ", \"cmdarg-profile\", \"cmdarg-profile-remove-disabled\""
1354
           ", \"cmdarg-ek1keyalgo\", \"cmdarg-ek2keyalgo\""
1355
           " ], "
1356
           "\"profiles\": [%s], "
1357
           "\"version\": \"" VERSION "\" "
1358
           "}\n",
1359
           swtpm_has_tpm12 ? "\"tpm-1.2\", " : "",
1360
           swtpm_has_tpm2  ? "\"tpm-2.0\", " : "",
1361
           param,
1362
           profile_list ? profile_list : ""
1363
           );
1364

1365
error:
9✔
1366
    g_strfreev(keysize_strs);
9✔
1367
    g_strfreev(profile_names);
9✔
1368

1369
    return ret;
9✔
1370
}
1371

1372
static int change_process_owner(const char *user)
1373
{
UNCOV
1374
    char *endptr;
×
UNCOV
1375
    unsigned long long uid = strtoull(user, &endptr, 10);
×
UNCOV
1376
    gid_t gid;
×
UNCOV
1377
    struct passwd *passwd;
×
UNCOV
1378
    int ret = 1;
×
1379

1380
    if (*endptr != '\0') {
×
1381
        /* assuming a name */
1382
        passwd = getpwnam(user);
×
1383
        if (passwd == NULL) {
×
UNCOV
1384
            logerr(gl_LOGFILE, "Error: User '%s' does not exist.\n", user);
×
1385
            goto error;
×
1386
        }
1387

1388
        if (initgroups(passwd->pw_name, passwd->pw_gid) != 0) {
×
1389
            logerr(gl_LOGFILE, "Error: initgroups() failed: %s\n", strerror(errno));
×
1390
            goto error;
×
1391
        }
1392

1393
        gid = passwd->pw_gid;
×
1394
        uid = passwd->pw_uid;
×
1395
    } else {
UNCOV
1396
        if (uid > 0xffffffff) {
×
UNCOV
1397
            logerr(gl_LOGFILE, "Error: uid %s outside valid range.\n", user);
×
1398
            goto error;
×
1399
        }
UNCOV
1400
        gid = (gid_t)uid;
×
1401
    }
1402

1403
    if (setgid(gid) != 0) {
×
UNCOV
1404
        logerr(gl_LOGFILE, "Error: setgid(%d) failed: %s\n", gid, strerror(errno));
×
1405
        goto error;
×
1406
    }
1407

1408
    if (setuid(uid) != 0) {
×
1409
        logerr(gl_LOGFILE, "Error: setuid(%lld) failed: %s\n", uid, strerror(errno));
×
1410
        goto error;
×
1411
    }
1412

1413
    ret = 0;
1414

1415
error:
×
UNCOV
1416
    return ret;
×
1417
}
1418

1419
static int handle_create_config_files(const char *opt_arg)
1420
{
1421
    g_auto(GStrv) tokens = NULL;
×
UNCOV
1422
    gboolean overwrite = FALSE;
×
UNCOV
1423
    gboolean root_flag = FALSE;
×
UNCOV
1424
    gboolean skip_if_exist = FALSE;
×
1425

1426
    if (opt_arg) {
×
1427
        tokens = g_strsplit_set(opt_arg, ", ", -1);
×
1428
        overwrite = g_strv_contains((const gchar **)tokens, "overwrite");
×
1429
        root_flag = g_strv_contains((const gchar **)tokens, "root");
×
UNCOV
1430
        skip_if_exist = g_strv_contains((const gchar **)tokens, "skip-if-exist");
×
1431
        if (overwrite && skip_if_exist) {
×
1432
            fprintf(stderr, "Error: overwrite and skip-if-exist cannot both be used\n");
×
1433
            return 1;
×
1434
        }
1435
    }
1436

1437
    return create_config_files(overwrite, root_flag, skip_if_exist);
×
1438
}
1439

1440
static int read_config_file(const gchar *config_file,
165✔
1441
                            const struct passwd *user,
1442
                            gchar ***config_file_lines)
1443
{
1444
    if (access(config_file, R_OK) != 0) {
165✔
UNCOV
1445
        logerr(gl_LOGFILE, "User %s cannot read config file %s.\n",
×
1446
               user ? user->pw_name : "<unknown>", config_file);
UNCOV
1447
        return -1;
×
1448
    }
1449

1450
    if (read_file_lines(config_file, config_file_lines))
165✔
1451
        return -1;
1452

1453
    return 0;
1454
}
1455

1456
static bool parse_keyalgo(const char *keyalgo_str,
20✔
1457
                          enum keyalgo *keyalgo,
1458
                          unsigned int *keyalgo_param,
1459
                          unsigned long *flags)
1460
{
1461
    size_t i;
20✔
1462

1463
    for (i = 0; i < ARRAY_LEN(keyalgo_choices); i++) {
75✔
1464
        if (!strcasecmp(keyalgo_choices[i].name, keyalgo_str)) {
75✔
1465
            *keyalgo = keyalgo_choices[i].keyalgo;
20✔
1466
            *keyalgo_param = keyalgo_choices[i].keyalgo_param;
20✔
1467
            return true;
20✔
1468
        }
1469
    }
UNCOV
1470
    logerr(gl_LOGFILE,
×
1471
           "Key algorithm %s is not supported.\n", keyalgo_str);
UNCOV
1472
    return false;
×
1473
}
1474

1475
int main(int argc, char *argv[])
192✔
1476
{
1477
    int opt, option_index = 0;
192✔
1478
    static const struct option long_options[] = {
192✔
1479
        {"tpm-state", required_argument, NULL, 't'},
1480
        {"tpmstate", required_argument, NULL, 't'}, /* alias for tpm-state */
1481
        {"tpm", required_argument, NULL, 'T'},
1482
        {"swtpm_ioctl", required_argument, NULL, '_'},
1483
        {"tpm2", no_argument, NULL, '2'},
1484
        {"ecc", no_argument, NULL, 'e'},
1485
        {"createek", no_argument, NULL, 'c'},
1486
        {"create-spk", no_argument, NULL, 'C'},
1487
        {"ek1keyalgo", required_argument, NULL, '4'},
1488
        {"ek2keyalgo", required_argument, NULL, '5'},
1489
        {"take-ownership", no_argument, NULL, 'o'},
1490
        {"ownerpass", required_argument, NULL, 'O'},
1491
        {"owner-well-known", no_argument, NULL, 'w'},
1492
        {"srkpass", required_argument, NULL, 'S'},
1493
        {"srk-well-known", no_argument, NULL, 's'},
1494
        {"create-ek-cert", no_argument, NULL, 'E'},
1495
        {"create-platform-cert", no_argument, NULL, 'P'},
1496
        {"lock-nvram", no_argument, NULL, 'L'},
1497
        {"display", no_argument, NULL, 'i'},
1498
        {"config", required_argument, NULL, 'f'},
1499
        {"vmid", required_argument, NULL, 'm'},
1500
        {"keyfile", required_argument, NULL, 'x'},
1501
        {"keyfile-fd", required_argument, NULL, 'X'},
1502
        {"pwdfile", required_argument, NULL, 'k'},
1503
        {"pwdfile-fd", required_argument, NULL, 'K'},
1504
        {"cipher", required_argument, NULL, 'p'},
1505
        {"runas", required_argument, NULL, 'r'},
1506
        {"logfile", required_argument, NULL, 'l'},
1507
        {"overwrite", no_argument, NULL, 'v'},
1508
        {"not-overwrite", no_argument, NULL, 'V'},
1509
        {"allow-signing", no_argument, NULL, 'a'},
1510
        {"decryption", no_argument, NULL, 'd'},
1511
        {"pcr-banks", required_argument, NULL, 'b'},
1512
        {"rsa-keysize", required_argument, NULL, 'A'},
1513
        {"write-ek-cert-files", required_argument, NULL, '3'},
1514
        {"create-config-files", optional_argument, NULL, 'u'},
1515
        {"tcsd-system-ps-file", required_argument, NULL, 'F'},
1516
        {"version", no_argument, NULL, '1'},
1517
        {"print-capabilities", no_argument, NULL, 'y'},
1518
        {"reconfigure", no_argument, NULL, 'R'},
1519
        {"profile", required_argument, NULL, 'I'},
1520
        {"profile-name", required_argument, NULL, 'J'},
1521
        {"profile-file", required_argument, NULL, 'g'},
1522
        {"profile-file-fd", required_argument, NULL, 'G'},
1523
        {"profile-remove-disabled", required_argument, NULL, 'j'},
1524
        {"print-profiles", no_argument, NULL, 'M'},
1525
        {"help", no_argument, NULL, 'h'},
1526
        {NULL, 0, NULL, 0}
1527
    };
1528
    unsigned long flags = 0;
192✔
1529
    g_auto(GStrv) config_file_lines = NULL;
192✔
1530
    g_autofree gchar *swtpm_prg = NULL;
192✔
1531
    g_autofree gchar *tpm_state_path = NULL;
192✔
1532
    struct swtpm_backend_ops *backend_ops = &swtpm_backend_dir;
192✔
1533
    void *backend_state = NULL;
192✔
1534
    g_autofree gchar *config_file = NULL;
192✔
1535
    g_autofree gchar *ownerpass = NULL;
192✔
1536
    gboolean got_ownerpass = FALSE;
192✔
1537
    g_autofree gchar *srkpass = NULL;
192✔
1538
    gboolean got_srkpass = FALSE;
192✔
1539
    g_autofree gchar *vmid = NULL;
192✔
1540
    g_autofree gchar *pcr_banks = NULL;
192✔
1541
    gboolean printcapabilities = FALSE;
192✔
1542
    gboolean printprofiles = FALSE;
192✔
1543
    g_autofree gchar *keyfile = NULL;
192✔
1544
    long int keyfile_fd = -1;
192✔
1545
    g_autofree gchar *pwdfile = NULL;
192✔
1546
    long int pwdfile_fd = -1;
192✔
1547
    g_autofree gchar *cipher = g_strdup("aes-128-cbc");
384✔
1548
    g_autofree gchar *rsa_keysize_str = NULL;
192✔
1549
    unsigned int rsa_keysize = 2048;
192✔
1550
    g_autofree gchar *swtpm_keyopt = NULL;
192✔
1551
    g_autofree gchar *runas = NULL;
192✔
1552
    g_autofree gchar *certsdir = NULL;
192✔
1553
    g_autofree gchar *user_certsdir = NULL;
192✔
1554
    g_autofree gchar *json_profile = NULL;
192✔
1555
    g_autofree gchar *json_profile_name = NULL;
192✔
1556
    g_autofree gchar *json_profile_file = NULL;
192✔
1557
    g_autofree gchar *profile_remove_disabled_param = NULL;
192✔
1558
    g_autofree gchar *ek1keyalgo_str = NULL;
192✔
1559
    g_autofree gchar *ek2keyalgo_str = NULL;
192✔
1560
    int json_profile_fd = -1;
192✔
1561
    gchar *tmp;
192✔
1562
    gchar **swtpm_prg_l = NULL;
192✔
1563
    gchar **tmp_l = NULL;
192✔
1564
    size_t i, n;
192✔
1565
    int logfd;
192✔
1566
    const struct passwd *curr_user;
192✔
1567
    struct group *curr_grp;
192✔
1568
    char *endptr;
192✔
1569
    gboolean swtpm_has_tpm12 = FALSE;
192✔
1570
    gboolean swtpm_has_tpm2 = FALSE;
192✔
1571
    int fds_to_pass[2] = { -1, -1 };
192✔
1572
    unsigned n_fds_to_pass = 0;
192✔
1573
    char tmpbuffer[200];
192✔
1574
    time_t now;
192✔
1575
    struct tm *tm;
192✔
1576
    int ret = 1;
192✔
1577
    g_autoptr(GError) error = NULL;
192✔
1578
    enum keyalgo ek1keyalgo = KEYALGO_RSA;
192✔
1579
    enum keyalgo ek2keyalgo = KEYALGO_ECC;
192✔
1580
    unsigned int ek1keyalgo_param = 0;
192✔
1581
    unsigned int ek2keyalgo_param = 0;
192✔
1582

1583
    setvbuf(stdout, 0, _IONBF, 0);
192✔
1584

1585
    if (init(&config_file) < 0)
192✔
UNCOV
1586
        goto error;
×
1587

1588
    swtpm_prg = g_find_program_in_path("swtpm");
192✔
1589
    if (swtpm_prg) {
192✔
1590
        tmp = g_strconcat(swtpm_prg, " socket", NULL);
75✔
1591
        g_free(swtpm_prg);
75✔
1592
        swtpm_prg = tmp;
75✔
1593
    }
1594

1595
    while ((opt = getopt_long(argc, argv, "h?",
3,340✔
1596
                              long_options, &option_index)) != -1) {
1,670✔
1597
        switch (opt) {
1,480✔
1598
        case 't': /* --tpmstate, --tpm-state */
177✔
1599
            g_free(tpm_state_path);
177✔
1600
            if (strncmp(optarg, "dir://", 6) == 0) {
177✔
1601
                tpm_state_path = g_strdup(optarg);
10✔
1602
            } else if (strncmp(optarg, "file://", 7) == 0) {
167✔
1603
                tpm_state_path = g_strdup(optarg);
3✔
1604
                backend_ops = &swtpm_backend_file;
1605
            } else {
1606
                /* always prefix with dir:// so we can pass verbatim to swtpm */
1607
                tpm_state_path = g_strconcat("dir://", optarg, NULL);
164✔
1608
            }
1609
            break;
1610
        case 'T': /* --tpm */
178✔
1611
            g_free(swtpm_prg);
178✔
1612
            swtpm_prg = g_strdup(optarg);
178✔
1613
            break;
UNCOV
1614
        case '_': /* --swtpm_ioctl */
×
UNCOV
1615
            fprintf(stdout, "Warning: --swtpm_ioctl is deprecated and has no effect.");
×
UNCOV
1616
            break;
×
1617
        case '2': /* --tpm2 */
154✔
1618
            flags |= SETUP_TPM2_F;
154✔
1619
            break;
154✔
1620
        case 'e': /* --ecc */
17✔
1621
            flags |= SETUP_TPM2_ECC_F;
17✔
1622
            break;
17✔
1623
        case '4': /* --ek1keyalgo */
10✔
1624
            g_free(ek1keyalgo_str);
10✔
1625
            ek1keyalgo_str = g_strdup(optarg);
10✔
1626
            break;
1627
        case '5': /* --ek2keyalgo */
10✔
1628
            g_free(ek2keyalgo_str);
10✔
1629
            ek2keyalgo_str = g_strdup(optarg);
10✔
1630
            break;
1631
        case 'c': /* --createek */
50✔
1632
            flags |= SETUP_CREATE_EK_F;
50✔
1633
            break;
50✔
1634
        case 'C': /* --create-spk */
12✔
1635
            flags |= SETUP_CREATE_SPK_F;
12✔
1636
            break;
12✔
1637
        case 'o': /* --take-ownership */
10✔
1638
            flags |= SETUP_CREATE_EK_F | SETUP_TAKEOWN_F;
10✔
1639
            break;
10✔
1640
        case 'O': /* --ownerpass */
2✔
1641
            g_free(ownerpass);
2✔
1642
            ownerpass = g_strdup(optarg);
2✔
1643
            got_ownerpass = TRUE;
1644
            break;
1645
        case 'w': /* --owner-well-known */
2✔
1646
            flags |= SETUP_OWNERPASS_ZEROS_F;
2✔
1647
            got_ownerpass = TRUE;
2✔
1648
            break;
2✔
1649
        case 'S': /* --srk-pass */
2✔
1650
            g_free(srkpass);
2✔
1651
            srkpass = g_strdup(optarg);
2✔
1652
            got_srkpass = TRUE;
1653
            break;
1654
        case 's': /* --srk-well-known */
2✔
1655
            flags |= SETUP_SRKPASS_ZEROS_F;
2✔
1656
            got_srkpass = TRUE;
2✔
1657
            break;
2✔
1658
        case 'E': /* --create-ek-cert */
58✔
1659
            flags |= SETUP_CREATE_EK_F | SETUP_EK_CERT_F;
58✔
1660
            break;
58✔
1661
        case 'P': /* --create-platform-cert */
56✔
1662
            flags |= SETUP_CREATE_EK_F | SETUP_PLATFORM_CERT_F;
56✔
1663
            break;
56✔
1664
        case 'L': /* --lock-nvram */
16✔
1665
            flags |= SETUP_LOCK_NVRAM_F;
16✔
1666
            break;
16✔
1667
        case 'i': /* --display */
40✔
1668
            flags |= SETUP_DISPLAY_RESULTS_F;
40✔
1669
            break;
40✔
1670
        case 'f': /* --config */
220✔
1671
            g_free(config_file);
220✔
1672
            config_file = g_strdup(optarg);
220✔
1673
            break;
220✔
1674
        case 'm': /* --vmid */
41✔
1675
            g_free(vmid);
41✔
1676
            vmid = g_strdup(optarg);
41✔
1677
            break;
1678
        case 'x': /* --keyfile */
12✔
1679
            g_free(keyfile);
12✔
1680
            keyfile = g_strdup(optarg);
12✔
1681
            break;
1682
        case 'X': /* --pwdfile-fd' */
2✔
1683
            keyfile_fd = strtoull(optarg, &endptr, 10);
2✔
1684
            if (*endptr != '\0' && keyfile_fd >= INT_MAX) {
2✔
UNCOV
1685
                fprintf(stderr, "Invalid file descriptor '%s'\n", optarg);
×
UNCOV
1686
                goto error;
×
1687
            }
1688
            break;
1689
        case 'k': /* --pwdfile */
17✔
1690
            g_free(pwdfile);
17✔
1691
            pwdfile = g_strdup(optarg);
17✔
1692
            break;
1693
        case 'K': /* --pwdfile-fd' */
2✔
1694
            pwdfile_fd = strtoull(optarg, &endptr, 10);
2✔
1695
            if (*endptr != '\0' || pwdfile_fd >= INT_MAX) {
2✔
UNCOV
1696
                fprintf(stderr, "Invalid file descriptor '%s'\n", optarg);
×
UNCOV
1697
                goto error;
×
1698
            }
1699
            break;
1700
        case 'p': /* --cipher */
14✔
1701
            g_free(cipher);
14✔
1702
            cipher = g_strdup(optarg);
14✔
1703
            break;
UNCOV
1704
        case 'r': /* --runas */
×
UNCOV
1705
            g_free(runas);
×
UNCOV
1706
            runas = g_strdup(optarg);
×
1707
            break;
1708
        case 'l': /* --logfile */
96✔
1709
            g_free(gl_LOGFILE);
96✔
1710
            gl_LOGFILE = g_strdup(optarg);
96✔
1711
            break;
96✔
1712
        case 'v': /* --overwrite */
93✔
1713
            flags |= SETUP_STATE_OVERWRITE_F;
93✔
1714
            break;
93✔
1715
        case 'V': /* --not-overwrite */
3✔
1716
            flags |= SETUP_STATE_NOT_OVERWRITE_F;
3✔
1717
            break;
3✔
1718
        case 'a': /* --allow-signing */
25✔
1719
            flags |= SETUP_ALLOW_SIGNING_F;
25✔
1720
            break;
25✔
1721
        case 'd': /* --decryption */
8✔
1722
            flags |= SETUP_DECRYPTION_F;
8✔
1723
            break;
8✔
1724
        case 'b': /* --pcr-banks */
9✔
1725
            tmp = g_strconcat(pcr_banks ? pcr_banks: "",
18✔
1726
                              pcr_banks ? "," : "", g_strstrip(optarg), NULL);
1727
            g_free(pcr_banks);
9✔
1728
            pcr_banks = tmp;
9✔
1729
            break;
9✔
1730
        case 'A': /* --rsa-keysize */
21✔
1731
            g_free(rsa_keysize_str);
21✔
1732
            rsa_keysize_str = strdup(optarg);
21✔
1733
            flags |= SETUP_RSA_KEYSIZE_BY_USER_F;
21✔
1734
            break;
21✔
1735
        case '3': /* --write-ek-cert-files */
9✔
1736
            g_free(user_certsdir);
9✔
1737
            user_certsdir = g_strdup(optarg);
9✔
1738
            flags |= SETUP_WRITE_EK_CERT_FILES_F;
9✔
1739
            break;
9✔
UNCOV
1740
        case 'u':
×
UNCOV
1741
            if (optarg == NULL && optind < argc && argv[optind][0] != '0')
×
UNCOV
1742
                optarg = argv[optind++];
×
UNCOV
1743
            ret = handle_create_config_files(optarg);
×
UNCOV
1744
            goto out;
×
1745
        case 'F': /* --tcsd-system-ps-file */
1746
            printf("Warning: --tcsd-system-ps-file is deprecated and has no effect.");
×
1747
            break;
×
1748
        case '1': /* --version */
1✔
1749
            versioninfo();
1✔
1750
            ret = 0;
1✔
1751
            goto out;
1✔
1752
        case 'y': /* --print-capabilities */
1753
            printcapabilities = TRUE;
1754
            break;
1755
        case 'R': /* --reconfigure */
8✔
1756
            flags |= SETUP_RECONFIGURE_F;
8✔
1757
            break;
8✔
1758
        case 'I': /* --profile */
60✔
1759
            g_free(json_profile);
60✔
1760
            json_profile = g_strdup(optarg);
60✔
1761
            break;
60✔
1762
        case 'J': /* --profile-name */
23✔
1763
            g_free(json_profile_name);
23✔
1764
            json_profile_name = g_strdup(optarg);
23✔
1765
            break;
1766
        case 'g': /* --profile-file */
1✔
1767
            g_free(json_profile_file);
1✔
1768
            json_profile_file = g_strdup(optarg);
1✔
1769
            break;
1✔
UNCOV
1770
        case 'G': /* --profile-file-fd */
×
UNCOV
1771
            json_profile_fd = strtoull(optarg, &endptr, 10);
×
UNCOV
1772
            if (*endptr != '\0' || json_profile_fd >= INT_MAX) {
×
UNCOV
1773
                fprintf(stderr, "Invalid file descriptor '%s'\n", optarg);
×
UNCOV
1774
                goto error;
×
1775
            }
1776
            break;
1777
        case 'j': /* --profile-remove-disabled */
6✔
1778
            if (strcmp(optarg, "fips-host") != 0 &&
6✔
1779
                strcmp(optarg, "check") != 0) {
×
UNCOV
1780
                fprintf(stderr,
×
1781
                        "Unsupported parameter for --profile-remove-disabled: %s\n",
1782
                        optarg);
UNCOV
1783
                goto error;
×
1784
            }
1785
            g_free(profile_remove_disabled_param);
6✔
1786
            profile_remove_disabled_param = g_strdup(optarg);
1,676✔
1787
            break;
1788
        case 'M': /* --print-profiles */
3✔
1789
            printprofiles = TRUE;
3✔
1790
            break;
3✔
1791
        case '?':
1✔
1792
        case 'h': /* --help */
1793
            usage(argv[0], config_file);
1✔
1794
            if (opt == 'h')
1✔
1795
                ret = 0;
1✔
1796
            goto out;
1✔
UNCOV
1797
        default:
×
UNCOV
1798
            fprintf(stderr, "Unknown option code %d\n", opt);
×
UNCOV
1799
            usage(argv[0], config_file);
×
UNCOV
1800
            goto error;
×
1801
        }
1802
    }
1803

1804
    if (gl_LOGFILE != NULL) {
190✔
1805
        logfd = open(gl_LOGFILE, O_WRONLY|O_APPEND|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR|S_IRGRP);
96✔
1806
        if (logfd < 0) {
96✔
UNCOV
1807
            fprintf(stderr, "Cannot open logfile %s: %s\n", gl_LOGFILE, strerror(errno));
×
UNCOV
1808
            goto error;
×
1809
        }
1810
        close(logfd);
96✔
1811
    }
1812

1813
    if (swtpm_prg == NULL) {
190✔
1814
        logerr(gl_LOGFILE,
11✔
1815
               "Default TPM 'swtpm' could not be found and was not provided using --tpm.\n");
1816
        goto error;
11✔
1817
    }
1818

1819
    swtpm_prg_l = split_cmdline(swtpm_prg);
179✔
1820
    tmp = g_find_program_in_path(swtpm_prg_l[0]);
179✔
1821
    if (!tmp) {
179✔
UNCOV
1822
        logerr(gl_LOGFILE, "swtpm at %s is not an executable.\n", swtpm_prg_l[0]);
×
UNCOV
1823
        goto error;
×
1824
    }
1825
    g_free(tmp);
179✔
1826

1827
    ret = get_supported_tpm_versions((const char **)swtpm_prg_l, &swtpm_has_tpm12, &swtpm_has_tpm2);
179✔
1828
    if (ret != 0)
179✔
UNCOV
1829
        goto error;
×
1830

1831
    if (printcapabilities) {
179✔
1832
        ret = print_capabilities((const char **)swtpm_prg_l, swtpm_has_tpm12, swtpm_has_tpm2);
9✔
1833
        goto out;
9✔
1834
    }
1835

1836
    if ((flags & SETUP_TPM2_F) != 0 && !swtpm_has_tpm2) {
170✔
UNCOV
1837
        logerr(gl_LOGFILE, "swtpm at %s does not support TPM 2\n", swtpm_prg_l[0]);
×
UNCOV
1838
        goto error;
×
1839
    } else if ((flags & SETUP_TPM2_F) == 0 && !swtpm_has_tpm12){
170✔
UNCOV
1840
        logerr(gl_LOGFILE, "swtpm at %s does not support TPM 1.2\n", swtpm_prg_l[0]);
×
UNCOV
1841
        goto error;
×
1842
    }
1843

1844
    if (runas) {
170✔
1845
        ret = change_process_owner(runas);
×
1846
        if (ret != 0)
×
UNCOV
1847
            goto error;
×
1848
    }
1849

1850
    curr_user = getpwuid(getuid());
170✔
1851

1852
    if (printprofiles) {
170✔
1853
        ret = 0;
3✔
1854
        if (read_config_file(config_file, curr_user, &config_file_lines) < 0)
3✔
UNCOV
1855
            goto error;
×
1856

1857
        if (flags & SETUP_TPM2_F) {
3✔
1858
            if (profile_printall((const char **)swtpm_prg_l, config_file_lines))
3✔
1859
                ret = 1;
3✔
1860
        } else {
UNCOV
1861
            printf("{}\n");
×
1862
        }
1863
        goto out;
3✔
1864
    }
1865

1866
    if (!got_ownerpass)
167✔
1867
        ownerpass = g_strdup(DEFAULT_OWNER_PASSWORD);
163✔
1868
    if (!got_srkpass)
167✔
1869
        srkpass = g_strdup(DEFAULT_SRK_PASSWORD);
163✔
1870

1871
    // Check tpm_state_path directory and access rights
1872
    if (tpm_state_path == NULL) {
167✔
UNCOV
1873
        logerr(gl_LOGFILE, "--tpm-state must be provided\n");
×
UNCOV
1874
        goto error;
×
1875
    }
1876

1877
    backend_state = backend_ops->parse_backend(tpm_state_path);
167✔
1878
    if (!backend_state)
167✔
1879
        goto error;
×
1880

1881
    if (backend_ops->check_access(backend_state, R_OK|W_OK, curr_user) != 0)
167✔
UNCOV
1882
        goto error;
×
1883

1884
    if ((flags & SETUP_WRITE_EK_CERT_FILES_F)) {
167✔
1885
        if (check_directory_access(user_certsdir, W_OK, curr_user) != 0)
9✔
UNCOV
1886
            goto error;
×
1887
    }
1888

1889
    if (flags & SETUP_TPM2_F) {
167✔
1890
        if (flags & SETUP_TAKEOWN_F) {
138✔
1891
            logerr(gl_LOGFILE, "Taking ownership is not supported for TPM 2.\n");
×
UNCOV
1892
            goto error;
×
1893
        }
1894
    } else {
1895
        if (flags & SETUP_TPM2_ECC_F) {
29✔
1896
            logerr(gl_LOGFILE, "--ecc requires --tpm2.\n");
×
1897
            goto error;
×
1898
        }
1899
        if (flags & SETUP_CREATE_SPK_F) {
29✔
UNCOV
1900
            logerr(gl_LOGFILE, "--create-spk requires --tpm2.\n");
×
1901
            goto error;
×
1902
        }
1903
        if (flags & SETUP_RECONFIGURE_F) {
29✔
UNCOV
1904
            logerr(gl_LOGFILE, "--reconfigure requires --tpm2.\n");
×
1905
            goto error;
×
1906
        }
1907
        if (flags & SETUP_ALLOW_SIGNING_F) {
29✔
UNCOV
1908
            logerr(gl_LOGFILE, "--allow-signing requires --tpm2.\n");
×
1909
            goto error;
×
1910
        }
1911
        if (flags & SETUP_DECRYPTION_F) {
29✔
UNCOV
1912
            logerr(gl_LOGFILE, "--decryption requires --tpm2.\n");
×
1913
            goto error;
×
1914
        }
1915
        if (pcr_banks) {
29✔
UNCOV
1916
            logerr(gl_LOGFILE, "--pcr-banks requires --tpm2.\n");
×
1917
            goto error;
×
1918
        }
1919
    }
1920

1921
    if (!(flags & SETUP_RECONFIGURE_F)) {
167✔
1922
        ret = check_state_overwrite((const char **)swtpm_prg_l, flags, tpm_state_path);
161✔
1923
        if (ret == 1) {
161✔
1924
            goto error;
3✔
1925
        } else if (ret == 2) {
158✔
1926
            ret = 0;
2✔
1927
            goto out;
2✔
1928
        }
1929

1930
        ret = backend_ops->delete_state(backend_state);
156✔
1931
        if (ret != 0)
156✔
UNCOV
1932
            goto error;
×
1933
    }
1934

1935
    if (!config_file_lines &&
324✔
1936
        read_config_file(config_file, curr_user, &config_file_lines) < 0)
162✔
1937
        goto error;
×
1938

1939
    /* check pcr_banks; read from config file if not given */
1940
    tmp_l = g_strsplit(pcr_banks ? pcr_banks : "", ",", -1);
162✔
1941
    for (i = 0, n = 0; tmp_l[i]; i++) {
338✔
1942
        g_strstrip(tmp_l[i]);
14✔
1943
        n += strlen(tmp_l[i]);
14✔
1944
    }
1945
    g_strfreev(tmp_l);
162✔
1946
    if (n == 0) {
162✔
1947
        g_free(pcr_banks);
154✔
1948
        pcr_banks = get_default_pcr_banks(config_file_lines);
154✔
1949
    }
1950

1951
    if ((json_profile != NULL) +
162✔
1952
        (json_profile_name != NULL) +
162✔
1953
        (json_profile_file != NULL) +
162✔
1954
        (json_profile_fd > 0) > 1) {
162✔
UNCOV
1955
        logerr(gl_LOGFILE, "Only one of --profile, --profile-name, --profile-file, and --profile-file-fd may be given.\n");
×
UNCOV
1956
        goto error;
×
1957
    }
1958

1959
    if ((flags & SETUP_RECONFIGURE_F) &&
162✔
1960
         (json_profile ||
6✔
1961
          json_profile_name ||
6✔
1962
          json_profile_file ||
6✔
1963
          json_profile_fd > 0)) {
UNCOV
1964
            logerr(gl_LOGFILE, "Reconfiguration does not accept a (new) profile.\n");
×
UNCOV
1965
            goto error;
×
1966
    }
1967

1968
    if (json_profile_name) {
162✔
1969
        if (profile_name_check(json_profile_name) < 0)
23✔
1970
            goto error;
×
1971
        /*
1972
         * Load profile from distro and local locations; sets json_profile_file
1973
         * to filename or json_profile with the JSON.
1974
         */
1975
        if (profile_get_by_name(config_file_lines,
23✔
1976
                                json_profile_name,
1977
                                &json_profile_file,
1978
                                &json_profile) < 0) {
UNCOV
1979
            logerr(gl_LOGFILE, "Could not find or access profile '%s'.\n",
×
1980
                   json_profile_name);
UNCOV
1981
            goto error;
×
1982
        }
1983
    }
1984

1985
    if (json_profile_file) {
162✔
1986
        json_profile_fd = open(json_profile_file, O_RDONLY);
5✔
1987
        if (json_profile_fd < 0) {
5✔
UNCOV
1988
            logerr(gl_LOGFILE, "Could not open profile file '%s': %s\n",
×
UNCOV
1989
                   json_profile_file, strerror(errno));
×
UNCOV
1990
            goto error;
×
1991
        }
1992
    }
1993

1994
    /*
1995
     * Read default profile from swtpm_setup.conf;
1996
     * Do not read it when --reconfigure'ing
1997
     */
1998
    if ((flags & SETUP_TPM2_F) != 0 &&
162✔
1999
        json_profile == NULL && json_profile_fd < 0 &&
136✔
2000
        (flags & SETUP_RECONFIGURE_F) == 0) {
2001

2002
        json_profile_fd = get_default_profile_fd(config_file_lines);
46✔
2003
        if (json_profile_fd == -2)
46✔
UNCOV
2004
            goto error;
×
2005
        if (json_profile_fd < 0)
46✔
2006
            json_profile = get_default_profile(config_file_lines);
46✔
2007
    }
2008

2009
    if (json_profile_fd >= 0)
157✔
2010
        fds_to_pass[n_fds_to_pass++] = json_profile_fd;
5✔
2011

2012
    if ((flags & SETUP_TPM2_F) != 0 && json_profile) {
162✔
2013
        if (validate_json_profile((const char **)swtpm_prg_l, json_profile) != 0)
95✔
2014
            goto error;
1✔
2015
    } else if (json_profile) {
67✔
UNCOV
2016
        logerr(gl_LOGFILE, "There's no --profile support for TPM 1.2\n");
×
UNCOV
2017
        goto error;
×
2018
    }
2019

2020
    if (cipher != NULL) {
161✔
2021
        if (strcmp(cipher, "aes-128-cbc") != 0 &&
161✔
2022
            strcmp(cipher, "aes-cbc") != 0 &&
13✔
2023
            strcmp(cipher, "aes-256-cbc") != 0) {
13✔
UNCOV
2024
            logerr(gl_LOGFILE, "Unsupported cipher %s.\n", cipher);
×
UNCOV
2025
            goto error;
×
2026
        }
2027
        tmp = g_strdup_printf(",mode=%s", cipher);
161✔
2028
        g_free(cipher);
161✔
2029
        cipher = tmp;
161✔
2030
    }
2031

2032
    if (keyfile != NULL) {
161✔
2033
        if (access(keyfile, R_OK) != 0) {
12✔
UNCOV
2034
            logerr(gl_LOGFILE, "User %s cannot read keyfile %s.\n",
×
2035
                   curr_user ? curr_user->pw_name : "<unknown>", keyfile);
UNCOV
2036
            goto error;
×
2037
        }
2038
        swtpm_keyopt = g_strdup_printf("file=%s%s", keyfile, cipher);
12✔
2039
        logit(gl_LOGFILE, "  The TPM's state will be encrypted with a provided key.\n");
12✔
2040
    } else if (pwdfile != NULL) {
149✔
2041
        if (access(pwdfile, R_OK) != 0) {
17✔
UNCOV
2042
            logerr(gl_LOGFILE, "User %s cannot read passphrase file %s.\n",
×
2043
                   curr_user ? curr_user->pw_name : "<unknown>", pwdfile);
UNCOV
2044
            goto error;
×
2045
        }
2046
        swtpm_keyopt = g_strdup_printf("pwdfile=%s%s", pwdfile, cipher);
17✔
2047
        logit(gl_LOGFILE, "  The TPM's state will be encrypted using a key derived from a passphrase.\n");
17✔
2048
    } else if (keyfile_fd >= 0) {
132✔
2049
        fds_to_pass[n_fds_to_pass++] = keyfile_fd;
2✔
2050
        swtpm_keyopt = g_strdup_printf("fd=%ld%s", keyfile_fd, cipher);
2✔
2051
        logit(gl_LOGFILE, "  The TPM's state will be encrypted with a provided key (fd).\n");
2✔
2052
    } else if (pwdfile_fd >= 0) {
130✔
2053
        fds_to_pass[n_fds_to_pass++] = pwdfile_fd;
2✔
2054
        swtpm_keyopt = g_strdup_printf("pwdfd=%ld%s", pwdfile_fd, cipher);
2✔
2055
        logit(gl_LOGFILE, "  The TPM's state will be encrypted using a key derived from a passphrase (fd).\n");
2✔
2056
    }
2057

2058
    if ((flags & SETUP_TPM2_F) != 0) {
161✔
2059
        if (!ek1keyalgo_str)
135✔
2060
            ek1keyalgo_str = get_config_value(config_file_lines, "ek1keyalgo");
125✔
2061
        if (ek1keyalgo_str &&
135✔
2062
            !parse_keyalgo(ek1keyalgo_str, &ek1keyalgo, &ek1keyalgo_param, &flags))
10✔
UNCOV
2063
            goto error;
×
2064

2065
        if (!ek2keyalgo_str)
135✔
2066
            ek2keyalgo_str = get_config_value(config_file_lines, "ek2keyalgo");
125✔
2067
        if (ek2keyalgo_str &&
135✔
2068
            !parse_keyalgo(ek2keyalgo_str, &ek2keyalgo, &ek2keyalgo_param, &flags))
10✔
UNCOV
2069
            goto error;
×
2070

2071
        if (ek1keyalgo_param == 0 && ek1keyalgo == KEYALGO_RSA) {
135✔
2072
            if ((flags & SETUP_RSA_KEYSIZE_BY_USER_F) == 0)
125✔
2073
                rsa_keysize_str = get_default_rsa_keysize(config_file_lines);
105✔
2074

2075
            rsa_keysize = parse_rsa_keysize(flags, &rsa_keysize_str, swtpm_prg_l);
125✔
2076
            if (!rsa_keysize)
125✔
UNCOV
2077
                goto error;
×
2078
        } else {
2079
            if (ek1keyalgo == KEYALGO_RSA &&
16✔
2080
                !is_rsa_keysize_supported(flags, ek1keyalgo_param, swtpm_prg_l))
6✔
UNCOV
2081
                goto error;
×
2082
            if (ek2keyalgo == KEYALGO_RSA &&
14✔
2083
                !is_rsa_keysize_supported(flags, ek2keyalgo_param, swtpm_prg_l))
4✔
UNCOV
2084
                goto error;
×
2085
        }
2086
    }
2087

2088
    if (flags & SETUP_RECONFIGURE_F) {
161✔
2089
        if (flags & (SETUP_CREATE_EK_F | SETUP_EK_CERT_F | SETUP_PLATFORM_CERT_F)) {
6✔
UNCOV
2090
            logerr(gl_LOGFILE, "Reconfiguration is not supported with creation of EK or certificates\n");
×
UNCOV
2091
            goto error;
×
2092
        }
2093
    }
2094

2095
    now = time(NULL);
161✔
2096
    tm = localtime(&now);
161✔
2097
    if (strftime(tmpbuffer, sizeof(tmpbuffer), "%a %d %h %Y %I:%M:%S %p %Z", tm) == 0) {
161✔
UNCOV
2098
        logerr(gl_LOGFILE, "Could not format time/date string.\n");
×
UNCOV
2099
        goto error;
×
2100
    }
2101
    curr_grp = getgrgid(getgid());
161✔
2102
    logit(gl_LOGFILE, "Starting vTPM %s as %s:%s @ %s\n",
316✔
2103
          flags & SETUP_RECONFIGURE_F ? "reconfiguration" : "manufacturing",
2104
          curr_user ? curr_user->pw_name : "<unknown>",
2105
          curr_grp ? curr_grp->gr_name : "<unknown>",
2106
          tmpbuffer);
2107

2108
    if (flags & (SETUP_EK_CERT_F | SETUP_PLATFORM_CERT_F)) {
161✔
2109
        certsdir = g_dir_make_tmp("swtpm_setup.certs.XXXXXX", &error);
57✔
2110
        if (certsdir == NULL) {
57✔
UNCOV
2111
            logerr(gl_LOGFILE, "Could not create temporary directory for certs: %s\n",
×
UNCOV
2112
                   error->message);
×
UNCOV
2113
            goto error;
×
2114
        }
2115
    }
2116

2117
    if ((flags & SETUP_TPM2_F) == 0) {
161✔
2118
        ret = init_tpm(flags, swtpm_prg_l, config_file, tpm_state_path, ownerpass, srkpass, vmid,
26✔
2119
                       swtpm_keyopt, fds_to_pass, n_fds_to_pass, certsdir, user_certsdir);
2120
    } else {
2121
        if (ek1keyalgo_param == 0)
135✔
2122
            ek1keyalgo_param = rsa_keysize; // default
125✔
2123
        if (ek2keyalgo_param == 0)
135✔
2124
            ek2keyalgo_param = TPM2_ECC_NIST_P384; // default
125✔
2125

2126
        ret = init_tpm2(flags, swtpm_prg_l, config_file, tpm_state_path, vmid, pcr_banks,
135✔
2127
                       swtpm_keyopt, fds_to_pass, n_fds_to_pass,
2128
                       ek1keyalgo, ek1keyalgo_param,
2129
                       ek2keyalgo, ek2keyalgo_param,
2130
                       certsdir, user_certsdir, json_profile, json_profile_fd,
2131
                       profile_remove_disabled_param);
2132
    }
2133

2134
    if (ret == 0) {
161✔
2135
        logit(gl_LOGFILE, "Successfully authored TPM state.\n");
153✔
2136
    } else {
2137
        logerr(gl_LOGFILE, "An error occurred. Authoring the TPM state failed.\n");
8✔
2138
        backend_ops->delete_state(backend_state);
8✔
2139
    }
2140

2141
    now = time(NULL);
161✔
2142
    tm = localtime(&now);
161✔
2143
    if (strftime(tmpbuffer, sizeof(tmpbuffer), "%a %d %h %Y %I:%M:%S %p %Z", tm) == 0) {
161✔
UNCOV
2144
        logerr(gl_LOGFILE, "Could not format time/date string.\n");
×
UNCOV
2145
        goto error;
×
2146
    }
2147
    logit(gl_LOGFILE, "Ending vTPM manufacturing @ %s\n",
161✔
2148
          tmpbuffer);
2149

2150
out:
192✔
2151
    if (certsdir && g_rmdir(certsdir) != 0)
192✔
UNCOV
2152
        logerr(gl_LOGFILE, "Could not remove temporary directory for certs: %s\n",
×
UNCOV
2153
               strerror(errno));
×
2154

2155
    if (backend_ops && backend_state)
192✔
2156
        backend_ops->free_backend(backend_state);
167✔
2157
    g_strfreev(swtpm_prg_l);
192✔
2158
    g_free(gl_LOGFILE);
192✔
2159

2160
    return ret;
192✔
2161

2162
error:
15✔
2163
    ret = 1;
15✔
2164
    goto out;
15✔
2165
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc