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

stefanberger / swtpm / #2974

07 May 2026 02:12AM UTC coverage: 73.613% (-0.05%) from 73.663%
#2974

push

travis-ci

web-flow
Merge 5b8dffd9d into 74f272e33

3 of 3 new or added lines in 1 file covered. (100.0%)

6 existing lines in 2 files now uncovered.

7998 of 10865 relevant lines covered (73.61%)

9912.55 hits per line

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

79.46
/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 <openssl/pem.h>
35
#include <openssl/sha.h>
36
#include <openssl/x509v3.h>
37

38
#include <libtpms/tpm_nvfilename.h>
39

40
#include "profile.h"
41
#include "swtpm.h"
42
#include "swtpm_conf.h"
43
#include "swtpm_utils.h"
44
#include "swtpm_setup_utils.h"
45

46
/* default values for passwords */
47
#define DEFAULT_OWNER_PASSWORD "ooo"
48
#define DEFAULT_SRK_PASSWORD   "sss"
49

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

71
/* default configuration file */
72
#define SWTPM_SETUP_CONF "swtpm_setup.conf"
73

74
/* Default logging goes to stderr */
75
gchar *gl_LOGFILE = NULL;
76

77
#define DEFAULT_RSA_KEYSIZE 2048
78

79
#define DEFAULT_EK1KEYALGO "rsa2048"
80
#define DEFAULT_EK2KEYALGO "ecc_nist_p384"
81

82
/* data extracted from EK certificate; */
83
struct ek_certificate_data {
84
    bool needed;  /* data are only needed if IAK and/or IDevID are created */
85
    unsigned char id[32];
86
    size_t id_len;
87
    unsigned char serial[20];
88
    size_t serial_len;
89
};
90

91
static const struct flag_to_certfile {
92
    unsigned long flag;
93
    const char *filename;
94
    const char *type;
95
} flags_to_certfiles[] = {
96
    {.flag = SETUP_EK_CERT_F      , .filename = "ek.cert",       .type = "ek" },
97
    {.flag = SETUP_PLATFORM_CERT_F, .filename = "platform.cert", .type = "platform" },
98
    {.flag = SETUP_IAK_F,           .filename = "iak.cert",      .type = "iak" },
99
    {.flag = SETUP_IDEVID_F,        .filename = "idevid.cert",   .type = "idevid" },
100
    {.flag = 0,                     .filename = NULL,            .type = NULL},
101
};
102

103
static const struct {
104
    const char *name;
105
    enum keyalgo keyalgo;
106
    unsigned int keyalgo_param;
107
} keyalgo_choices[] = {
108
    { .name = "rsa2048"      , .keyalgo = KEYALGO_RSA, .keyalgo_param = 2048 },
109
    { .name = "rsa3072"      , .keyalgo = KEYALGO_RSA, .keyalgo_param = 3072 },
110
    { .name = "rsa4096"      , .keyalgo = KEYALGO_RSA, .keyalgo_param = 4096 },
111
    { .name = "ecc_nist_p384", .keyalgo = KEYALGO_ECC, .keyalgo_param = TPM2_ECC_NIST_P384 },
112
    { .name = "secp384r1"    , .keyalgo = KEYALGO_ECC, .keyalgo_param = TPM2_ECC_NIST_P384 },
113
    { .name = "ecc_nist_p256", .keyalgo = KEYALGO_ECC, .keyalgo_param = TPM2_ECC_NIST_P256 },
114
    { .name = "secp256r1"    , .keyalgo = KEYALGO_ECC, .keyalgo_param = TPM2_ECC_NIST_P256 },
115
    { .name = "ecc_nist_p521", .keyalgo = KEYALGO_ECC, .keyalgo_param = TPM2_ECC_NIST_P521 },
116
    { .name = "secp521r1"    , .keyalgo = KEYALGO_ECC, .keyalgo_param = TPM2_ECC_NIST_P521 },
117
};
118

119
/* initialize the path of the config_file */
120
static int init(gchar **config_file)
197✔
121
{
122
    const gchar *configdir = g_get_user_config_dir();
197✔
123

124
    *config_file = g_build_filename(configdir, SWTPM_SETUP_CONF, NULL);
197✔
125
    if (access(*config_file, R_OK) != 0) {
197✔
126
        g_free(*config_file);
197✔
127
        *config_file = g_build_filename(SYSCONFDIR, SWTPM_SETUP_CONF, NULL);
197✔
128
    }
129

130
    return 0;
197✔
131
}
132

133
/* Get the spec and attributes parameters from swtpm */
134
static int tpm_get_specs_and_attributes(struct swtpm *swtpm, gchar ***params)
126✔
135
{
136
    int ret;
126✔
137
    g_autofree gchar *json = NULL;
252✔
138
    JsonParser *jp = NULL;
126✔
139
    GError *error = NULL;
126✔
140
    JsonReader *jr = NULL;
126✔
141
    JsonNode *root;
126✔
142
    static const struct parse_rule {
126✔
143
         const char *node1;
144
         const char *node2;
145
         gboolean is_int;
146
         const char *optname;
147
    } parser_rules[7] = {
148
         {"TPMSpecification", "family", FALSE, "--tpm-spec-family"},
149
         {"TPMSpecification", "level", TRUE, "--tpm-spec-level"},
150
         {"TPMSpecification", "revision", TRUE, "--tpm-spec-revision"},
151
         {"TPMAttributes", "manufacturer", FALSE, "--tpm-manufacturer"},
152
         {"TPMAttributes", "model", FALSE, "--tpm-model"},
153
         {"TPMAttributes", "version", FALSE, "--tpm-version"},
154
         {NULL, NULL, FALSE, NULL},
155
    };
156
    size_t idx;
126✔
157

158
    ret = swtpm->cops->ctrl_get_tpm_specs_and_attrs(swtpm, &json);
126✔
159
    if (ret != 0) {
126✔
160
        logerr(gl_LOGFILE, "Could not get the TPM spec and attribute parameters.\n");
×
161
        return 1;
×
162
    }
163

164
    jp = json_parser_new();
126✔
165

166
    if (!json_parser_load_from_data(jp, json, -1, &error)) {
126✔
167
        logerr(gl_LOGFILE, "JSON parser failed: %s\n", error->message);
×
168
        g_error_free(error);
×
169
        goto error;
×
170
    }
171

172
    *params = NULL;
126✔
173
    root = json_parser_get_root(jp);
126✔
174

175
    for (idx = 0; parser_rules[idx].node1 != NULL; idx++) {
1,008✔
176
        jr = json_reader_new(root);
756✔
177
        if (json_reader_read_member(jr, parser_rules[idx].node1) &&
1,512✔
178
            json_reader_read_member(jr, parser_rules[idx].node2)) {
756✔
179
            gchar *str;
756✔
180

181
            if (parser_rules[idx].is_int)
756✔
182
                str = g_strdup_printf("%ld", (long)json_reader_get_int_value(jr));
252✔
183
            else
184
                str = g_strdup(json_reader_get_string_value(jr));
504✔
185

186
            *params = concat_varrays(*params,
2,268✔
187
                                    (gchar*[]){
756✔
188
                                        g_strdup(parser_rules[idx].optname),
1,512✔
189
                                        str,
190
                                        NULL
191
                                    }, TRUE);
192
        } else {
193
            logerr(gl_LOGFILE, "Could not find [%s][%s] in '%s'\n",
×
194
                   parser_rules[idx].node1, parser_rules[idx].node2, json);
×
195
            ret = 1;
×
196
            break;
×
197
        }
198
        g_object_unref(jr);
756✔
199
        jr = NULL;
756✔
200
    }
201

202
    if (ret) {
×
203
        g_strfreev(*params);
×
204
        *params = NULL;
×
205
        g_object_unref(jr);
×
206
    }
207
error:
126✔
208
    g_object_unref(jp);
126✔
209

210
    return ret;
126✔
211
}
212

213
/* Call an external tool to create the certificates */
214
static int call_create_certs(unsigned long flags, unsigned int cert_flags,
126✔
215
                             const gchar *configfile, const gchar *certsdir,
216
                             const gchar *key_params, const gchar *vmid,
217
                             const gchar *tpm_serial_num, struct swtpm *swtpm)
218
{
219
    gchar **config_file_lines = NULL; /* must free */
126✔
220
    g_autofree gchar *create_certs_tool = NULL;
252✔
221
    g_autofree gchar *create_certs_tool_config = NULL;
126✔
222
    g_autofree gchar *create_certs_tool_options = NULL;
126✔
223
    g_autofree const gchar **cmd = NULL;
126✔
224
    gchar **params = NULL; /* must free */
126✔
225
    g_autofree gchar *prgname = NULL;
126✔
226
    const char *key_opt = "--key";
126✔
227
    gboolean success;
126✔
228
    gint exit_status;
126✔
229
    size_t idx, j;
126✔
230
    gchar *s;
126✔
231
    int ret;
126✔
232

233
    ret = tpm_get_specs_and_attributes(swtpm, &params);
126✔
234
    if (ret != 0)
126✔
235
        goto error;
×
236

237
    ret = read_file_lines(configfile, &config_file_lines);
126✔
238
    if (ret != 0)
126✔
239
        goto error;
×
240

241
    create_certs_tool = get_config_value(config_file_lines, "create_certs_tool");
126✔
242
    create_certs_tool_config = get_config_value(config_file_lines, "create_certs_tool_config");
126✔
243
    create_certs_tool_options = get_config_value(config_file_lines, "create_certs_tool_options");
126✔
244

245
    ret = 0;
126✔
246

247
    if (create_certs_tool != NULL) {
126✔
248
        g_autofree gchar *create_certs_tool_path = g_find_program_in_path(create_certs_tool);
252✔
249
        if (create_certs_tool_path == NULL) {
126✔
250
            logerr(gl_LOGFILE, "Could not find %s in PATH.\n", create_certs_tool);
×
251
            ret = 1;
×
252
            goto error;
×
253
        }
254

255
        if (flags & SETUP_TPM2_F) {
126✔
256
            params = concat_varrays(params,
236✔
257
                                (gchar*[]){
118✔
258
                                    g_strdup("--tpm2"),
118✔
259
                                    NULL
260
                                }, TRUE);
261
        }
262

263
        /* use the old --ek option when the ek is passed */
264
        if (cert_flags & (SETUP_EK_CERT_F | SETUP_PLATFORM_CERT_F))
126✔
265
            key_opt = "--ek";
112✔
266

267
        cmd = concat_arrays((const gchar*[]) {
126✔
268
                                create_certs_tool_path,
269
                                "--type", "_",  /* '_' must be at index '2' ! */
270
                                key_opt, key_params,
271
                                "--dir", certsdir,
272
                                NULL
273
                            }, NULL, FALSE);
274

275
        if (flags & SETUP_ALLOW_SIGNING_F) {
126✔
276
            cmd = concat_arrays(cmd, (const gchar*[]){"--allow-signing", NULL}, TRUE);
42✔
277
            /* once --allow-signing is passed we need to pass --decryption also */
278
            if (flags & SETUP_DECRYPTION_F)
42✔
279
                cmd = concat_arrays(cmd, (const gchar*[]){"--decryption", NULL}, TRUE);
14✔
280
        }
281
        if (gl_LOGFILE != NULL)
126✔
282
            cmd = concat_arrays(cmd, (const gchar*[]){"--logfile", gl_LOGFILE, NULL}, TRUE);
21✔
283
        if (vmid != NULL)
126✔
284
            cmd = concat_arrays(cmd, (const gchar*[]){"--vmid", vmid, NULL}, TRUE);
83✔
285
        cmd = concat_arrays(cmd, (const char **)params, TRUE);
126✔
286
        if (create_certs_tool_config != NULL)
126✔
287
            cmd = concat_arrays(cmd, (const gchar*[]){"--configfile", create_certs_tool_config, NULL}, TRUE);
21✔
288
        if (create_certs_tool_options != NULL)
126✔
289
            cmd = concat_arrays(cmd, (const gchar*[]){"--optsfile", create_certs_tool_options, NULL}, TRUE);
21✔
290
        if (tpm_serial_num) /* required for IAK & IDevID */
126✔
291
            cmd = concat_arrays(cmd, (const gchar*[]){"--tpm-serial-num", tpm_serial_num, NULL}, TRUE);
14✔
292

293
        s = g_strrstr(create_certs_tool, G_DIR_SEPARATOR_S);
126✔
294
        if (s)
126✔
295
            prgname = strdup(&s[1]);
21✔
296
        else
297
            prgname = strdup(create_certs_tool);
105✔
298

299
        for (idx = 0; flags_to_certfiles[idx].filename != NULL; idx++) {
630✔
300
            if (cert_flags & flags_to_certfiles[idx].flag) {
504✔
301
                g_autofree gchar *standard_output = NULL;
187✔
302
                g_autofree gchar *standard_error = NULL;
187✔
303
                GError *error = NULL;
187✔
304
                gchar **lines;
187✔
305

306
                cmd[2] = (gchar *)flags_to_certfiles[idx].type; /* replaces the "_" above */
187✔
307

308
                s = g_strjoinv(" ", (char **)cmd);
187✔
309
                logit(gl_LOGFILE, "  Invoking %s\n", s);
187✔
310
                g_free(s);
187✔
311

312
                success = spawn_sync(NULL, cmd, NULL, 0, NULL, NULL,
187✔
313
                                     &standard_output, &standard_error, &exit_status, &error);
314
                if (!success) {
187✔
315
                    logerr(gl_LOGFILE, "An error occurred running %s: %s\n",
×
316
                           create_certs_tool, error->message);
×
317
                    g_error_free(error);
×
318
                    ret = 1;
×
319
                    break;
×
320
                } else if (exit_status != 0) {
187✔
321
                    logerr(gl_LOGFILE, "%s exit with status %d: %s\n",
×
322
                           prgname, WEXITSTATUS(exit_status), standard_error);
×
323
                    ret = 1;
×
324
                    break;
×
325
                }
326

327
                lines = g_strsplit(standard_output, "\n", -1);
187✔
328
                for (j = 0; lines[j] != NULL; j++) {
374✔
329
                    if (strlen(lines[j]) > 0)
×
330
                        logit(gl_LOGFILE, "%s: %s\n", prgname, lines[j]);
×
331
                }
332
                g_strfreev(lines);
187✔
333

334
                SWTPM_G_FREE(standard_output);
187✔
335
                SWTPM_G_FREE(standard_error);
187✔
336
            }
337
        }
338
    }
339

340
error:
×
341
    g_strfreev(config_file_lines);
126✔
342
    g_strfreev(params);
126✔
343

344
    return ret;
126✔
345
}
346

347
static char *create_certfile_name(const gchar *user_certsdir,
21✔
348
                                  const gchar *key_type,
349
                                  const gchar *key_description)
350
{
351
    g_autofree gchar *filename = g_strdup_printf("%s-%s.crt", key_type, key_description);
21✔
352

353
    return g_strjoin(G_DIR_SEPARATOR_S, user_certsdir, filename, NULL);
21✔
354
}
355

356
/*
357
 * Remove the cert file unless the user wants a copy of it.
358
 */
359
static int certfile_move_or_delete(unsigned long flags, gboolean preserve, const gchar *certfile,
187✔
360
                                   const gchar *user_certsdir, const gchar *key_type,
361
                                   const gchar *key_description)
362
{
363
    g_autofree gchar *content = NULL;
374✔
364
    g_autofree gchar *cf = NULL;
187✔
365
    gsize content_length;
187✔
366
    GError *error = NULL;
187✔
367
    size_t offset = 0;
187✔
368

369
    if (preserve && (flags & SETUP_WRITE_EK_CERT_FILES_F) && user_certsdir != NULL) {
187✔
370
        if (!g_file_get_contents(certfile, &content, &content_length, &error))
21✔
371
            goto error;
×
372

373
        cf = create_certfile_name(user_certsdir, key_type, key_description);
21✔
374
        if (!(flags & SETUP_TPM2_F)) {
21✔
375
            /* A TPM 1.2 certificate has a 7 byte header at the beginning
376
             * that we now remove */
377
            if (content_length >= 8)
1✔
378
                offset = 7;
21✔
379
        }
380
        if (!g_file_set_contents(cf, &content[offset], content_length - offset,
21✔
381
                                 &error))
382
            goto error;
×
383
        if (g_chmod(cf, S_IRUSR | S_IWUSR | S_IRGRP) < 0) {
21✔
384
            logerr(gl_LOGFILE, "Failed to chmod file '%s': %s\n", cf, strerror(errno));
×
385
            goto error_unlink;
×
386
        }
387
    }
388
    unlink(certfile);
187✔
389

390
    return 0;
187✔
391

392
error:
×
393
    logerr(gl_LOGFILE, "%s\n", error->message);
×
394
    g_error_free(error);
×
395

396
error_unlink:
×
397
    unlink(certfile);
×
398

399
    return 1;
×
400
}
401

402
static int read_certificate_file(const gchar *certsdir, const gchar *filename,
187✔
403
                                 gchar **filecontent, gsize *filecontent_len,
404
                                 gchar **certfile)
405
{
406
    *certfile = g_strjoin(G_DIR_SEPARATOR_S, certsdir, filename, NULL);
187✔
407

408
    return read_file(*certfile, filecontent, filecontent_len);
187✔
409
}
410

411
static int tpm2_extract_certificate_data(const gchar *certdata, size_t certdata_len,
54✔
412
                                         struct ek_certificate_data *ecd)
413
{
414
    const ASN1_OCTET_STRING *os;
54✔
415
    const ASN1_INTEGER *serial;
54✔
416
    X509 *cert = NULL;
54✔
417
    BIGNUM *bn = NULL;
54✔
418
    BIO *bio = NULL;
54✔
419
    int ret = 1;
54✔
420

421
    if (!ecd->needed)
54✔
422
        return 0;
423

424
    cert = d2i_X509(NULL, (const unsigned char **)&certdata, certdata_len);
7✔
425
    if (!cert) {
7✔
426
        fprintf(stderr, "Could not convert byte array to certificate.\n");
×
427
        goto cleanup;
×
428
    }
429

430
    os = X509_get0_authority_key_id(cert);
7✔
431
    if (os == NULL) {
7✔
432
        fprintf(stderr, "The certificate does not have an AKID.\n");
×
433
        goto cleanup;
×
434
    }
435

436
    ecd->id_len = min((size_t)ASN1_STRING_length(os), sizeof(ecd->id));
7✔
437
    memcpy(ecd->id, ASN1_STRING_get0_data(os), ecd->id_len);
7✔
438

439
    serial = X509_get0_serialNumber(cert);
7✔
440
    if (!serial) {
7✔
441
        fprintf(stderr, "Could not get serial number from certificate.\n");
×
442
        goto cleanup;
×
443
    }
444
    bn = ASN1_INTEGER_to_BN(serial, NULL);
7✔
445
    if (!bn) {
7✔
446
        fprintf(stderr, "Out of memory.\n");
×
447
        goto cleanup;
×
448
    }
449
    if ((size_t)BN_num_bytes(bn) > sizeof(ecd->serial)) {
7✔
450
        fprintf(stderr, "The serial number is too large for the buffer.\n");
×
451
        goto cleanup;
×
452
    }
453
    ecd->serial_len = BN_bn2bin(bn, ecd->serial);
7✔
454

455
    ret = 0;
7✔
456

457
cleanup:
7✔
458
    BN_free(bn);
7✔
459
    X509_free(cert);
7✔
460
    BIO_free(bio);
7✔
461

462
    return ret;
7✔
463
}
464

465
/*
466
 * Read the certificate from the file where swtpm_cert left it.
467
 * Write the file into the TPM's NVRAM and, if the user wants it,
468
 * copy it into a user-provided directory.
469
 */
470
static int tpm2_persist_certificate(unsigned long flags, const gchar *certsdir,
172✔
471
                                    const struct flag_to_certfile *ftc,
472
                                    enum keyalgo keyalgo, unsigned int keyalgo_param,
473
                                    struct swtpm2 *swtpm2, const gchar *user_certsdir,
474
                                    const gchar *key_type, const gchar *key_description,
475
                                    struct ek_certificate_data *ecd)
476
{
477
    g_autofree gchar *filecontent = NULL;
344✔
478
    g_autofree gchar *certfile = NULL;
172✔
479
    gsize filecontent_len;
172✔
480
    gboolean preserve;
172✔
481
    int ret;
172✔
482

483
    ret = read_certificate_file(certsdir, ftc->filename,
172✔
484
                                &filecontent, &filecontent_len, &certfile);
485
    if (ret != 0)
172✔
486
        goto error_unlink;
×
487

488
    if (ecd) {
172✔
489
        ret = tpm2_extract_certificate_data(filecontent, filecontent_len, ecd);
54✔
490
        if (ret != 0)
54✔
491
            goto error_unlink;
×
492
    }
493

494
    if (ftc->flag == SETUP_IAK_F) {
172✔
495
        ret = swtpm2->ops->write_iak_cert_nvram(&swtpm2->swtpm,
7✔
496
                                     !!(flags & SETUP_LOCK_NVRAM_F),
7✔
497
                                     (const unsigned char*)filecontent, filecontent_len);
498
    } else if (ftc->flag == SETUP_IDEVID_F) {
165✔
499
        ret = swtpm2->ops->write_idevid_cert_nvram(&swtpm2->swtpm,
7✔
500
                                     !!(flags & SETUP_LOCK_NVRAM_F),
7✔
501
                                     (const unsigned char *)filecontent, filecontent_len);
502
    } else if (ftc->flag == SETUP_EK_CERT_F) {
158✔
503
        ret = swtpm2->ops->write_ek_cert_nvram(&swtpm2->swtpm,
104✔
504
                                     keyalgo, keyalgo_param,
505
                                     !!(flags & SETUP_LOCK_NVRAM_F),
104✔
506
                                     (const unsigned char*)filecontent, filecontent_len);
507
    } else {
508
        ret = swtpm2->ops->write_platform_cert_nvram(&swtpm2->swtpm,
54✔
509
                                     !!(flags & SETUP_LOCK_NVRAM_F),
54✔
510
                                     (const unsigned char *)filecontent, filecontent_len);
511
    }
512

513
    if (ret != 0)
172✔
514
        goto error_unlink;
×
515

516
    preserve = !!(ftc->flag & (SETUP_EK_CERT_F | SETUP_IAK_F | SETUP_IDEVID_F));
172✔
517

518
    return certfile_move_or_delete(flags, preserve,
172✔
519
                                   certfile, user_certsdir,
520
                                   key_type, key_description);
521

522
error_unlink:
×
523
    unlink(certfile);
×
524
    return 1;
×
525
}
526

527
/* Create EK and certificate for a TPM 2 */
528
static int tpm2_create_ek_and_cert(unsigned long flags, const gchar *config_file,
250✔
529
                                   const gchar *certsdir, const gchar *vmid,
530
                                   enum keyalgo keyalgo, unsigned int keyalgo_param,
531
                                   struct swtpm2 *swtpm2, const gchar *user_certsdir,
532
                                   struct ek_certificate_data *ecd)
533
{
534
    g_autofree gchar *key_params = NULL;
500✔
535
    struct ek_certificate_data *ecd_dup;
250✔
536
    const char *key_description = "";
250✔
537
    unsigned long cert_flags;
250✔
538
    const gchar *key_type;
250✔
539
    size_t idx;
250✔
540
    int ret;
250✔
541

542
    if (flags & SETUP_CREATE_EK_F) {
250✔
543
        ret = swtpm2->ops->create_ek(&swtpm2->swtpm, keyalgo, keyalgo_param,
236✔
544
                                     !!(flags & SETUP_ALLOW_SIGNING_F),
118✔
545
                                     !!(flags & SETUP_DECRYPTION_F),
118✔
546
                                     !!(flags & SETUP_LOCK_NVRAM_F),
118✔
547
                                     &key_params, &key_description);
548
        if (ret != 0)
118✔
549
            return 1;
550
    }
551

552
    /* Only look at ek and platform certs here */
553
    cert_flags = flags & (SETUP_EK_CERT_F | SETUP_PLATFORM_CERT_F);
250✔
554
    if (cert_flags) {
250✔
555
        ret = call_create_certs(flags, cert_flags, config_file, certsdir, key_params,
104✔
556
                                vmid, NULL, &swtpm2->swtpm);
557
        if (ret != 0)
104✔
558
            return 1;
559

560
        for (idx = 0; flags_to_certfiles[idx].filename; idx++) {
520✔
561
            if (cert_flags & flags_to_certfiles[idx].flag) {
416✔
562

563
                ecd_dup = NULL;
158✔
564
                if (flags_to_certfiles[idx].flag & SETUP_EK_CERT_F) {
158✔
565
                    key_type = "ek";
566
                    ecd_dup = ecd;
567
                } else {
568
                    key_type = "";
54✔
569
                }
570

571
                ret = tpm2_persist_certificate(flags, certsdir, &flags_to_certfiles[idx],
158✔
572
                                               keyalgo, keyalgo_param, swtpm2,
573
                                               user_certsdir, key_type, key_description,
574
                                               ecd_dup);
575
                if (ret)
158✔
576
                    return 1;
577
            }
578
        }
579
    }
580

581
    return 0;
582
}
583

584
/* Create endorsement keys and certificates for a TPM 2 */
585
static int tpm2_create_eks_and_certs(unsigned long flags, const gchar *config_file,
127✔
586
                                     const gchar *certsdir, const gchar *vmid,
587
                                     enum keyalgo ek1keyalgo, unsigned int ek1keyalgo_param,
588
                                     enum keyalgo ek2keyalgo, unsigned int ek2keyalgo_param,
589
                                     struct swtpm2 *swtpm2, const gchar *user_certsdir,
590
                                     struct ek_certificate_data *ecd)
591
{
592
     int ret;
127✔
593

594
     ret = tpm2_create_ek_and_cert(flags, config_file, certsdir, vmid, ek1keyalgo,
127✔
595
                                   ek1keyalgo_param, swtpm2, user_certsdir, ecd);
596
     if (ret != 0)
127✔
597
         return 1;
598

599
     /* two keys the same -- create only one */
600
     if (ek1keyalgo_param == ek2keyalgo_param && ek1keyalgo == ek2keyalgo)
127✔
601
         return 0;
602

603
     /* platform cert only with EK1 */
604
     flags &= ~SETUP_PLATFORM_CERT_F;
123✔
605
     return tpm2_create_ek_and_cert(flags, config_file, certsdir, vmid, ek2keyalgo,
123✔
606
                                    ek2keyalgo_param, swtpm2, user_certsdir, NULL);
607
}
608

609
static gchar *tpm2_create_tpm_serial_num(struct swtpm2 *swtpm2, const struct ek_certificate_data *ecd)
7✔
610
{
611
    struct swtpm *swtpm = &swtpm2->swtpm;
7✔
612
    g_autofree gchar *cert_ser = NULL;
14✔
613
    g_autofree gchar *ca_akid = NULL;
7✔
614
    uint32_t res;
7✔
615
    char code[sizeof(res) + 1];
7✔
616
    size_t i;
7✔
617
    int ret;
7✔
618

619
    ret = swtpm2->ops->get_capability(swtpm, TPM2_CAP_TPM_PROPERTIES,
7✔
620
                                      TPM2_PT_MANUFACTURER, &res);
621
    if (ret != 0) {
7✔
622
        logerr(gl_LOGFILE, "TPM_GetCapability failed\n");
×
623
        return NULL;
×
624
    }
625

626
    ca_akid = print_as_hex(ecd->id, ecd->id_len);
7✔
627
    cert_ser = print_as_hex(ecd->serial, ecd->serial_len);
7✔
628
    for (i = 0; i < sizeof(res); i++)
42✔
629
        code[i] = res >> (8 * (3 - i));
28✔
630
    code[4] = 0;
7✔
631

632
    return g_strdup_printf("%s:%s:%s", code, ca_akid, cert_ser);
7✔
633
}
634

635
/* Create the IAK and cert */
636
static int tpm2_create_iak_idevid_and_certs(unsigned long flags, const gchar *config_file,
127✔
637
                                            const gchar *certsdir, const char *vmid,
638
                                            enum keyalgo iakkeyalgo, unsigned int iakkeyalgo_param,
639
                                            enum keyalgo idevidkeyalgo, unsigned int idevidkeyalgo_param,
640
                                            struct swtpm2 *swtpm2, const gchar *user_certsdir,
641
                                            const struct ek_certificate_data *ecd)
642
{
643
    g_autofree gchar *tpm_serial_num = NULL;
254✔
644
    g_autofree gchar *key_params = NULL;
127✔
645
    const char *key_description;
127✔
646
    const char *key_type = NULL;
127✔
647
    unsigned long cert_flags = 0;
127✔
648
    unsigned int keyalgo_param;
127✔
649
    enum keyalgo keyalgo;
127✔
650
    size_t idx;
127✔
651
    int ret;
127✔
652

653
    /* Only look at IAK and IDevID certs here */
654
    if (iakkeyalgo != KEYALGO_NONE)
127✔
655
        cert_flags |= SETUP_IAK_F;
7✔
656
    if (idevidkeyalgo != KEYALGO_NONE)
127✔
657
        cert_flags |= SETUP_IDEVID_F;
7✔
658

659
    if (!cert_flags)
127✔
660
        return 0;
661

662
    tpm_serial_num = tpm2_create_tpm_serial_num(swtpm2, ecd);
7✔
663

664
    for (idx = 0; flags_to_certfiles[idx].filename; idx++) {
42✔
665
        if (cert_flags & flags_to_certfiles[idx].flag) {
28✔
666

667
            SWTPM_G_FREE(key_params);
14✔
668

669
            if (flags_to_certfiles[idx].flag == SETUP_IAK_F) {
14✔
670
                key_type = "iak";
7✔
671
                keyalgo = iakkeyalgo;
7✔
672
                keyalgo_param = iakkeyalgo_param;
7✔
673
                ret = swtpm2->ops->create_iak(&swtpm2->swtpm,
7✔
674
                                              keyalgo, keyalgo_param,
675
                                              &key_params, &key_description);
676
            } else if (flags_to_certfiles[idx].flag == SETUP_IDEVID_F) {
7✔
677
                key_type = "idevid";
7✔
678
                keyalgo = idevidkeyalgo;
7✔
679
                keyalgo_param = idevidkeyalgo_param;
7✔
680
                ret = swtpm2->ops->create_idevid(&swtpm2->swtpm,
7✔
681
                                                 keyalgo, keyalgo_param,
682
                                                 &key_params, &key_description);
683
            } else {
684
                continue;
×
685
            }
686
            if (ret != 0)
14✔
687
                return 1;
688

689
            ret = call_create_certs(flags, flags_to_certfiles[idx].flag, config_file,
14✔
690
                                    certsdir, key_params, vmid, tpm_serial_num,
691
                                    &swtpm2->swtpm);
692
            if (ret != 0)
14✔
693
                return 1;
694

695
            ret = tpm2_persist_certificate(flags, certsdir, &flags_to_certfiles[idx],
14✔
696
                                           keyalgo, keyalgo_param, swtpm2,
697
                                           user_certsdir, key_type, key_description, NULL);
698
            if (ret)
14✔
699
                return 1;
700
        }
701
    }
702

703
    return 0;
704
}
705

706
/* Get the default PCR banks from the config file and if nothing can
707
   be found there use the DEFAULT_PCR_BANKS #define.
708
 */
709
static gchar *get_default_pcr_banks(gchar *const *config_file_lines)
159✔
710
{
711
    gchar *pcr_banks;
159✔
712

713
    pcr_banks = get_config_value(config_file_lines, "active_pcr_banks");
159✔
714
    if (pcr_banks)
159✔
715
        g_strstrip(pcr_banks);
27✔
716
    if (pcr_banks == NULL || strlen(pcr_banks) == 0) {
27✔
717
        g_free(pcr_banks);
132✔
718
        pcr_banks = g_strdup(DEFAULT_PCR_BANKS);
132✔
719
    }
720
    return pcr_banks;
159✔
721
}
722

723
/* Get the default RSA keysize from the config file */
724
static gchar *get_default_rsa_keysize(gchar *const *config_file_lines)
105✔
725
{
726
    gchar *rsa_keysize;
105✔
727

728
    rsa_keysize = get_config_value(config_file_lines, "rsa_keysize");
105✔
729
    if (rsa_keysize)
105✔
730
        g_strstrip(rsa_keysize);
6✔
731
    if (rsa_keysize == NULL || strlen(rsa_keysize) == 0) {
6✔
732
        g_free(rsa_keysize);
99✔
733
        rsa_keysize = g_strdup_printf("%d", DEFAULT_RSA_KEYSIZE);
99✔
734
    }
735
    return rsa_keysize;
105✔
736
}
737

738
/* Get the default profile from the config file */
739
static gchar *get_default_profile(gchar *const *config_file_lines)
46✔
740
{
741
    gchar *profile;
46✔
742

743
    profile = get_config_value(config_file_lines, "profile");
46✔
744
    if (profile)
46✔
745
        g_strstrip(profile);
16✔
746
    return profile;
46✔
747
}
748

749
/* If available, open the default profile and return its file descriptor */
750
static int get_default_profile_fd(gchar *const *config_file_lines)
46✔
751
{
752
    g_autofree gchar *profile_file = NULL;
92✔
753
    int fd;
46✔
754

755
    profile_file = get_config_value(config_file_lines, "profile_file");
46✔
756
    if (!profile_file)
46✔
757
        return -1;
758

759
    fd = open(profile_file, O_RDONLY);
×
760
    if (fd < 0) {
×
761
        logerr(gl_LOGFILE, "Could not read default profile '%s': %s",
×
762
               profile_file, strerror(errno));
×
763
        return -2;
×
764
    }
765
    return fd;
766
}
767

768
/* Activate the given list of PCR banks. If pcr_banks is '-' then leave
769
 * the configuration as-is.
770
 */
771
static int tpm2_activate_pcr_banks(struct swtpm2 *swtpm2,
133✔
772
                                   const gchar *pcr_banks)
773
{
774
    g_autofree gchar *active_pcr_banks_join = NULL;
266✔
775
    g_autofree gchar *all_pcr_banks_join = NULL;
133✔
776
    g_auto(GStrv) active_pcr_banks = NULL;
133✔
777
    g_auto(GStrv) all_pcr_banks = NULL;
133✔
778
    g_auto(GStrv) pcr_banks_l = NULL;
133✔
779
    struct swtpm *swtpm = &swtpm2->swtpm;
133✔
780
    int ret = 0;
133✔
781

782
    if (g_str_equal(pcr_banks, "-"))
133✔
783
        return 0;
784

785
    ret = swtpm2->ops->get_all_pcr_banks(swtpm, &all_pcr_banks);
133✔
786
    if (ret != 0)
133✔
787
        return ret;
788

789
    pcr_banks_l = g_strsplit(pcr_banks, ",", -1);
133✔
790
    ret = swtpm2->ops->set_active_pcr_banks(swtpm, pcr_banks_l, all_pcr_banks,
133✔
791
                                            &active_pcr_banks);
792
    if (ret != 0)
133✔
793
        return ret;
794

795
    active_pcr_banks_join = g_strjoinv(",", active_pcr_banks);
132✔
796
    all_pcr_banks_join = g_strjoinv(",", all_pcr_banks);
132✔
797
    logit(gl_LOGFILE, "Successfully activated PCR banks %s among %s.\n",
132✔
798
          active_pcr_banks_join, all_pcr_banks_join);
799

800
    return 0;
132✔
801
}
802

803
static int log_active_profile(struct swtpm2 *swtpm2)
134✔
804
{
805
    g_autofree gchar *profile = NULL;
268✔
806
    char *tmp;
134✔
807

808
    profile = swtpm2->ops->get_active_profile(&swtpm2->swtpm);
134✔
809
    if (!profile) {
134✔
810
        logerr(gl_LOGFILE, "Could not get active profile.\n");
7✔
811
        return 1;
7✔
812
    }
813
    /* Strip out surrounding '{"ActiveProfile":<to display>} */
814
    tmp = strrchr(profile, '}');
127✔
815
    if (!tmp)
127✔
816
        goto malformatted;
×
817
    *tmp = 0;
127✔
818

819
    tmp = strchr(profile, ':');
127✔
820
    if (!tmp)
127✔
821
        goto malformatted;
×
822

823
    logit(gl_LOGFILE, "Active profile: %s\n", tmp + 1);
127✔
824
    return 0;
127✔
825

826
malformatted:
×
827
    logerr(gl_LOGFILE, "Malformatted active profile");
×
828
    return 1;
×
829
}
830

831
/* Simulate manufacturing a TPM 2: create keys and certificates */
832
static int init_tpm2(unsigned long flags, gchar **swtpm_prg_l, const gchar *config_file,
140✔
833
                     const gchar *tpm2_state_path, const gchar *vmid, const gchar *pcr_banks,
834
                     const gchar *swtpm_keyopt, int *fds_to_pass, size_t n_fds_to_pass,
835
                     enum keyalgo ek1keyalgo, unsigned int ek1keyalgo_param,
836
                     enum keyalgo ek2keyalgo, unsigned int ek2keyalgo_param,
837
                     enum keyalgo iakkeyalgo, unsigned int iakkeyalgo_param,
838
                     enum keyalgo idevidkeyalgo, unsigned int idevidkeyalgo_param,
839
                     const gchar *certsdir, const gchar *user_certsdir,
840
                     const gchar *json_profile,
841
                     int json_profile_fd, const gchar *profile_remove_disabled_param)
842
{
843
    struct ek_certificate_data ecd = {
140✔
844
        .needed = iakkeyalgo != KEYALGO_NONE || idevidkeyalgo != KEYALGO_NONE,
140✔
845
    };
846
    unsigned int keyalgo_param;
140✔
847
    struct swtpm2 *swtpm2;
140✔
848
    enum keyalgo keyalgo;
140✔
849
    struct swtpm *swtpm;
140✔
850
    int ret;
140✔
851

852
    swtpm2 = swtpm2_new(swtpm_prg_l, tpm2_state_path, swtpm_keyopt, gl_LOGFILE,
140✔
853
                        fds_to_pass, n_fds_to_pass, json_profile, json_profile_fd,
854
                        profile_remove_disabled_param);
855
    if (swtpm2 == NULL)
140✔
856
        return 1;
857
    swtpm = &swtpm2->swtpm;
140✔
858

859
    ret = swtpm->cops->start(swtpm);
140✔
860
    if (ret != 0) {
140✔
UNCOV
861
        logerr(gl_LOGFILE, "Could not start the TPM 2.\n");
×
UNCOV
862
        goto error;
×
863
    }
864

865
    if (!(flags & SETUP_RECONFIGURE_F)) {
140✔
866
        ret = log_active_profile(swtpm2);
134✔
867
        if (ret)
134✔
868
            goto error;
7✔
869

870
        if ((flags & SETUP_CREATE_SPK_F)) {
127✔
871
            if ((flags & SETUP_TPM2_ECC_F)) {
16✔
872
                keyalgo = KEYALGO_ECC;
873
                keyalgo_param = TPM2_ECC_NIST_P384;
874
            } else {
875
                keyalgo = KEYALGO_RSA;
10✔
876
                keyalgo_param = 3072;
10✔
877
            }
878
            ret = swtpm2->ops->create_spk(swtpm, keyalgo, keyalgo_param);
16✔
879
            if (ret != 0)
16✔
880
                goto destroy;
×
881
        }
882

883
        ret = tpm2_create_eks_and_certs(flags, config_file, certsdir, vmid,
127✔
884
                                        ek1keyalgo, ek1keyalgo_param,
885
                                        ek2keyalgo, ek2keyalgo_param,
886
                                        swtpm2, user_certsdir, &ecd);
887
        if (ret != 0)
127✔
888
            goto destroy;
×
889

890
        ret = tpm2_create_iak_idevid_and_certs(flags, config_file, certsdir, vmid,
127✔
891
                                               iakkeyalgo, iakkeyalgo_param,
892
                                               idevidkeyalgo, idevidkeyalgo_param,
893
                                               swtpm2, user_certsdir, &ecd);
894
        if (ret != 0)
127✔
895
            goto destroy;
×
896
    }
897

898
    ret = tpm2_activate_pcr_banks(swtpm2, pcr_banks);
133✔
899
    if (ret != 0)
133✔
900
        goto destroy;
1✔
901

902
    ret = swtpm2->ops->shutdown(swtpm);
132✔
903

904
destroy:
133✔
905
    swtpm->cops->destroy(swtpm);
133✔
906

907
error:
140✔
908
    swtpm_free(swtpm);
140✔
909

910
    return ret;
140✔
911
}
912

913
/* Create the owner password digest */
914
static void tpm12_get_ownerpass_digest(unsigned long flags, const gchar *ownerpass,
9✔
915
                                       unsigned char ownerpass_digest[SHA_DIGEST_LENGTH])
916
{
917
    const gchar zeros[SHA_DIGEST_LENGTH]= {0, };
9✔
918
    size_t len;
9✔
919

920
    if (ownerpass == NULL) {
9✔
921
        if (flags & SETUP_OWNERPASS_ZEROS_F) {
2✔
922
            ownerpass = zeros;
923
            len = sizeof(zeros);
924
        } else {
925
            ownerpass = DEFAULT_OWNER_PASSWORD;
×
926
            len = strlen(ownerpass);
×
927
        }
928
    } else {
929
        len = strlen(ownerpass);
7✔
930
    }
931
    SHA1((const unsigned char *)ownerpass, len, ownerpass_digest);
9✔
932
}
9✔
933

934
/* Create the SRK password digest */
935
static void tpm12_get_srkpass_digest(unsigned long flags, const gchar *srkpass,
9✔
936
                                     unsigned char srkpass_digest[SHA_DIGEST_LENGTH])
937
{
938
    const gchar zeros[SHA_DIGEST_LENGTH]= {0, };
9✔
939
    size_t len;
9✔
940

941
    if (srkpass == NULL) {
9✔
942
        if (flags & SETUP_SRKPASS_ZEROS_F) {
2✔
943
            srkpass = zeros;
944
            len = sizeof(zeros);
945
        } else {
946
            srkpass = DEFAULT_SRK_PASSWORD;
×
947
            len = strlen(srkpass);
×
948
        }
949
    } else {
950
        len = strlen(srkpass);
7✔
951
    }
952
    SHA1((const unsigned char *)srkpass, len, srkpass_digest);
9✔
953
}
9✔
954

955
/* Take ownership of a TPM 1.2 */
956
static int tpm12_take_ownership(unsigned long flags, const gchar *ownerpass,
9✔
957
                                const gchar *srkpass, gchar *pubek, size_t pubek_len,
958
                                struct swtpm12 *swtpm12)
959
{
960
    unsigned char ownerpass_digest[SHA_DIGEST_LENGTH];
9✔
961
    unsigned char srkpass_digest[SHA_DIGEST_LENGTH];
9✔
962

963
    tpm12_get_ownerpass_digest(flags, ownerpass, ownerpass_digest);
9✔
964
    tpm12_get_srkpass_digest(flags, srkpass, srkpass_digest);
9✔
965

966
    return swtpm12->ops->take_ownership(&swtpm12->swtpm, ownerpass_digest, srkpass_digest,
9✔
967
                                        (const unsigned char *)pubek, pubek_len);
968
}
969

970
/* Create the certificates for a TPM 1.2 */
971
static int tpm12_create_certs(unsigned long flags, const gchar *config_file,
8✔
972
                              const gchar *certsdir, const gchar *ekparam,
973
                              const gchar *vmid, struct swtpm12 *swtpm12,
974
                              const gchar *user_certsdir)
975
{
976
    g_autofree gchar *filecontent = NULL;
16✔
977
    g_autofree gchar *certfile = NULL;
8✔
978
    unsigned int cert_flags;
8✔
979
    const gchar *key_type;
8✔
980
    gsize filecontent_len;
8✔
981
    size_t idx;
8✔
982
    int ret;
8✔
983

984
    /* TPM 1.2 only has ek and platform certs */
985
    cert_flags = flags & (SETUP_EK_CERT_F | SETUP_PLATFORM_CERT_F);
8✔
986

987
    ret = call_create_certs(flags, cert_flags, config_file, certsdir, ekparam,
8✔
988
                            vmid, NULL, &swtpm12->swtpm);
989
    if (ret != 0)
8✔
990
        return 1;
991

992
    for (idx = 0; flags_to_certfiles[idx].filename; idx++) {
40✔
993
        if (cert_flags & flags_to_certfiles[idx].flag) {
32✔
994
            SWTPM_G_FREE(filecontent);
15✔
995
            SWTPM_G_FREE(certfile);
15✔
996

997
            ret = read_certificate_file(certsdir, flags_to_certfiles[idx].filename,
15✔
998
                                        &filecontent, &filecontent_len, &certfile);
999
            if (ret != 0)
15✔
1000
                return 1;
1001

1002
            if (flags_to_certfiles[idx].flag == SETUP_EK_CERT_F) {
15✔
1003
                ret = swtpm12->ops->write_ek_cert_nvram(&swtpm12->swtpm,
8✔
1004
                                                (const unsigned char*)filecontent, filecontent_len);
1005
                if (ret == 0)
8✔
1006
                    logit(gl_LOGFILE, "Successfully created NVRAM area for EK certificate.\n");
8✔
1007
            } else {
1008
                ret = swtpm12->ops->write_platform_cert_nvram(&swtpm12->swtpm,
7✔
1009
                                                  (const unsigned char*)filecontent, filecontent_len);
1010
                if (ret == 0)
7✔
1011
                    logit(gl_LOGFILE, "Successfully created NVRAM area for Platform certificate.\n");
7✔
1012
            }
1013

1014
            if (ret != 0) {
15✔
1015
                unlink(certfile);
×
1016
                return 1;
×
1017
            }
1018

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

1021
            if (certfile_move_or_delete(flags, !!(flags_to_certfiles[idx].flag & SETUP_EK_CERT_F),
15✔
1022
                                        certfile, user_certsdir, key_type, "rsa2048") != 0)
1023
                return 1;
1024
        }
1025
    }
1026

1027
    return 0;
1028
}
1029

1030
/* Simulate manufacturing a TPM 1.2: create keys and certificate and possibly take ownership */
1031
static int init_tpm(unsigned long flags, gchar **swtpm_prg_l, const gchar *config_file,
26✔
1032
                    const gchar *tpm_state_path, const gchar *ownerpass, const gchar *srkpass,
1033
                    const gchar *vmid, const gchar *swtpm_keyopt,
1034
                    int *fds_to_pass, size_t n_fds_to_pass, const gchar *certsdir,
1035
                    const gchar *user_certsdir)
1036
{
1037
    struct swtpm12 *swtpm12;
26✔
1038
    struct swtpm *swtpm;
26✔
1039
    g_autofree gchar *pubek = NULL;
52✔
1040
    size_t pubek_len = 0;
26✔
1041
    int ret = 1;
26✔
1042

1043
    swtpm12 = swtpm12_new(swtpm_prg_l, tpm_state_path, swtpm_keyopt, gl_LOGFILE,
26✔
1044
                          fds_to_pass, n_fds_to_pass);
1045
    if (swtpm12 == NULL)
26✔
1046
        return 1;
1047
    swtpm = &swtpm12->swtpm;
26✔
1048

1049
    ret = swtpm->cops->start(swtpm);
26✔
1050
    if (ret != 0) {
26✔
1051
        logerr(gl_LOGFILE, "Could not start the TPM 1.2.\n");
×
1052
        goto error;
×
1053
    }
1054

1055
    ret = swtpm12->ops->run_swtpm_bios(swtpm);
26✔
1056
    if (ret != 0)
26✔
1057
         goto destroy;
×
1058

1059
    if ((flags & SETUP_CREATE_EK_F)) {
26✔
1060
        ret = swtpm12->ops->create_endorsement_key_pair(swtpm, &pubek, &pubek_len);
19✔
1061
        if (ret != 0)
19✔
1062
            goto destroy;
×
1063

1064
        logit(gl_LOGFILE, "Successfully created EK.\n");
19✔
1065

1066
        /* can only take owernship if created an EK */
1067
        if ((flags & SETUP_TAKEOWN_F)) {
19✔
1068
            ret = tpm12_take_ownership(flags, ownerpass, srkpass, pubek, pubek_len, swtpm12);
9✔
1069
            if (ret != 0)
9✔
1070
                goto destroy;
×
1071

1072
            logit(gl_LOGFILE, "Successfully took ownership of the TPM.\n");
9✔
1073
        }
1074

1075
        /* can only create EK cert if created an EK */
1076
        if ((flags & SETUP_EK_CERT_F)) {
19✔
1077
            g_autofree gchar *ekparam = print_as_hex((unsigned char *)pubek, pubek_len);
16✔
1078

1079
            ret = tpm12_create_certs(flags, config_file, certsdir, ekparam, vmid, swtpm12,
8✔
1080
                                     user_certsdir);
1081
            if (ret != 0)
8✔
1082
                goto destroy;
×
1083
        }
1084
    }
1085

1086
    if ((flags & SETUP_LOCK_NVRAM_F)) {
26✔
1087
        ret = swtpm12->ops->nv_lock(swtpm);
12✔
1088
        if (ret == 0)
12✔
1089
            logit(gl_LOGFILE, "Successfully locked NVRAM access.\n");
12✔
1090
    }
1091

1092
destroy:
14✔
1093
    swtpm->cops->destroy(swtpm);
26✔
1094

1095
error:
26✔
1096
    swtpm_free(swtpm);
26✔
1097

1098
    return ret;
26✔
1099
}
1100

1101
/* Check whether we are allowed to overwrite existing state.
1102
 * This function returns 2 if the state exists but flag is set to not to overwrite it,
1103
 * 0 in case we can overwrite it, 1 if the state exists.
1104
 */
1105
static int check_state_overwrite(const gchar **swtpm_prg_l, unsigned int flags,
166✔
1106
                                 const char *tpm_state_path)
1107
{
1108
    gboolean success;
166✔
1109
    g_autofree gchar *standard_output = NULL;
332✔
1110
    int exit_status = 0;
166✔
1111
    g_autoptr(GError) error = NULL;
166✔
1112
    g_autofree const gchar **argv = NULL;
166✔
1113
    g_autofree gchar *statearg = g_strdup_printf("backend-uri=%s", tpm_state_path);
332✔
1114
    g_autofree gchar *logop = NULL;
166✔
1115
    g_autofree const gchar **my_argv = NULL;
166✔
1116

1117
    my_argv = concat_arrays((const gchar*[]) {
166✔
1118
                                "--print-states",
1119
                                "--tpmstate",
1120
                                statearg,
1121
                                NULL
1122
                            }, NULL, FALSE);
1123

1124
    if (flags & SETUP_TPM2_F)
166✔
1125
        my_argv = concat_arrays(my_argv, (const gchar*[]) { "--tpm2", NULL }, TRUE);
137✔
1126

1127
    if (gl_LOGFILE != NULL) {
166✔
1128
        logop = g_strdup_printf("file=%s", gl_LOGFILE);
90✔
1129
        my_argv = concat_arrays(my_argv, (const gchar*[]){"--log", logop, NULL}, TRUE);
90✔
1130
    }
1131

1132
    argv = concat_arrays(swtpm_prg_l, my_argv, FALSE);
166✔
1133

1134
    success = spawn_sync(NULL, argv, NULL, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL,
166✔
1135
                         &standard_output, NULL, &exit_status, &error);
1136
    if (!success) {
166✔
1137
        logerr(gl_LOGFILE, "Could not start swtpm '%s': %s\n", swtpm_prg_l[0], error->message);
×
1138
        return 1;
×
1139
    }
1140

1141
    if (exit_status != 0) {
166✔
1142
        logerr(gl_LOGFILE, "%s exit with status %d: %s\n",
×
1143
               swtpm_prg_l[0], exit_status, standard_output);
1144
        return 1;
×
1145
    }
1146

1147
    if (g_strstr_len(standard_output, -1, TPM_PERMANENT_ALL_NAME) != NULL) {
166✔
1148
        /* State file exists */
1149
        if (flags & SETUP_STATE_NOT_OVERWRITE_F) {
77✔
1150
            logit(gl_LOGFILE, "Not overwriting existing state file.\n");
2✔
1151
            return 2;
2✔
1152
        }
1153
        if (flags & SETUP_STATE_OVERWRITE_F)
75✔
1154
            return 0;
1155
        logerr(gl_LOGFILE, "Found existing TPM state '%s'.\n", TPM_PERMANENT_ALL_NAME);
3✔
1156
        return 1;
3✔
1157
    }
1158

1159
    return 0;
1160
}
1161

1162
static void versioninfo(void)
2✔
1163
{
1164
    printf("TPM emulator setup tool version %d.%d.%d\n",
2✔
1165
           SWTPM_VER_MAJOR, SWTPM_VER_MINOR, SWTPM_VER_MICRO);
1166
}
2✔
1167

1168
static void usage(const char *prgname, const char *default_config_file)
1✔
1169
{
1170
    versioninfo();
1✔
1171
    printf(
1✔
1172
        "Usage: %s [options]\n"
1173
        "\n"
1174
        "The following options are supported:\n"
1175
        "\n"
1176
        "--runas <user>   : Run this program under the given user's account.\n"
1177
        "\n"
1178
        "--tpm-state <dir>: Path where the TPM's state will be written to;\n"
1179
        "                   this is a mandatory argument. Prefix with dir:// to\n"
1180
        "                   use directory backend, or file:// to use linear file.\n"
1181
        "\n"
1182
        "--tpmstate <dir> : This is an alias for --tpm-state <dir>.\n"
1183
        "\n"
1184
        "--tpm '<path-to-executable> socket'\n"
1185
        "                 : Path to the TPM executable; this is an optional argument and\n"
1186
        "                   by default 'swtpm' in the PATH is used.\n"
1187
        "\n"
1188
        "--swtpm_ioctl <executable>\n"
1189
        "                 : Path to the swtpm_ioctl executable; this is deprecated\n"
1190
        "                   argument.\n"
1191
        "\n"
1192
        "--tpm2           : Setup a TPM 2; by default a TPM 1.2 is setup.\n"
1193
        "\n"
1194
        "--createek       : Create the EK; for a TPM 2 an RSA and ECC EK will be\n"
1195
        "                   created\n"
1196
        "\n"
1197
        "--allow-signing  : Create an EK that can be used for signing;\n"
1198
        "                   this option requires --tpm2.\n"
1199
        "                   Note: Careful, this option will create a non-standard EK!\n"
1200
        "\n"
1201
        "--decryption     : Create an EK that can be used for key encipherment;\n"
1202
        "                   this is the default unless --allow-signing is given;\n"
1203
        "                   this option requires --tpm2.\n"
1204
        "\n"
1205
        "--ecc            : This option allows to create a TPM 2's ECC key as storage\n"
1206
        "                   primary key; a TPM 2 always gets an RSA and an ECC EK key.\n"
1207
        "\n"
1208
        "--ek1keyalgo <alg>\n"
1209
        "                 : Choice of the 1st EK's key algorithm; default is %s\n"
1210
        "                   choices: rsa2048, rsa3072, rsa4096, ecc_nist_p384\n"
1211
        "\n"
1212
        "--ek2keyalgo <alg>\n"
1213
        "                 : Choice of the 2nd EK's key algorithm; default is %s\n"
1214
        "                   choices: same as for --ek1keyalgo\n"
1215
        "\n"
1216
        "--iakkeyalgo <alg>\n"
1217
        "                 : Choice of the IAK algorithm; default is 'none'\n"
1218
        "                   choices: rsa2048, rsa3072, rsa4096, ecc_nist_p384\n"
1219
        "\n"
1220
        "--idevidkeyalgo <alg>\n"
1221
        "                 : Choice of the IDevID key algorithm; default is 'none'\n"
1222
        "                   choices: same as for --iakkeyalgo\n"
1223
        "\n"
1224
        "--take-ownership : Take ownership; this option implies --createek\n"
1225
        "  --ownerpass  <password>\n"
1226
        "                 : Provide custom owner password; default is %s\n"
1227
        "  --owner-well-known:\n"
1228
        "                 : Use an owner password of 20 zero bytes\n"
1229
        "  --srkpass <password>\n"
1230
        "                 : Provide custom SRK password; default is %s\n"
1231
        "  --srk-well-known:\n"
1232
        "                 : Use an SRK password of 20 zero bytes\n"
1233
        "--create-ek-cert : Create an EK certificate; this implies --createek\n"
1234
        "\n"
1235
        "--create-platform-cert\n"
1236
        "                 : Create a platform certificate; this implies --create-ek-cert\n"
1237
        "\n"
1238
        "--create-spk     : Create storage primary key; this requires --tpm2; deprecated\n"
1239
        "\n"
1240
        "--lock-nvram     : Lock NVRAM access\n"
1241
        "\n"
1242
        "--display        : At the end display as much info as possible about the\n"
1243
        "                   configuration of the TPM\n"
1244
        "\n"
1245
        "--config <config file>\n"
1246
        "                 : Path to configuration file; default is %s\n"
1247
        "\n"
1248
        "--logfile <logfile>\n"
1249
        "                 : Path to log file; default is logging to stderr\n"
1250
        "\n"
1251
        "--keyfile <keyfile>\n"
1252
        "                 : Path to a key file containing the encryption key for the\n"
1253
        "                   TPM to encrypt its persistent state with. The content\n"
1254
        "                   must be a 32 hex digit number representing a 128bit AES key.\n"
1255
        "                   This parameter will be passed to the TPM using\n"
1256
        "                   '--key file=<file>'.\n"
1257
        "\n"
1258
        "--keyfile-fd <fd>: Like --keyfile but a file descriptor is given to read the\n"
1259
        "                   encryption key from.\n"
1260
        "\n"
1261
        "--pwdfile <pwdfile>\n"
1262
        "                 : Path to a file containing a passphrase from which the\n"
1263
        "                   TPM will derive the 128bit AES key. The passphrase can be\n"
1264
        "                   32 bytes long.\n"
1265
        "                   This parameter will be passed to the TPM using\n"
1266
        "                   '--key pwdfile=<file>'.\n"
1267
        "\n"
1268
        "--pwdfile-fd <fd>: Like --pwdfile but a file descriptor is given to to read\n"
1269
        "                   the passphrase from.\n"
1270
        "\n"
1271
        "--cipher <cipher>: The cipher to use; either aes-128-cbc or aes-256-cbc;\n"
1272
        "                   the default is aes-128-cbc; the same cipher must be\n"
1273
        "                   used on the swtpm command line\n"
1274
        "\n"
1275
        "--overwrite      : Overwrite existing TPM state by re-initializing it; if this\n"
1276
        "                   option is not given, this program will return an error if\n"
1277
        "                   existing state is detected\n"
1278
        "\n"
1279
        "--not-overwrite  : Do not overwrite existing TPM state but silently end\n"
1280
        "\n"
1281
        "--vmid <vm id>   : Unique (VM) identifier to use as common name in certificate\n"
1282
        "\n"
1283
        "--pcr-banks <banks>\n"
1284
        "                 : Set of PCR banks to activate. Provide a comma separated list\n"
1285
        "                   like 'sha1,sha256'. '-' to skip and leave all banks active.\n"
1286
        "                   Default: %s\n"
1287
        "\n"
1288
        "--rsa-keysize <keysize>\n"
1289
        "                 : The RSA key size of the 1st EK key; 3072 and 4096 bits may\n"
1290
        "                   be supported if libtpms supports it. This option is ignored\n"
1291
        "                   if --ek1keyalgo is used.\n"
1292
        "                   Default: %u\n"
1293
        "\n"
1294
        "--write-ek-cert-files <directory>\n"
1295
        "                 : Write EK cert files into the given directory\n"
1296
        "\n"
1297
        "--tcsd-system-ps-file <file>\n"
1298
        "                 : This option is deprecated and has no effect.\n"
1299
        "\n"
1300
        "--print-capabilities\n"
1301
        "                 : Print JSON formatted capabilities added after v0.1 and exit.\n"
1302
        "\n"
1303
        "--create-config-files [[overwrite][,root]]\n"
1304
        "                 : Create swtpm_setup and swtpm-localca config files for a\n"
1305
        "                   user account.\n"
1306
        "                   overwrite: overwrite any existing files\n"
1307
        "                   root: allow to create files under root's home directory\n"
1308
        "                   skip-if-exist: if any file exists exit without error\n"
1309
        "\n"
1310
        "--reconfigure    : Reconfigure an existing swtpm by reusing existing state.\n"
1311
        "                   The active PCR banks can be changed but no new keys will\n"
1312
        "                   be created.\n"
1313
        "\n"
1314
        "--profile <json-profile>\n"
1315
        "                 : Configure swtpm with the given profile.\n"
1316
        "\n"
1317
        "--profile-name <profile name | built-in profile name>\n"
1318
        "                 : Search for a profile with the <name>.json in distro and\n"
1319
        "                   local directories; if not found try it as a built-in.\n"
1320
        "\n"
1321
        "--profile-file <file>\n"
1322
        "                 : Configure swtpm with a profile read from the given file.\n"
1323
        "\n"
1324
        "--profile-file-fd <fd>\n"
1325
        "                 : Configure swtpm with a profile read from a file descriptor.\n"
1326
        "\n"
1327
        "--profile-remove-disabled check|fips-host\n"
1328
        "                 : Instruct swtpm to remove algorithms that may be disabled by\n"
1329
        "                   FIPS mode on the host from 'custom' profile.\n"
1330
        "                   check: algorithms are tested.\n"
1331
        "                   fips-host: no testing.\n"
1332
        "\n"
1333
        "--print-profiles : Display all local and distro-provided profile as well as\n"
1334
        "                   the ones built into libtpms and exit.\n"
1335
        "\n"
1336
        "--version        : Display version and exit\n"
1337
        "\n"
1338
        "--help,-h        : Display this help screen\n\n",
1339
            prgname,
1340
            DEFAULT_EK1KEYALGO,
1341
            DEFAULT_EK2KEYALGO,
1342
            DEFAULT_OWNER_PASSWORD,
1343
            DEFAULT_SRK_PASSWORD,
1344
            default_config_file,
1345
            DEFAULT_PCR_BANKS,
1346
            DEFAULT_RSA_KEYSIZE
1347
        );
1348
}
1✔
1349

1350
static int get_swtpm_capabilities(const gchar **swtpm_prg_l, gboolean is_tpm2,
444✔
1351
                                  gchar **standard_output)
1352
{
1353
    const gchar *my_argv[] = { "--print-capabilities", is_tpm2 ? "--tpm2" : NULL, NULL };
444✔
1354
    g_autofree gchar *standard_error = NULL;
888✔
1355
    g_autofree gchar *logop = NULL;
444✔
1356
    g_autoptr(GError) error = NULL;
444✔
1357
    g_autofree const gchar **argv = NULL;
444✔
1358
    int exit_status = 0;
444✔
1359
    gboolean success;
444✔
1360
    int ret = 1;
444✔
1361

1362
    argv = concat_arrays(swtpm_prg_l, my_argv, FALSE);
444✔
1363

1364
    if (gl_LOGFILE != NULL) {
444✔
1365
        logop = g_strdup_printf("file=%s", gl_LOGFILE);
257✔
1366
        argv = concat_arrays(argv, (const gchar*[]){"--log", logop, NULL}, TRUE);
257✔
1367
    }
1368

1369
    success = spawn_sync(NULL, argv, NULL, 0, NULL, NULL,
444✔
1370
                         standard_output, &standard_error, &exit_status, &error);
1371
    if (!success) {
444✔
1372
        logerr(gl_LOGFILE, "Could not start swtpm '%s': %s\n", swtpm_prg_l[0], error->message);
×
1373
        goto error;
×
1374
    }
1375
    if (exit_status != 0) {
444✔
1376
        /* possible: failure to access log file */
1377
        logerr(gl_LOGFILE, "Failed to run swtpm '%s': %s\n", swtpm_prg_l[0], standard_error);
×
1378
        goto error;
×
1379
    }
1380
    ret = 0;
1381

1382
error:
444✔
1383
    return ret;
444✔
1384
}
1385

1386
static int get_supported_tpm_versions(const gchar **swtpm_prg_l, gboolean *swtpm_has_tpm12,
184✔
1387
                                      gboolean *swtpm_has_tpm2)
1388
{
1389
    g_autofree gchar *standard_output = NULL;
368✔
1390
    int ret;
184✔
1391

1392
    ret = get_swtpm_capabilities(swtpm_prg_l, FALSE, &standard_output);
184✔
1393
    if (ret)
184✔
1394
        return ret;
1395

1396
    *swtpm_has_tpm12 = g_strstr_len(standard_output, -1, "\"tpm-1.2\"") != NULL;
184✔
1397
    *swtpm_has_tpm2 = g_strstr_len(standard_output, -1, "\"tpm-2.0\"") != NULL;
184✔
1398

1399
    return 0;
184✔
1400
}
1401

1402
/* Get the support RSA key sizes.
1403
 *  This function returns an array of ints like the following
1404
 *  - [ 1024, 2048, 3072, 4096 ]
1405
 *  - [] (empty array, indicating only 2048 bit RSA keys are supported)
1406
 */
1407
static int get_rsa_keysizes(unsigned long flags, const gchar **swtpm_prg_l,
151✔
1408
                            unsigned int **keysizes, size_t *n_keysizes)
1409
{
1410
    g_autofree gchar *standard_output = NULL;
302✔
1411
    const gchar *needle = "\"rsa-keysize-";
151✔
1412
    unsigned int keysize;
151✔
1413
    int ret = 1;
151✔
1414
    char *p;
151✔
1415
    int n;
151✔
1416

1417
    *n_keysizes = 0;
151✔
1418

1419
    if (flags & SETUP_TPM2_F) {
151✔
1420
        ret = get_swtpm_capabilities(swtpm_prg_l, TRUE, &standard_output);
151✔
1421
        if (ret)
151✔
1422
            goto error;
×
1423

1424
        p = standard_output;
151✔
1425
        /* A crude way of parsing the json output just looking for "rsa-keysize-%u" */
1426
        while ((p = g_strstr_len(p, -1, needle)) != NULL) {
755✔
1427
            p += strlen(needle);
604✔
1428
            n = sscanf(p, "%u\"", &keysize);
604✔
1429
            if (n == 1) {
604✔
1430
                *keysizes = g_realloc(*keysizes, (*n_keysizes + 1) * sizeof(unsigned int));
604✔
1431
                (*keysizes)[*n_keysizes] = keysize;
604✔
1432
                (*n_keysizes)++;
604✔
1433
            }
1434
        }
1435
    }
1436
    ret = 0;
1437

1438
error:
151✔
1439
    return ret;
151✔
1440
}
1441

1442
/* Return the RSA key size capabilities in a NULL-terminated array */
1443
static int get_rsa_keysize_caps(unsigned long flags, const gchar **swtpm_prg_l,
9✔
1444
                                gchar ***keysize_strs)
1445
{
1446
    unsigned int *keysizes = NULL;
9✔
1447
    size_t n_keysizes = 0;
9✔
1448
    size_t i, j;
9✔
1449
    int ret = get_rsa_keysizes(flags, swtpm_prg_l, &keysizes, &n_keysizes);
9✔
1450
    if (ret)
9✔
1451
        return ret;
1452

1453
    *keysize_strs = g_malloc0(sizeof(char *) * (n_keysizes + 1));
9✔
1454
    for (i = 0, j = 0; i < n_keysizes; i++) {
45✔
1455
        if (keysizes[i] >= 2048)
36✔
1456
            (*keysize_strs)[j++] = g_strdup_printf("tpm2-rsa-keysize-%u", keysizes[i]);
27✔
1457
    }
1458

1459
    g_free(keysizes);
9✔
1460

1461
    return 0;
9✔
1462
}
1463

1464
static bool is_rsa_keysize_supported(unsigned long flags, unsigned int rsa_keysize,
142✔
1465
                                     gchar **swtpm_prg_l)
1466
{
1467
    g_autofree unsigned int *keysizes = NULL;
284✔
1468
    gboolean found = FALSE;
142✔
1469
    size_t n_keysizes;
142✔
1470
    size_t i;
142✔
1471
    int ret;
142✔
1472

1473
    ret = get_rsa_keysizes(flags, (const char **)swtpm_prg_l, &keysizes, &n_keysizes);
142✔
1474
    if (ret)
142✔
1475
        return false;
1476

1477
    for (i = 0; i < n_keysizes && !found; i++)
463✔
1478
        found = (keysizes[i] == rsa_keysize);
321✔
1479
    if (!found && rsa_keysize != 2048) {
142✔
1480
        logerr(gl_LOGFILE, "%u bit RSA keys are not supported by libtpms.\n", rsa_keysize);
×
1481
        return false;
×
1482
    }
1483
    return true;
1484
}
1485

1486
/* Parse the rsa_keysize_str and check that it contains a supported size */
1487
static unsigned int parse_rsa_keysize(unsigned long flags, char **rsa_keysize_str,
125✔
1488
                                      gchar **swtpm_prg_l)
1489
{
1490
    unsigned int *keysizes = NULL;
125✔
1491
    unsigned int rsa_keysize;
125✔
1492
    size_t n_keysizes;
125✔
1493
    int ret;
125✔
1494

1495
    if (strcmp(*rsa_keysize_str, "max") == 0) {
125✔
1496
        ret = get_rsa_keysizes(flags, (const char **)swtpm_prg_l, &keysizes, &n_keysizes);
×
1497
        if (ret)
×
1498
            return 0;
1499
        g_free(*rsa_keysize_str);
×
1500
        if (n_keysizes > 0) {
×
1501
            /* last one is the biggest one */
1502
            *rsa_keysize_str = g_strdup_printf("%u", keysizes[n_keysizes - 1]);
×
1503
        } else {
1504
            *rsa_keysize_str = g_strdup("2048");
×
1505
        }
1506
        g_free(keysizes);
×
1507
    }
1508

1509
    if (strcmp(*rsa_keysize_str, "2048") == 0 ||
125✔
1510
        strcmp(*rsa_keysize_str, "3072") == 0 ||
19✔
1511
        strcmp(*rsa_keysize_str, "4096") == 0) {
7✔
1512

1513
        rsa_keysize = strtoull(*rsa_keysize_str, NULL, 10);
125✔
1514

1515
        if (!is_rsa_keysize_supported(flags, rsa_keysize, swtpm_prg_l))
125✔
1516
            return 0;
1517
        return rsa_keysize;
1518
    }
1519

1520
    logit(gl_LOGFILE, "Unsupported RSA key size %s.\n", *rsa_keysize_str);
×
1521
    return 0;
×
1522
}
1523

1524
static int validate_json_profile(const gchar **swtpm_prg_l, const char *json_profile)
100✔
1525
{
1526
    g_autofree gchar *standard_output = NULL;
200✔
1527
    int ret;
100✔
1528

1529
    ret = get_swtpm_capabilities(swtpm_prg_l, TRUE, &standard_output);
100✔
1530
    if (ret)
100✔
1531
        return ret;
1532

1533
    return check_json_profile(standard_output, json_profile);
100✔
1534
}
1535

1536
/* Print the JSON object of swtpm_setup's capabilities */
1537
static int print_capabilities(const char **swtpm_prg_l, gboolean swtpm_has_tpm12,
9✔
1538
                              gboolean swtpm_has_tpm2)
1539
{
1540
    g_autofree gchar *standard_output = NULL;
18✔
1541
    g_autofree gchar *param = g_strdup("");
18✔
1542
    g_autofree gchar *profile_list = NULL;
9✔
1543
    gchar **profile_names = NULL;
9✔
1544
    gchar **keysize_strs = NULL;
9✔
1545
    gchar *tmp;
9✔
1546
    size_t i;
9✔
1547
    int ret = 0;
9✔
1548

1549
    ret = get_rsa_keysize_caps(SETUP_TPM2_F, swtpm_prg_l, &keysize_strs);
9✔
1550
    if (ret)
9✔
1551
        return 1;
1552

1553
    for (i = 0; keysize_strs[i] != NULL; i++) {
36✔
1554
        tmp = g_strdup_printf("%s, \"%s\"", param, keysize_strs[i]);
27✔
1555
        g_free(param);
27✔
1556
        param = tmp;
27✔
1557
    }
1558

1559
    if (swtpm_has_tpm2) {
9✔
1560
        ret = get_swtpm_capabilities(swtpm_prg_l, TRUE, &standard_output);
9✔
1561
        if (ret)
9✔
1562
            goto error;
×
1563
        ret = get_profile_names(standard_output, &profile_names);
9✔
1564
        if (ret)
9✔
1565
            goto error;
×
1566

1567
        if (g_strv_length(profile_names) > 0) {
9✔
1568
            tmp = g_strjoinv("\", \"", profile_names);
9✔
1569
            profile_list = g_strdup_printf(" \"%s\" ", tmp);
9✔
1570
            g_free(tmp);
9✔
1571
        }
1572
    }
1573

1574
    printf("{ \"type\": \"swtpm_setup\", "
9✔
1575
           "\"features\": [ %s%s\"cmdarg-keyfile-fd\", \"cmdarg-pwdfile-fd\", \"tpm12-not-need-root\""
1576
           ", \"cmdarg-write-ek-cert-files\", \"cmdarg-create-config-files\""
1577
           ", \"cmdarg-reconfigure-pcr-banks\""
1578
           "%s"
1579
           ", \"cmdarg-profile\", \"cmdarg-profile-remove-disabled\""
1580
           ", \"cmdarg-ek1keyalgo\", \"cmdarg-ek2keyalgo\""
1581
           ", \"cmdarg-iakkeyalgo\", \"cmdarg-idevidkeyalgo\""
1582
           " ], "
1583
           "\"profiles\": [%s], "
1584
           "\"version\": \"" VERSION "\" "
1585
           "}\n",
1586
           swtpm_has_tpm12 ? "\"tpm-1.2\", " : "",
1587
           swtpm_has_tpm2  ? "\"tpm-2.0\", " : "",
1588
           param,
1589
           profile_list ? profile_list : ""
1590
           );
1591

1592
error:
9✔
1593
    g_strfreev(keysize_strs);
9✔
1594
    g_strfreev(profile_names);
9✔
1595

1596
    return ret;
9✔
1597
}
1598

1599
static int change_process_owner(const char *user)
1600
{
1601
    char *endptr;
×
1602
    unsigned long long uid = strtoull(user, &endptr, 10);
×
1603
    gid_t gid;
×
1604
    struct passwd *passwd;
×
1605
    int ret = 1;
×
1606

1607
    if (*endptr != '\0') {
×
1608
        /* assuming a name */
1609
        passwd = getpwnam(user);
×
1610
        if (passwd == NULL) {
×
1611
            logerr(gl_LOGFILE, "Error: User '%s' does not exist.\n", user);
×
1612
            goto error;
×
1613
        }
1614

1615
        if (initgroups(passwd->pw_name, passwd->pw_gid) != 0) {
×
1616
            logerr(gl_LOGFILE, "Error: initgroups() failed: %s\n", strerror(errno));
×
1617
            goto error;
×
1618
        }
1619

1620
        gid = passwd->pw_gid;
×
1621
        uid = passwd->pw_uid;
×
1622
    } else {
1623
        if (uid > 0xffffffff) {
×
1624
            logerr(gl_LOGFILE, "Error: uid %s outside valid range.\n", user);
×
1625
            goto error;
×
1626
        }
1627
        gid = (gid_t)uid;
×
1628
    }
1629

1630
    if (setgid(gid) != 0) {
×
1631
        logerr(gl_LOGFILE, "Error: setgid(%d) failed: %s\n", gid, strerror(errno));
×
1632
        goto error;
×
1633
    }
1634

1635
    if (setuid(uid) != 0) {
×
1636
        logerr(gl_LOGFILE, "Error: setuid(%lld) failed: %s\n", uid, strerror(errno));
×
1637
        goto error;
×
1638
    }
1639

1640
    ret = 0;
1641

1642
error:
×
1643
    return ret;
×
1644
}
1645

1646
static int handle_create_config_files(const char *opt_arg)
1647
{
1648
    g_auto(GStrv) tokens = NULL;
×
1649
    gboolean overwrite = FALSE;
×
1650
    gboolean root_flag = FALSE;
×
1651
    gboolean skip_if_exist = FALSE;
×
1652

1653
    if (opt_arg) {
×
1654
        tokens = g_strsplit_set(opt_arg, ", ", -1);
×
1655
        overwrite = g_strv_contains((const gchar **)tokens, "overwrite");
×
1656
        root_flag = g_strv_contains((const gchar **)tokens, "root");
×
1657
        skip_if_exist = g_strv_contains((const gchar **)tokens, "skip-if-exist");
×
1658
        if (overwrite && skip_if_exist) {
×
1659
            fprintf(stderr, "Error: overwrite and skip-if-exist cannot both be used\n");
×
1660
            return 1;
×
1661
        }
1662
    }
1663

1664
    return create_config_files(overwrite, root_flag, skip_if_exist);
×
1665
}
1666

1667
static int read_config_file(const gchar *config_file,
170✔
1668
                            const struct passwd *user,
1669
                            gchar ***config_file_lines)
1670
{
1671
    if (access(config_file, R_OK) != 0) {
170✔
1672
        logerr(gl_LOGFILE, "User %s cannot read config file %s.\n",
×
1673
               user ? user->pw_name : "<unknown>", config_file);
1674
        return -1;
×
1675
    }
1676

1677
    if (read_file_lines(config_file, config_file_lines))
170✔
1678
        return -1;
1679

1680
    return 0;
1681
}
1682

1683
static bool parse_keyalgo(const char *keyalgo_str,
44✔
1684
                          enum keyalgo *keyalgo,
1685
                          unsigned int *keyalgo_param,
1686
                          unsigned long *flags)
1687
{
1688
    size_t i;
44✔
1689

1690
    for (i = 0; i < ARRAY_LEN(keyalgo_choices); i++) {
176✔
1691
        if (!strcasecmp(keyalgo_choices[i].name, keyalgo_str)) {
176✔
1692
            *keyalgo = keyalgo_choices[i].keyalgo;
44✔
1693
            *keyalgo_param = keyalgo_choices[i].keyalgo_param;
44✔
1694
            return true;
44✔
1695
        }
1696
    }
1697
    logerr(gl_LOGFILE,
×
1698
           "Key algorithm %s is not supported.\n", keyalgo_str);
1699
    return false;
×
1700
}
1701

1702
int main(int argc, char *argv[])
197✔
1703
{
1704
    int opt, option_index = 0;
197✔
1705
    static const struct option long_options[] = {
197✔
1706
        {"tpm-state", required_argument, NULL, 't'},
1707
        {"tpmstate", required_argument, NULL, 't'}, /* alias for tpm-state */
1708
        {"tpm", required_argument, NULL, 'T'},
1709
        {"swtpm_ioctl", required_argument, NULL, '_'},
1710
        {"tpm2", no_argument, NULL, '2'},
1711
        {"ecc", no_argument, NULL, 'e'},
1712
        {"createek", no_argument, NULL, 'c'},
1713
        {"create-spk", no_argument, NULL, 'C'},
1714
        {"ek1keyalgo", required_argument, NULL, '4'},
1715
        {"ek2keyalgo", required_argument, NULL, '5'},
1716
        {"iakkeyalgo", required_argument, NULL, '6'},
1717
        {"idevidkeyalgo", required_argument, NULL, '7'},
1718
        {"take-ownership", no_argument, NULL, 'o'},
1719
        {"ownerpass", required_argument, NULL, 'O'},
1720
        {"owner-well-known", no_argument, NULL, 'w'},
1721
        {"srkpass", required_argument, NULL, 'S'},
1722
        {"srk-well-known", no_argument, NULL, 's'},
1723
        {"create-ek-cert", no_argument, NULL, 'E'},
1724
        {"create-platform-cert", no_argument, NULL, 'P'},
1725
        {"lock-nvram", no_argument, NULL, 'L'},
1726
        {"display", no_argument, NULL, 'i'},
1727
        {"config", required_argument, NULL, 'f'},
1728
        {"vmid", required_argument, NULL, 'm'},
1729
        {"keyfile", required_argument, NULL, 'x'},
1730
        {"keyfile-fd", required_argument, NULL, 'X'},
1731
        {"pwdfile", required_argument, NULL, 'k'},
1732
        {"pwdfile-fd", required_argument, NULL, 'K'},
1733
        {"cipher", required_argument, NULL, 'p'},
1734
        {"runas", required_argument, NULL, 'r'},
1735
        {"logfile", required_argument, NULL, 'l'},
1736
        {"overwrite", no_argument, NULL, 'v'},
1737
        {"not-overwrite", no_argument, NULL, 'V'},
1738
        {"allow-signing", no_argument, NULL, 'a'},
1739
        {"decryption", no_argument, NULL, 'd'},
1740
        {"pcr-banks", required_argument, NULL, 'b'},
1741
        {"rsa-keysize", required_argument, NULL, 'A'},
1742
        {"write-ek-cert-files", required_argument, NULL, '3'},
1743
        {"create-config-files", optional_argument, NULL, 'u'},
1744
        {"tcsd-system-ps-file", required_argument, NULL, 'F'},
1745
        {"version", no_argument, NULL, '1'},
1746
        {"print-capabilities", no_argument, NULL, 'y'},
1747
        {"reconfigure", no_argument, NULL, 'R'},
1748
        {"profile", required_argument, NULL, 'I'},
1749
        {"profile-name", required_argument, NULL, 'J'},
1750
        {"profile-file", required_argument, NULL, 'g'},
1751
        {"profile-file-fd", required_argument, NULL, 'G'},
1752
        {"profile-remove-disabled", required_argument, NULL, 'j'},
1753
        {"print-profiles", no_argument, NULL, 'M'},
1754
        {"no-iak", no_argument, NULL, 'n'},
1755
        {"help", no_argument, NULL, 'h'},
1756
        {NULL, 0, NULL, 0}
1757
    };
1758
    unsigned long flags = 0;
197✔
1759
    g_auto(GStrv) config_file_lines = NULL;
197✔
1760
    g_autofree gchar *swtpm_prg = NULL;
197✔
1761
    g_autofree gchar *tpm_state_path = NULL;
197✔
1762
    struct swtpm_backend_ops *backend_ops = &swtpm_backend_dir;
197✔
1763
    void *backend_state = NULL;
197✔
1764
    g_autofree gchar *config_file = NULL;
197✔
1765
    g_autofree gchar *ownerpass = NULL;
197✔
1766
    gboolean got_ownerpass = FALSE;
197✔
1767
    g_autofree gchar *srkpass = NULL;
197✔
1768
    gboolean got_srkpass = FALSE;
197✔
1769
    g_autofree gchar *vmid = NULL;
197✔
1770
    g_autofree gchar *pcr_banks = NULL;
197✔
1771
    gboolean printcapabilities = FALSE;
197✔
1772
    gboolean printprofiles = FALSE;
197✔
1773
    g_autofree gchar *keyfile = NULL;
197✔
1774
    long int keyfile_fd = -1;
197✔
1775
    g_autofree gchar *pwdfile = NULL;
197✔
1776
    long int pwdfile_fd = -1;
197✔
1777
    g_autofree gchar *cipher = g_strdup("aes-128-cbc");
394✔
1778
    g_autofree gchar *rsa_keysize_str = NULL;
197✔
1779
    unsigned int rsa_keysize = 2048;
197✔
1780
    g_autofree gchar *swtpm_keyopt = NULL;
197✔
1781
    g_autofree gchar *runas = NULL;
197✔
1782
    g_autofree gchar *certsdir = NULL;
197✔
1783
    g_autofree gchar *user_certsdir = NULL;
197✔
1784
    g_autofree gchar *json_profile = NULL;
197✔
1785
    g_autofree gchar *json_profile_name = NULL;
197✔
1786
    g_autofree gchar *json_profile_file = NULL;
197✔
1787
    g_autofree gchar *profile_remove_disabled_param = NULL;
197✔
1788
    g_autofree gchar *ek1keyalgo_str = NULL;
197✔
1789
    g_autofree gchar *ek2keyalgo_str = NULL;
197✔
1790
    g_autofree gchar *iakkeyalgo_str = NULL;
197✔
1791
    g_autofree gchar *idevidkeyalgo_str = NULL;
197✔
1792
    int json_profile_fd = -1;
197✔
1793
    gchar *tmp;
197✔
1794
    gchar **swtpm_prg_l = NULL;
197✔
1795
    gchar **tmp_l = NULL;
197✔
1796
    size_t i, n;
197✔
1797
    int logfd;
197✔
1798
    const struct passwd *curr_user;
197✔
1799
    struct group *curr_grp;
197✔
1800
    char *endptr;
197✔
1801
    gboolean swtpm_has_tpm12 = FALSE;
197✔
1802
    gboolean swtpm_has_tpm2 = FALSE;
197✔
1803
    int fds_to_pass[2] = { -1, -1 };
197✔
1804
    unsigned n_fds_to_pass = 0;
197✔
1805
    char tmpbuffer[200];
197✔
1806
    gboolean no_iak = FALSE;
197✔
1807
    time_t now;
197✔
1808
    struct tm *tm;
197✔
1809
    int ret = 1;
197✔
1810
    g_autoptr(GError) error = NULL;
197✔
1811
    enum keyalgo ek1keyalgo = KEYALGO_RSA;
197✔
1812
    enum keyalgo ek2keyalgo = KEYALGO_ECC;
197✔
1813
    enum keyalgo iakkeyalgo = KEYALGO_NONE;
197✔
1814
    enum keyalgo idevidkeyalgo = KEYALGO_NONE;
197✔
1815
    unsigned int ek1keyalgo_param = 0;
197✔
1816
    unsigned int ek2keyalgo_param = 0;
197✔
1817
    unsigned int iakkeyalgo_param = 0;
197✔
1818
    unsigned int idevidkeyalgo_param = 0;
197✔
1819

1820
    setvbuf(stdout, 0, _IONBF, 0);
197✔
1821

1822
    if (init(&config_file) < 0)
197✔
1823
        goto error;
×
1824

1825
    swtpm_prg = g_find_program_in_path("swtpm");
197✔
1826
    if (swtpm_prg) {
197✔
1827
        tmp = g_strconcat(swtpm_prg, " socket", NULL);
80✔
1828
        g_free(swtpm_prg);
80✔
1829
        swtpm_prg = tmp;
80✔
1830
    }
1831

1832
    while ((opt = getopt_long(argc, argv, "h?",
3,500✔
1833
                              long_options, &option_index)) != -1) {
1,750✔
1834
        switch (opt) {
1,555✔
1835
        case 't': /* --tpmstate, --tpm-state */
182✔
1836
            g_free(tpm_state_path);
182✔
1837
            if (strncmp(optarg, "dir://", 6) == 0) {
182✔
1838
                tpm_state_path = g_strdup(optarg);
10✔
1839
            } else if (strncmp(optarg, "file://", 7) == 0) {
172✔
1840
                tpm_state_path = g_strdup(optarg);
3✔
1841
                backend_ops = &swtpm_backend_file;
1842
            } else {
1843
                /* always prefix with dir:// so we can pass verbatim to swtpm */
1844
                tpm_state_path = g_strconcat("dir://", optarg, NULL);
169✔
1845
            }
1846
            break;
1847
        case 'T': /* --tpm */
183✔
1848
            g_free(swtpm_prg);
183✔
1849
            swtpm_prg = g_strdup(optarg);
183✔
1850
            break;
1851
        case '_': /* --swtpm_ioctl */
×
1852
            fprintf(stdout, "Warning: --swtpm_ioctl is deprecated and has no effect.");
×
1853
            break;
×
1854
        case '2': /* --tpm2 */
159✔
1855
            flags |= SETUP_TPM2_F;
159✔
1856
            break;
159✔
1857
        case 'e': /* --ecc */
21✔
1858
            flags |= SETUP_TPM2_ECC_F;
21✔
1859
            break;
21✔
1860
        case '4': /* --ek1keyalgo */
15✔
1861
            g_free(ek1keyalgo_str);
15✔
1862
            ek1keyalgo_str = g_strdup(optarg);
15✔
1863
            break;
1864
        case '5': /* --ek2keyalgo */
15✔
1865
            g_free(ek2keyalgo_str);
15✔
1866
            ek2keyalgo_str = g_strdup(optarg);
15✔
1867
            break;
1868
        case '6': /* --iakkeyalgo */
7✔
1869
            g_free(iakkeyalgo_str);
7✔
1870
            iakkeyalgo_str = g_strdup(optarg);
7✔
1871
            break;
1872
        case '7': /* --idevidkeyalgo */
7✔
1873
            g_free(idevidkeyalgo_str);
7✔
1874
            idevidkeyalgo_str = g_strdup(optarg);
7✔
1875
            break;
1876
        case 'c': /* --createek */
50✔
1877
            flags |= SETUP_CREATE_EK_F;
50✔
1878
            break;
50✔
1879
        case 'C': /* --create-spk */
17✔
1880
            flags |= SETUP_CREATE_SPK_F;
17✔
1881
            break;
17✔
1882
        case 'o': /* --take-ownership */
10✔
1883
            flags |= SETUP_CREATE_EK_F | SETUP_TAKEOWN_F;
10✔
1884
            break;
10✔
1885
        case 'O': /* --ownerpass */
2✔
1886
            g_free(ownerpass);
2✔
1887
            ownerpass = g_strdup(optarg);
2✔
1888
            got_ownerpass = TRUE;
1889
            break;
1890
        case 'w': /* --owner-well-known */
2✔
1891
            flags |= SETUP_OWNERPASS_ZEROS_F;
2✔
1892
            got_ownerpass = TRUE;
2✔
1893
            break;
2✔
1894
        case 'S': /* --srk-pass */
2✔
1895
            g_free(srkpass);
2✔
1896
            srkpass = g_strdup(optarg);
2✔
1897
            got_srkpass = TRUE;
1898
            break;
1899
        case 's': /* --srk-well-known */
2✔
1900
            flags |= SETUP_SRKPASS_ZEROS_F;
2✔
1901
            got_srkpass = TRUE;
2✔
1902
            break;
2✔
1903
        case 'E': /* --create-ek-cert */
63✔
1904
            flags |= SETUP_CREATE_EK_F | SETUP_EK_CERT_F;
63✔
1905
            break;
63✔
1906
        case 'P': /* --create-platform-cert */
61✔
1907
            flags |= SETUP_CREATE_EK_F | SETUP_PLATFORM_CERT_F;
61✔
1908
            break;
61✔
1909
        case 'L': /* --lock-nvram */
16✔
1910
            flags |= SETUP_LOCK_NVRAM_F;
16✔
1911
            break;
16✔
1912
        case 'i': /* --display */
40✔
1913
            flags |= SETUP_DISPLAY_RESULTS_F;
40✔
1914
            break;
40✔
1915
        case 'f': /* --config */
230✔
1916
            g_free(config_file);
230✔
1917
            config_file = g_strdup(optarg);
230✔
1918
            break;
230✔
1919
        case 'm': /* --vmid */
43✔
1920
            g_free(vmid);
43✔
1921
            vmid = g_strdup(optarg);
43✔
1922
            break;
1923
        case 'x': /* --keyfile */
12✔
1924
            g_free(keyfile);
12✔
1925
            keyfile = g_strdup(optarg);
12✔
1926
            break;
1927
        case 'X': /* --pwdfile-fd' */
2✔
1928
            keyfile_fd = strtoull(optarg, &endptr, 10);
2✔
1929
            if (*endptr != '\0' && keyfile_fd >= INT_MAX) {
2✔
1930
                fprintf(stderr, "Invalid file descriptor '%s'\n", optarg);
×
1931
                goto error;
×
1932
            }
1933
            break;
1934
        case 'k': /* --pwdfile */
17✔
1935
            g_free(pwdfile);
17✔
1936
            pwdfile = g_strdup(optarg);
17✔
1937
            break;
1938
        case 'K': /* --pwdfile-fd' */
2✔
1939
            pwdfile_fd = strtoull(optarg, &endptr, 10);
2✔
1940
            if (*endptr != '\0' || pwdfile_fd >= INT_MAX) {
2✔
1941
                fprintf(stderr, "Invalid file descriptor '%s'\n", optarg);
×
1942
                goto error;
×
1943
            }
1944
            break;
1945
        case 'p': /* --cipher */
14✔
1946
            g_free(cipher);
14✔
1947
            cipher = g_strdup(optarg);
14✔
1948
            break;
1949
        case 'r': /* --runas */
×
1950
            g_free(runas);
×
1951
            runas = g_strdup(optarg);
×
1952
            break;
1953
        case 'l': /* --logfile */
96✔
1954
            g_free(gl_LOGFILE);
96✔
1955
            gl_LOGFILE = g_strdup(optarg);
96✔
1956
            break;
96✔
1957
        case 'v': /* --overwrite */
93✔
1958
            flags |= SETUP_STATE_OVERWRITE_F;
93✔
1959
            break;
93✔
1960
        case 'V': /* --not-overwrite */
3✔
1961
            flags |= SETUP_STATE_NOT_OVERWRITE_F;
3✔
1962
            break;
3✔
1963
        case 'a': /* --allow-signing */
25✔
1964
            flags |= SETUP_ALLOW_SIGNING_F;
25✔
1965
            break;
25✔
1966
        case 'd': /* --decryption */
8✔
1967
            flags |= SETUP_DECRYPTION_F;
8✔
1968
            break;
8✔
1969
        case 'b': /* --pcr-banks */
9✔
1970
            tmp = g_strconcat(pcr_banks ? pcr_banks: "",
18✔
1971
                              pcr_banks ? "," : "", g_strstrip(optarg), NULL);
1972
            g_free(pcr_banks);
9✔
1973
            pcr_banks = tmp;
9✔
1974
            break;
9✔
1975
        case 'A': /* --rsa-keysize */
21✔
1976
            g_free(rsa_keysize_str);
21✔
1977
            rsa_keysize_str = strdup(optarg);
21✔
1978
            flags |= SETUP_RSA_KEYSIZE_BY_USER_F;
21✔
1979
            break;
21✔
1980
        case '3': /* --write-ek-cert-files */
9✔
1981
            g_free(user_certsdir);
9✔
1982
            user_certsdir = g_strdup(optarg);
9✔
1983
            flags |= SETUP_WRITE_EK_CERT_FILES_F;
9✔
1984
            break;
9✔
1985
        case 'u':
×
1986
            if (optarg == NULL && optind < argc && argv[optind][0] != '0')
×
1987
                optarg = argv[optind++];
×
1988
            ret = handle_create_config_files(optarg);
×
1989
            goto out;
×
1990
        case 'F': /* --tcsd-system-ps-file */
1991
            printf("Warning: --tcsd-system-ps-file is deprecated and has no effect.");
×
1992
            break;
×
1993
        case '1': /* --version */
1✔
1994
            versioninfo();
1✔
1995
            ret = 0;
1✔
1996
            goto out;
1✔
1997
        case 'y': /* --print-capabilities */
1998
            printcapabilities = TRUE;
1999
            break;
2000
        case 'R': /* --reconfigure */
8✔
2001
            flags |= SETUP_RECONFIGURE_F;
8✔
2002
            break;
8✔
2003
        case 'I': /* --profile */
60✔
2004
            g_free(json_profile);
60✔
2005
            json_profile = g_strdup(optarg);
60✔
2006
            break;
60✔
2007
        case 'J': /* --profile-name */
28✔
2008
            g_free(json_profile_name);
28✔
2009
            json_profile_name = g_strdup(optarg);
28✔
2010
            break;
2011
        case 'g': /* --profile-file */
1✔
2012
            g_free(json_profile_file);
1✔
2013
            json_profile_file = g_strdup(optarg);
1✔
2014
            break;
1✔
2015
        case 'G': /* --profile-file-fd */
×
2016
            json_profile_fd = strtoull(optarg, &endptr, 10);
×
2017
            if (*endptr != '\0' || json_profile_fd >= INT_MAX) {
×
2018
                fprintf(stderr, "Invalid file descriptor '%s'\n", optarg);
×
2019
                goto error;
×
2020
            }
2021
            break;
2022
        case 'j': /* --profile-remove-disabled */
6✔
2023
            if (strcmp(optarg, "fips-host") != 0 &&
6✔
2024
                strcmp(optarg, "check") != 0) {
×
2025
                fprintf(stderr,
×
2026
                        "Unsupported parameter for --profile-remove-disabled: %s\n",
2027
                        optarg);
2028
                goto error;
×
2029
            }
2030
            g_free(profile_remove_disabled_param);
6✔
2031
            profile_remove_disabled_param = g_strdup(optarg);
1,756✔
2032
            break;
2033
        case 'M': /* --print-profiles */
3✔
2034
            printprofiles = TRUE;
3✔
2035
            break;
3✔
2036
        case 'n': /* --no-iak */
×
2037
            no_iak = TRUE;
×
2038
            break;
×
2039
        case '?':
1✔
2040
        case 'h': /* --help */
2041
            usage(argv[0], config_file);
1✔
2042
            if (opt == 'h')
1✔
2043
                ret = 0;
1✔
2044
            goto out;
1✔
2045
        default:
×
2046
            fprintf(stderr, "Unknown option code %d\n", opt);
×
2047
            usage(argv[0], config_file);
×
2048
            goto error;
×
2049
        }
2050
    }
2051

2052
    if (gl_LOGFILE != NULL) {
195✔
2053
        logfd = open(gl_LOGFILE, O_WRONLY|O_APPEND|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR|S_IRGRP);
96✔
2054
        if (logfd < 0) {
96✔
2055
            fprintf(stderr, "Cannot open logfile %s: %s\n", gl_LOGFILE, strerror(errno));
×
2056
            goto error;
×
2057
        }
2058
        close(logfd);
96✔
2059
    }
2060

2061
    if (swtpm_prg == NULL) {
195✔
2062
        logerr(gl_LOGFILE,
11✔
2063
               "Default TPM 'swtpm' could not be found and was not provided using --tpm.\n");
2064
        goto error;
11✔
2065
    }
2066

2067
    swtpm_prg_l = split_cmdline(swtpm_prg);
184✔
2068
    tmp = g_find_program_in_path(swtpm_prg_l[0]);
184✔
2069
    if (!tmp) {
184✔
2070
        logerr(gl_LOGFILE, "swtpm at %s is not an executable.\n", swtpm_prg_l[0]);
×
2071
        goto error;
×
2072
    }
2073
    g_free(tmp);
184✔
2074

2075
    ret = get_supported_tpm_versions((const char **)swtpm_prg_l, &swtpm_has_tpm12, &swtpm_has_tpm2);
184✔
2076
    if (ret != 0)
184✔
2077
        goto error;
×
2078

2079
    if (printcapabilities) {
184✔
2080
        ret = print_capabilities((const char **)swtpm_prg_l, swtpm_has_tpm12, swtpm_has_tpm2);
9✔
2081
        goto out;
9✔
2082
    }
2083

2084
    if ((flags & SETUP_TPM2_F) != 0 && !swtpm_has_tpm2) {
175✔
2085
        logerr(gl_LOGFILE, "swtpm at %s does not support TPM 2\n", swtpm_prg_l[0]);
×
2086
        goto error;
×
2087
    } else if ((flags & SETUP_TPM2_F) == 0 && !swtpm_has_tpm12){
175✔
2088
        logerr(gl_LOGFILE, "swtpm at %s does not support TPM 1.2\n", swtpm_prg_l[0]);
×
2089
        goto error;
×
2090
    }
2091

2092
    if (runas) {
175✔
2093
        ret = change_process_owner(runas);
×
2094
        if (ret != 0)
×
2095
            goto error;
×
2096
    }
2097

2098
    curr_user = getpwuid(getuid());
175✔
2099

2100
    if (printprofiles) {
175✔
2101
        ret = 0;
3✔
2102
        if (read_config_file(config_file, curr_user, &config_file_lines) < 0)
3✔
2103
            goto error;
×
2104

2105
        if (flags & SETUP_TPM2_F) {
3✔
2106
            if (profile_printall((const char **)swtpm_prg_l, config_file_lines))
3✔
2107
                ret = 1;
3✔
2108
        } else {
2109
            printf("{}\n");
×
2110
        }
2111
        goto out;
3✔
2112
    }
2113

2114
    if (!got_ownerpass)
172✔
2115
        ownerpass = g_strdup(DEFAULT_OWNER_PASSWORD);
168✔
2116
    if (!got_srkpass)
172✔
2117
        srkpass = g_strdup(DEFAULT_SRK_PASSWORD);
168✔
2118

2119
    // Check tpm_state_path directory and access rights
2120
    if (tpm_state_path == NULL) {
172✔
2121
        logerr(gl_LOGFILE, "--tpm-state must be provided\n");
×
2122
        goto error;
×
2123
    }
2124

2125
    backend_state = backend_ops->parse_backend(tpm_state_path);
172✔
2126
    if (!backend_state)
172✔
2127
        goto error;
×
2128

2129
    if (backend_ops->check_access(backend_state, R_OK|W_OK, curr_user) != 0)
172✔
2130
        goto error;
×
2131

2132
    if ((flags & SETUP_WRITE_EK_CERT_FILES_F)) {
172✔
2133
        if (check_directory_access(user_certsdir, W_OK, curr_user) != 0)
9✔
2134
            goto error;
×
2135
    }
2136

2137
    if (flags & SETUP_TPM2_F) {
172✔
2138
        if (flags & SETUP_TAKEOWN_F) {
143✔
2139
            logerr(gl_LOGFILE, "Taking ownership is not supported for TPM 2.\n");
×
2140
            goto error;
×
2141
        }
2142
    } else {
2143
        if (flags & SETUP_TPM2_ECC_F) {
29✔
2144
            logerr(gl_LOGFILE, "--ecc requires --tpm2.\n");
×
2145
            goto error;
×
2146
        }
2147
        if (flags & SETUP_CREATE_SPK_F) {
29✔
2148
            logerr(gl_LOGFILE, "--create-spk requires --tpm2.\n");
×
2149
            goto error;
×
2150
        }
2151
        if (flags & SETUP_RECONFIGURE_F) {
29✔
2152
            logerr(gl_LOGFILE, "--reconfigure requires --tpm2.\n");
×
2153
            goto error;
×
2154
        }
2155
        if (flags & SETUP_ALLOW_SIGNING_F) {
29✔
2156
            logerr(gl_LOGFILE, "--allow-signing requires --tpm2.\n");
×
2157
            goto error;
×
2158
        }
2159
        if (flags & SETUP_DECRYPTION_F) {
29✔
2160
            logerr(gl_LOGFILE, "--decryption requires --tpm2.\n");
×
2161
            goto error;
×
2162
        }
2163
        if (pcr_banks) {
29✔
2164
            logerr(gl_LOGFILE, "--pcr-banks requires --tpm2.\n");
×
2165
            goto error;
×
2166
        }
2167
    }
2168

2169
    if (!(flags & SETUP_RECONFIGURE_F)) {
172✔
2170
        ret = check_state_overwrite((const char **)swtpm_prg_l, flags, tpm_state_path);
166✔
2171
        if (ret == 1) {
166✔
2172
            goto error;
3✔
2173
        } else if (ret == 2) {
163✔
2174
            ret = 0;
2✔
2175
            goto out;
2✔
2176
        }
2177

2178
        ret = backend_ops->delete_state(backend_state);
161✔
2179
        if (ret != 0)
161✔
2180
            goto error;
×
2181
    }
2182

2183
    if (!config_file_lines &&
334✔
2184
        read_config_file(config_file, curr_user, &config_file_lines) < 0)
167✔
2185
        goto error;
×
2186

2187
    /* check pcr_banks; read from config file if not given */
2188
    tmp_l = g_strsplit(pcr_banks ? pcr_banks : "", ",", -1);
167✔
2189
    for (i = 0, n = 0; tmp_l[i]; i++) {
348✔
2190
        g_strstrip(tmp_l[i]);
14✔
2191
        n += strlen(tmp_l[i]);
14✔
2192
    }
2193
    g_strfreev(tmp_l);
167✔
2194
    if (n == 0) {
167✔
2195
        g_free(pcr_banks);
159✔
2196
        pcr_banks = get_default_pcr_banks(config_file_lines);
159✔
2197
    }
2198

2199
    if ((json_profile != NULL) +
167✔
2200
        (json_profile_name != NULL) +
167✔
2201
        (json_profile_file != NULL) +
167✔
2202
        (json_profile_fd > 0) > 1) {
167✔
2203
        logerr(gl_LOGFILE, "Only one of --profile, --profile-name, --profile-file, and --profile-file-fd may be given.\n");
×
2204
        goto error;
×
2205
    }
2206

2207
    if ((flags & SETUP_RECONFIGURE_F) &&
167✔
2208
         (json_profile ||
6✔
2209
          json_profile_name ||
6✔
2210
          json_profile_file ||
6✔
2211
          json_profile_fd > 0)) {
2212
            logerr(gl_LOGFILE, "Reconfiguration does not accept a (new) profile.\n");
×
2213
            goto error;
×
2214
    }
2215

2216
    if (json_profile_name) {
167✔
2217
        if (profile_name_check(json_profile_name) < 0)
28✔
2218
            goto error;
×
2219
        /*
2220
         * Load profile from distro and local locations; sets json_profile_file
2221
         * to filename or json_profile with the JSON.
2222
         */
2223
        if (profile_get_by_name(config_file_lines,
28✔
2224
                                json_profile_name,
2225
                                &json_profile_file,
2226
                                &json_profile) < 0) {
2227
            logerr(gl_LOGFILE, "Could not find or access profile '%s'.\n",
×
2228
                   json_profile_name);
2229
            goto error;
×
2230
        }
2231
    }
2232

2233
    if (json_profile_file) {
167✔
2234
        json_profile_fd = open(json_profile_file, O_RDONLY);
5✔
2235
        if (json_profile_fd < 0) {
5✔
2236
            logerr(gl_LOGFILE, "Could not open profile file '%s': %s\n",
×
2237
                   json_profile_file, strerror(errno));
×
2238
            goto error;
×
2239
        }
2240
    }
2241

2242
    /*
2243
     * Read default profile from swtpm_setup.conf;
2244
     * Do not read it when --reconfigure'ing
2245
     */
2246
    if ((flags & SETUP_TPM2_F) != 0 &&
167✔
2247
        json_profile == NULL && json_profile_fd < 0 &&
141✔
2248
        (flags & SETUP_RECONFIGURE_F) == 0) {
2249

2250
        json_profile_fd = get_default_profile_fd(config_file_lines);
46✔
2251
        if (json_profile_fd == -2)
46✔
2252
            goto error;
×
2253
        if (json_profile_fd < 0)
46✔
2254
            json_profile = get_default_profile(config_file_lines);
46✔
2255
    }
2256

2257
    if (json_profile_fd >= 0)
162✔
2258
        fds_to_pass[n_fds_to_pass++] = json_profile_fd;
5✔
2259

2260
    if ((flags & SETUP_TPM2_F) != 0 && json_profile) {
167✔
2261
        if (validate_json_profile((const char **)swtpm_prg_l, json_profile) != 0)
100✔
2262
            goto error;
1✔
2263
    } else if (json_profile) {
67✔
2264
        logerr(gl_LOGFILE, "There's no --profile support for TPM 1.2\n");
×
2265
        goto error;
×
2266
    }
2267

2268
    if (cipher != NULL) {
166✔
2269
        if (strcmp(cipher, "aes-128-cbc") != 0 &&
166✔
2270
            strcmp(cipher, "aes-cbc") != 0 &&
13✔
2271
            strcmp(cipher, "aes-256-cbc") != 0) {
13✔
2272
            logerr(gl_LOGFILE, "Unsupported cipher %s.\n", cipher);
×
2273
            goto error;
×
2274
        }
2275
        tmp = g_strdup_printf(",mode=%s", cipher);
166✔
2276
        g_free(cipher);
166✔
2277
        cipher = tmp;
166✔
2278
    }
2279

2280
    if (keyfile != NULL) {
166✔
2281
        if (access(keyfile, R_OK) != 0) {
12✔
2282
            logerr(gl_LOGFILE, "User %s cannot read keyfile %s.\n",
×
2283
                   curr_user ? curr_user->pw_name : "<unknown>", keyfile);
2284
            goto error;
×
2285
        }
2286
        swtpm_keyopt = g_strdup_printf("file=%s%s", keyfile, cipher);
12✔
2287
        logit(gl_LOGFILE, "  The TPM's state will be encrypted with a provided key.\n");
12✔
2288
    } else if (pwdfile != NULL) {
154✔
2289
        if (access(pwdfile, R_OK) != 0) {
17✔
2290
            logerr(gl_LOGFILE, "User %s cannot read passphrase file %s.\n",
×
2291
                   curr_user ? curr_user->pw_name : "<unknown>", pwdfile);
2292
            goto error;
×
2293
        }
2294
        swtpm_keyopt = g_strdup_printf("pwdfile=%s%s", pwdfile, cipher);
17✔
2295
        logit(gl_LOGFILE, "  The TPM's state will be encrypted using a key derived from a passphrase.\n");
17✔
2296
    } else if (keyfile_fd >= 0) {
137✔
2297
        fds_to_pass[n_fds_to_pass++] = keyfile_fd;
2✔
2298
        swtpm_keyopt = g_strdup_printf("fd=%ld%s", keyfile_fd, cipher);
2✔
2299
        logit(gl_LOGFILE, "  The TPM's state will be encrypted with a provided key (fd).\n");
2✔
2300
    } else if (pwdfile_fd >= 0) {
135✔
2301
        fds_to_pass[n_fds_to_pass++] = pwdfile_fd;
2✔
2302
        swtpm_keyopt = g_strdup_printf("pwdfd=%ld%s", pwdfile_fd, cipher);
2✔
2303
        logit(gl_LOGFILE, "  The TPM's state will be encrypted using a key derived from a passphrase (fd).\n");
2✔
2304
    }
2305

2306
    if ((flags & SETUP_TPM2_F) != 0) {
166✔
2307
        if (!ek1keyalgo_str)
140✔
2308
            ek1keyalgo_str = get_config_value(config_file_lines, "ek1keyalgo");
125✔
2309
        if (ek1keyalgo_str &&
140✔
2310
            !parse_keyalgo(ek1keyalgo_str, &ek1keyalgo, &ek1keyalgo_param, &flags))
15✔
2311
            goto error;
×
2312

2313
        if (!ek2keyalgo_str)
140✔
2314
            ek2keyalgo_str = get_config_value(config_file_lines, "ek2keyalgo");
125✔
2315
        if (ek2keyalgo_str &&
140✔
2316
            !parse_keyalgo(ek2keyalgo_str, &ek2keyalgo, &ek2keyalgo_param, &flags))
15✔
2317
            goto error;
×
2318

2319
        if (ek1keyalgo_param == 0 && ek1keyalgo == KEYALGO_RSA) {
140✔
2320
            if ((flags & SETUP_RSA_KEYSIZE_BY_USER_F) == 0)
125✔
2321
                rsa_keysize_str = get_default_rsa_keysize(config_file_lines);
105✔
2322

2323
            rsa_keysize = parse_rsa_keysize(flags, &rsa_keysize_str, swtpm_prg_l);
125✔
2324
            if (!rsa_keysize)
125✔
2325
                goto error;
×
2326
        } else {
2327
            if (ek1keyalgo == KEYALGO_RSA &&
25✔
2328
                !is_rsa_keysize_supported(flags, ek1keyalgo_param, swtpm_prg_l))
10✔
2329
                goto error;
×
2330
            if (ek2keyalgo == KEYALGO_RSA &&
22✔
2331
                !is_rsa_keysize_supported(flags, ek2keyalgo_param, swtpm_prg_l))
7✔
2332
                goto error;
×
2333
        }
2334

2335
        if (!iakkeyalgo_str)
140✔
2336
            iakkeyalgo_str = get_config_value(config_file_lines, "iakkeyalgo");
133✔
2337
        if (iakkeyalgo_str &&
140✔
2338
            !parse_keyalgo(iakkeyalgo_str, &iakkeyalgo, &iakkeyalgo_param, &flags))
7✔
2339
            goto error;
×
2340
        if (!idevidkeyalgo_str)
140✔
2341
            idevidkeyalgo_str = get_config_value(config_file_lines, "idevidkeyalgo");
133✔
2342
        if (idevidkeyalgo_str &&
140✔
2343
            !parse_keyalgo(idevidkeyalgo_str, &idevidkeyalgo, &idevidkeyalgo_param, &flags))
7✔
2344
            goto error;
×
2345

2346
        if ((iakkeyalgo != KEYALGO_NONE || idevidkeyalgo != KEYALGO_NONE) &&
140✔
2347
            (flags & SETUP_CREATE_EK_F)== 0 ) {
7✔
2348
            fprintf(stderr, "When creaing IAK and/or IDevID keys, then an EK certificate must be created as well.\n");
×
2349
            goto error;
×
2350
        }
2351
    }
2352

2353
    if (flags & SETUP_RECONFIGURE_F) {
166✔
2354
        if (flags & (SETUP_CREATE_EK_F | SETUP_EK_CERT_F | SETUP_PLATFORM_CERT_F)) {
6✔
2355
            logerr(gl_LOGFILE, "Reconfiguration is not supported with creation of EK or certificates\n");
×
2356
            goto error;
×
2357
        }
2358
    }
2359

2360
    now = time(NULL);
166✔
2361
    tm = localtime(&now);
166✔
2362
    if (strftime(tmpbuffer, sizeof(tmpbuffer), "%a %d %h %Y %I:%M:%S %p %Z", tm) == 0) {
166✔
2363
        logerr(gl_LOGFILE, "Could not format time/date string.\n");
×
2364
        goto error;
×
2365
    }
2366
    curr_grp = getgrgid(getgid());
166✔
2367
    logit(gl_LOGFILE, "Starting vTPM %s as %s:%s @ %s\n",
326✔
2368
          flags & SETUP_RECONFIGURE_F ? "reconfiguration" : "manufacturing",
2369
          curr_user ? curr_user->pw_name : "<unknown>",
2370
          curr_grp ? curr_grp->gr_name : "<unknown>",
2371
          tmpbuffer);
2372

2373
    if (flags & (SETUP_EK_CERT_F | SETUP_PLATFORM_CERT_F)) {
166✔
2374
        certsdir = g_dir_make_tmp("swtpm_setup.certs.XXXXXX", &error);
62✔
2375
        if (certsdir == NULL) {
62✔
2376
            logerr(gl_LOGFILE, "Could not create temporary directory for certs: %s\n",
×
2377
                   error->message);
×
2378
            goto error;
×
2379
        }
2380
        if (!no_iak)
62✔
2381
            flags |= SETUP_IAK_F | SETUP_IDEVID_F;
62✔
2382
    }
2383

2384
    if ((flags & SETUP_TPM2_F) == 0) {
166✔
2385
        ret = init_tpm(flags, swtpm_prg_l, config_file, tpm_state_path, ownerpass, srkpass, vmid,
26✔
2386
                       swtpm_keyopt, fds_to_pass, n_fds_to_pass, certsdir, user_certsdir);
2387
    } else {
2388
        if (ek1keyalgo_param == 0)
140✔
2389
            ek1keyalgo_param = rsa_keysize; // default
125✔
2390
        if (ek2keyalgo_param == 0)
140✔
2391
            ek2keyalgo_param = TPM2_ECC_NIST_P384; // default
125✔
2392

2393
        ret = init_tpm2(flags, swtpm_prg_l, config_file, tpm_state_path, vmid, pcr_banks,
140✔
2394
                       swtpm_keyopt, fds_to_pass, n_fds_to_pass,
2395
                       ek1keyalgo, ek1keyalgo_param,
2396
                       ek2keyalgo, ek2keyalgo_param,
2397
                       iakkeyalgo, iakkeyalgo_param,
2398
                       idevidkeyalgo, idevidkeyalgo_param,
2399
                       certsdir, user_certsdir, json_profile, json_profile_fd,
2400
                       profile_remove_disabled_param);
2401
    }
2402

2403
    if (ret == 0) {
166✔
2404
        logit(gl_LOGFILE, "Successfully authored TPM state.\n");
158✔
2405
    } else {
2406
        logerr(gl_LOGFILE, "An error occurred. Authoring the TPM state failed.\n");
8✔
2407
        backend_ops->delete_state(backend_state);
8✔
2408
    }
2409

2410
    now = time(NULL);
166✔
2411
    tm = localtime(&now);
166✔
2412
    if (strftime(tmpbuffer, sizeof(tmpbuffer), "%a %d %h %Y %I:%M:%S %p %Z", tm) == 0) {
166✔
2413
        logerr(gl_LOGFILE, "Could not format time/date string.\n");
×
2414
        goto error;
×
2415
    }
2416
    logit(gl_LOGFILE, "Ending vTPM manufacturing @ %s\n",
166✔
2417
          tmpbuffer);
2418

2419
out:
197✔
2420
    if (certsdir && g_rmdir(certsdir) != 0)
197✔
2421
        logerr(gl_LOGFILE, "Could not remove temporary directory for certs: %s\n",
×
2422
               strerror(errno));
×
2423

2424
    if (backend_ops && backend_state)
197✔
2425
        backend_ops->free_backend(backend_state);
172✔
2426
    g_strfreev(swtpm_prg_l);
197✔
2427
    g_free(gl_LOGFILE);
197✔
2428

2429
    return ret;
197✔
2430

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

© 2026 Coveralls, Inc