1 /* SPDX-License-Identifier: BSD-3-Clause */
3 * swtpm_setup.c: Tool to simulate TPM 1.2 & TPM 2 manufacturing
5 * Author: Stefan Berger, stefanb@linux.ibm.com
7 * Copyright (c) IBM Corporation, 2021
23 #include <sys/types.h>
26 #include <glib/gstdio.h>
27 #include <glib/gprintf.h>
29 #include <glib-object.h>
30 #include <json-glib/json-glib.h>
32 #include <libtpms/tpm_nvfilename.h>
35 #include "swtpm_setup_conf.h"
36 #include "swtpm_setup_utils.h"
37 #include "swtpm_utils.h"
39 #include <openssl/sha.h>
41 /* default values for passwords */
42 #define DEFAULT_OWNER_PASSWORD "ooo"
43 #define DEFAULT_SRK_PASSWORD "sss"
45 #define SETUP_CREATE_EK_F 1
46 #define SETUP_TAKEOWN_F 2
47 #define SETUP_EK_CERT_F 4
48 #define SETUP_PLATFORM_CERT_F 8
49 #define SETUP_LOCK_NVRAM_F 16
50 #define SETUP_SRKPASS_ZEROS_F 32
51 #define SETUP_OWNERPASS_ZEROS_F 64
52 #define SETUP_STATE_OVERWRITE_F 128
53 #define SETUP_STATE_NOT_OVERWRITE_F 256
54 #define SETUP_TPM2_F 512
55 #define SETUP_ALLOW_SIGNING_F 1024
56 #define SETUP_TPM2_ECC_F 2048
57 #define SETUP_CREATE_SPK_F 4096
58 #define SETUP_DISPLAY_RESULTS_F 8192
59 #define SETUP_DECRYPTION_F 16384
60 #define SETUP_WRITE_EK_CERT_FILES_F 32768
62 /* default configuration file */
63 #define SWTPM_SETUP_CONF "swtpm_setup.conf"
65 #define DEFAULT_PCR_BANKS "sha1,sha256"
67 /* Default logging goes to stderr */
68 gchar
*gl_LOGFILE
= NULL
;
70 #define DEFAULT_RSA_KEYSIZE 2048
73 static const struct flag_to_certfile
{
77 } flags_to_certfiles
[] = {
78 {.flag
= SETUP_EK_CERT_F
, .filename
= "ek.cert", .type
= "ek" },
79 {.flag
= SETUP_PLATFORM_CERT_F
, .filename
= "platform.cert", .type
= "platform" },
80 {.flag
= 0, .filename
= NULL
, .type
= NULL
},
83 /* initialize the path of the config_file */
84 static int init(gchar
**config_file
)
86 const gchar
*configdir
= g_get_user_config_dir();
88 *config_file
= g_build_filename(configdir
, SWTPM_SETUP_CONF
, NULL
);
89 if (access(*config_file
, R_OK
) != 0) {
91 *config_file
= g_build_filename(SYSCONFDIR
, SWTPM_SETUP_CONF
, NULL
);
97 /* Get the spec and attributes parameters from swtpm */
98 static int tpm_get_specs_and_attributes(struct swtpm
*swtpm
, gchar
***params
)
101 g_autofree gchar
*json
= NULL
;
102 JsonParser
*jp
= NULL
;
103 GError
*error
= NULL
;
104 JsonReader
*jr
= NULL
;
106 static const struct parse_rule
{
111 } parser_rules
[7] = {
112 {"TPMSpecification", "family", FALSE
, "--tpm-spec-family"},
113 {"TPMSpecification", "level", TRUE
, "--tpm-spec-level"},
114 {"TPMSpecification", "revision", TRUE
, "--tpm-spec-revision"},
115 {"TPMAttributes", "manufacturer", FALSE
, "--tpm-manufacturer"},
116 {"TPMAttributes", "model", FALSE
, "--tpm-model"},
117 {"TPMAttributes", "version", FALSE
, "--tpm-version"},
118 {NULL
, NULL
, FALSE
, NULL
},
122 ret
= swtpm
->cops
->ctrl_get_tpm_specs_and_attrs(swtpm
, &json
);
124 logerr(gl_LOGFILE
, "Could not get the TPM spec and attribute parameters.\n");
128 jp
= json_parser_new();
130 if (!json_parser_load_from_data(jp
, json
, -1, &error
)) {
131 logerr(gl_LOGFILE
, "JSON parser failed: %s\n", error
->message
);
137 root
= json_parser_get_root(jp
);
139 for (idx
= 0; parser_rules
[idx
].node1
!= NULL
; idx
++) {
140 jr
= json_reader_new(root
);
141 if (json_reader_read_member(jr
, parser_rules
[idx
].node1
) &&
142 json_reader_read_member(jr
, parser_rules
[idx
].node2
)) {
145 if (parser_rules
[idx
].is_int
)
146 str
= g_strdup_printf("%ld", (long)json_reader_get_int_value(jr
));
148 str
= g_strdup(json_reader_get_string_value(jr
));
150 *params
= concat_arrays(*params
,
152 g_strdup(parser_rules
[idx
].optname
),
157 logerr(gl_LOGFILE
, "Could not find [%s][%s] in '%s'\n",
158 parser_rules
[idx
].node1
, parser_rules
[idx
].node2
, json
);
177 /* Call an external tool to create the certificates */
178 static int call_create_certs(unsigned long flags
, const gchar
*configfile
, const gchar
*certsdir
,
179 const gchar
*ekparam
, const gchar
*vmid
, struct swtpm
*swtpm
)
181 gchar
**config_file_lines
= NULL
; /* must free */
182 g_autofree gchar
*create_certs_tool
= NULL
;
183 g_autofree gchar
*create_certs_tool_config
= NULL
;
184 g_autofree gchar
*create_certs_tool_options
= NULL
;
185 g_autofree gchar
**cmd
= NULL
;
186 gchar
**params
= NULL
; /* must free */
187 g_autofree gchar
*prgname
= NULL
;
194 ret
= tpm_get_specs_and_attributes(swtpm
, ¶ms
);
198 ret
= read_file_lines(configfile
, &config_file_lines
);
202 create_certs_tool
= get_config_value(config_file_lines
, "create_certs_tool");
203 create_certs_tool_config
= get_config_value(config_file_lines
, "create_certs_tool_config");
204 create_certs_tool_options
= get_config_value(config_file_lines
, "create_certs_tool_options");
208 if (create_certs_tool
!= NULL
) {
209 g_autofree gchar
*create_certs_tool_path
= g_find_program_in_path(create_certs_tool
);
210 if (create_certs_tool_path
== NULL
) {
211 logerr(gl_LOGFILE
, "Could not find %s in PATH.\n", create_certs_tool
);
216 if (flags
& SETUP_TPM2_F
) {
217 params
= concat_arrays(params
,
223 cmd
= concat_arrays((gchar
*[]) {
224 create_certs_tool_path
,
225 "--type", "_", /* '_' must be at index '2' ! */
226 "--ek", (gchar
*)ekparam
,
227 "--dir", (gchar
*)certsdir
,
230 if (gl_LOGFILE
!= NULL
)
231 cmd
= concat_arrays(cmd
, (gchar
*[]){"--logfile", (gchar
*)gl_LOGFILE
, NULL
}, TRUE
);
233 cmd
= concat_arrays(cmd
, (gchar
*[]){"--vmid", (gchar
*)vmid
, NULL
}, TRUE
);
234 cmd
= concat_arrays(cmd
, params
, TRUE
);
235 if (create_certs_tool_config
!= NULL
)
236 cmd
= concat_arrays(cmd
, (gchar
*[]){"--configfile", create_certs_tool_config
, NULL
}, TRUE
);
237 if (create_certs_tool_options
!= NULL
)
238 cmd
= concat_arrays(cmd
, (gchar
*[]){"--optsfile", create_certs_tool_options
, NULL
}, TRUE
);
240 s
= g_strrstr(create_certs_tool
, G_DIR_SEPARATOR_S
);
242 prgname
= strdup(&s
[1]);
244 prgname
= strdup(create_certs_tool
);
246 for (idx
= 0; flags_to_certfiles
[idx
].filename
!= NULL
; idx
++) {
247 if (flags
& flags_to_certfiles
[idx
].flag
) {
248 g_autofree gchar
*standard_output
= NULL
;
249 GError
*error
= NULL
;
252 cmd
[2] = (gchar
*)flags_to_certfiles
[idx
].type
; /* replaces the "_" above */
254 s
= g_strjoinv(" ", cmd
);
255 logit(gl_LOGFILE
, " Invoking %s\n", s
);
258 success
= g_spawn_sync(NULL
, cmd
, NULL
, G_SPAWN_STDERR_TO_DEV_NULL
, NULL
, NULL
,
259 &standard_output
, NULL
, &exit_status
, &error
);
261 logerr(gl_LOGFILE
, "An error occurred running %s: %s\n",
262 create_certs_tool
, error
->message
);
266 } else if (exit_status
!= 0) {
267 logerr(gl_LOGFILE
, "%s exit with status %d: %s\n",
268 prgname
, exit_status
, standard_output
);
273 lines
= g_strsplit(standard_output
, "\n", -1);
274 for (j
= 0; lines
[j
] != NULL
; j
++) {
275 if (strlen(lines
[j
]) > 0)
276 logit(gl_LOGFILE
, "%s: %s\n", prgname
, lines
[j
]);
280 g_free(standard_output
);
281 standard_output
= NULL
;
287 g_strfreev(config_file_lines
);
293 static char *create_ek_certfile_name(const gchar
*user_certsdir
, const gchar
*key_description
)
295 g_autofree gchar
*filename
= g_strdup_printf("ek-%s.crt", key_description
);
297 return g_strjoin(G_DIR_SEPARATOR_S
, user_certsdir
, filename
, NULL
);
301 * Remove the cert file unless the user wants a copy of it (EK only).
303 static int certfile_move_or_delete(unsigned long flags
, gboolean is_ek
, const gchar
*certfile
,
304 const gchar
*user_certsdir
, const gchar
*key_description
)
306 g_autofree gchar
*content
= NULL
;
307 g_autofree gchar
*cf
= NULL
;
308 gsize content_length
;
309 GError
*error
= NULL
;
312 if (is_ek
&& (flags
& SETUP_WRITE_EK_CERT_FILES_F
) && user_certsdir
!= NULL
) {
313 if (!g_file_get_contents(certfile
, &content
, &content_length
, &error
))
316 cf
= create_ek_certfile_name(user_certsdir
, key_description
);
317 if (!(flags
& SETUP_TPM2_F
)) {
318 /* A TPM 1.2 certificate has a 7 byte header at the beginning
319 * that we now remove */
320 if (content_length
>= 8)
323 if (!g_file_set_contents(cf
, &content
[offset
], content_length
- offset
,
326 if (g_chmod(cf
, S_IRUSR
| S_IWUSR
| S_IRGRP
) < 0) {
327 logerr(gl_LOGFILE
, "Failed to chmod file '%s': %s\n", cf
, strerror(errno
));
336 logerr(gl_LOGFILE
, "%s\n", error
->message
);
345 /* Create EK and certificate for a TPM 2 */
346 static int tpm2_create_ek_and_cert(unsigned long flags
, const gchar
*config_file
,
347 const gchar
*certsdir
, const gchar
*vmid
,
348 unsigned int rsa_keysize
, struct swtpm2
*swtpm2
,
349 const gchar
*user_certsdir
)
351 g_autofree gchar
*filecontent
= NULL
;
352 size_t filecontent_len
;
353 g_autofree gchar
*certfile
= NULL
;
354 g_autofree gchar
*ekparam
= NULL
;
355 const char *key_description
;
359 if (flags
& SETUP_CREATE_EK_F
) {
360 ret
= swtpm2
->ops
->create_ek(&swtpm2
->swtpm
, !!(flags
& SETUP_TPM2_ECC_F
), rsa_keysize
,
361 !!(flags
& SETUP_ALLOW_SIGNING_F
),
362 !!(flags
& SETUP_DECRYPTION_F
),
363 !!(flags
& SETUP_LOCK_NVRAM_F
),
364 &ekparam
, &key_description
);
369 if (flags
& (SETUP_EK_CERT_F
| SETUP_PLATFORM_CERT_F
)) {
370 ret
= call_create_certs(flags
, config_file
, certsdir
, ekparam
, vmid
, &swtpm2
->swtpm
);
374 for (idx
= 0; flags_to_certfiles
[idx
].filename
; idx
++) {
375 if (flags
& flags_to_certfiles
[idx
].flag
) {
377 certfile
= g_strjoin(G_DIR_SEPARATOR_S
, certsdir
, flags_to_certfiles
[idx
].filename
, NULL
);
381 ret
= read_file(certfile
, &filecontent
, &filecontent_len
);
385 if (flags_to_certfiles
[idx
].flag
== SETUP_EK_CERT_F
) {
386 ret
= swtpm2
->ops
->write_ek_cert_nvram(&swtpm2
->swtpm
,
387 !!(flags
& SETUP_TPM2_ECC_F
), rsa_keysize
,
388 !!(flags
& SETUP_LOCK_NVRAM_F
),
389 (const unsigned char*)filecontent
, filecontent_len
);
391 ret
= swtpm2
->ops
->write_platform_cert_nvram(&swtpm2
->swtpm
,
392 !!(flags
& SETUP_LOCK_NVRAM_F
),
393 (const unsigned char *)filecontent
, filecontent_len
);
401 if (certfile_move_or_delete(flags
, !!(flags_to_certfiles
[idx
].flag
& SETUP_EK_CERT_F
),
402 certfile
, user_certsdir
, key_description
) != 0)
411 /* Create endorsement keys and certificates for a TPM 2 */
412 static int tpm2_create_eks_and_certs(unsigned long flags
, const gchar
*config_file
,
413 const gchar
*certsdir
, const gchar
*vmid
,
414 unsigned int rsa_keysize
, struct swtpm2
*swtpm2
,
415 const gchar
*user_certsdir
)
419 /* 1st key will be RSA */
420 flags
= flags
& ~SETUP_TPM2_ECC_F
;
421 ret
= tpm2_create_ek_and_cert(flags
, config_file
, certsdir
, vmid
, rsa_keysize
, swtpm2
,
426 /* 2nd key will be an ECC; no more platform cert */
427 flags
= (flags
& ~SETUP_PLATFORM_CERT_F
) | SETUP_TPM2_ECC_F
;
428 return tpm2_create_ek_and_cert(flags
, config_file
, certsdir
, vmid
, rsa_keysize
, swtpm2
,
432 /* Simulate manufacturing a TPM 2: create keys and certificates */
433 static int init_tpm2(unsigned long flags
, gchar
**swtpm_prg_l
, const gchar
*config_file
,
434 const gchar
*tpm2_state_path
, const gchar
*vmid
, const gchar
*pcr_banks
,
435 const gchar
*swtpm_keyopt
, int *fds_to_pass
, size_t n_fds_to_pass
,
436 unsigned int rsa_keysize
, const gchar
*certsdir
,
437 const gchar
*user_certsdir
)
439 struct swtpm2
*swtpm2
;
443 swtpm2
= swtpm2_new(swtpm_prg_l
, tpm2_state_path
, swtpm_keyopt
, gl_LOGFILE
,
444 fds_to_pass
, n_fds_to_pass
);
447 swtpm
= &swtpm2
->swtpm
;
449 ret
= swtpm
->cops
->start(swtpm
);
451 logerr(gl_LOGFILE
, "Could not start the TPM 2.\n");
455 if ((flags
& SETUP_CREATE_SPK_F
)) {
456 ret
= swtpm2
->ops
->create_spk(swtpm
, !!(flags
& SETUP_TPM2_ECC_F
), rsa_keysize
);
461 ret
= tpm2_create_eks_and_certs(flags
, config_file
, certsdir
, vmid
, rsa_keysize
, swtpm2
,
466 if (strcmp(pcr_banks
, "-") != 0) {
467 gchar
**all_pcr_banks
= NULL
;
469 ret
= swtpm2
->ops
->get_all_pcr_banks(swtpm
, &all_pcr_banks
);
471 gchar
**active_pcr_banks
= NULL
;
472 gchar
**pcr_banks_l
= g_strsplit(pcr_banks
, ",", -1);
473 ret
= swtpm2
->ops
->set_active_pcr_banks(swtpm
, pcr_banks_l
, all_pcr_banks
,
475 g_strfreev(pcr_banks_l
);
477 g_autofree gchar
*active_pcr_banks_join
= g_strjoinv(",", active_pcr_banks
);
478 g_autofree gchar
*all_pcr_banks_join
= g_strjoinv(",", all_pcr_banks
);
479 logit(gl_LOGFILE
, "Successfully activated PCR banks %s among %s.\n",
480 active_pcr_banks_join
, all_pcr_banks_join
);
482 g_strfreev(active_pcr_banks
);
484 g_strfreev(all_pcr_banks
);
490 ret
= swtpm2
->ops
->shutdown(swtpm
);
493 swtpm
->cops
->destroy(swtpm
);
501 /* Create the owner password digest */
502 static void tpm12_get_ownerpass_digest(unsigned long flags
, const gchar
*ownerpass
,
503 unsigned char ownerpass_digest
[SHA_DIGEST_LENGTH
])
505 const gchar zeros
[SHA_DIGEST_LENGTH
]= {0, };
508 if (ownerpass
== NULL
) {
509 if (flags
& SETUP_OWNERPASS_ZEROS_F
) {
513 ownerpass
= DEFAULT_OWNER_PASSWORD
;
514 len
= strlen(ownerpass
);
517 len
= strlen(ownerpass
);
519 SHA1((const unsigned char *)ownerpass
, len
, ownerpass_digest
);
522 /* Create the SRK password digest */
523 static void tpm12_get_srkpass_digest(unsigned long flags
, const gchar
*srkpass
,
524 unsigned char srkpass_digest
[SHA_DIGEST_LENGTH
])
526 const gchar zeros
[SHA_DIGEST_LENGTH
]= {0, };
529 if (srkpass
== NULL
) {
530 if (flags
& SETUP_SRKPASS_ZEROS_F
) {
534 srkpass
= DEFAULT_SRK_PASSWORD
;
535 len
= strlen(srkpass
);
538 len
= strlen(srkpass
);
540 SHA1((const unsigned char *)srkpass
, len
, srkpass_digest
);
543 /* Take ownership of a TPM 1.2 */
544 static int tpm12_take_ownership(unsigned long flags
, const gchar
*ownerpass
,
545 const gchar
*srkpass
, gchar
*pubek
, size_t pubek_len
,
546 struct swtpm12
*swtpm12
)
548 unsigned char ownerpass_digest
[SHA_DIGEST_LENGTH
];
549 unsigned char srkpass_digest
[SHA_DIGEST_LENGTH
];
551 tpm12_get_ownerpass_digest(flags
, ownerpass
, ownerpass_digest
);
552 tpm12_get_srkpass_digest(flags
, srkpass
, srkpass_digest
);
554 return swtpm12
->ops
->take_ownership(&swtpm12
->swtpm
, ownerpass_digest
, srkpass_digest
,
555 (const unsigned char *)pubek
, pubek_len
);
558 /* Create the certificates for a TPM 1.2 */
559 static int tpm12_create_certs(unsigned long flags
, const gchar
*config_file
,
560 const gchar
*certsdir
, const gchar
*ekparam
,
561 const gchar
*vmid
, struct swtpm12
*swtpm12
,
562 const gchar
*user_certsdir
)
564 g_autofree gchar
*filecontent
= NULL
;
565 g_autofree gchar
*certfile
= NULL
;
566 gsize filecontent_len
;
570 ret
= call_create_certs(flags
, config_file
, certsdir
, ekparam
, vmid
, &swtpm12
->swtpm
);
574 for (idx
= 0; flags_to_certfiles
[idx
].filename
; idx
++) {
575 if (flags
& flags_to_certfiles
[idx
].flag
) {
577 certfile
= g_strjoin(G_DIR_SEPARATOR_S
, certsdir
,
578 flags_to_certfiles
[idx
].filename
, NULL
);
582 ret
= read_file(certfile
, &filecontent
, &filecontent_len
);
586 if (flags_to_certfiles
[idx
].flag
== SETUP_EK_CERT_F
) {
587 ret
= swtpm12
->ops
->write_ek_cert_nvram(&swtpm12
->swtpm
,
588 (const unsigned char*)filecontent
, filecontent_len
);
590 logit(gl_LOGFILE
, "Successfully created NVRAM area for EK certificate.\n");
592 ret
= swtpm12
->ops
->write_platform_cert_nvram(&swtpm12
->swtpm
,
593 (const unsigned char*)filecontent
, filecontent_len
);
595 logit(gl_LOGFILE
, "Successfully created NVRAM area for Platform certificate.\n");
603 if (certfile_move_or_delete(flags
, !!(flags_to_certfiles
[idx
].flag
& SETUP_EK_CERT_F
),
604 certfile
, user_certsdir
, "rsa2048") != 0)
612 /* Simulate manufacturing a TPM 1.2: create keys and certificate and possibly take ownership */
613 static int init_tpm(unsigned long flags
, gchar
**swtpm_prg_l
, const gchar
*config_file
,
614 const gchar
*tpm_state_path
, const gchar
*ownerpass
, const gchar
*srkpass
,
615 const gchar
*vmid
, const gchar
*swtpm_keyopt
,
616 int *fds_to_pass
, size_t n_fds_to_pass
, const gchar
*certsdir
,
617 const gchar
*user_certsdir
)
619 struct swtpm12
*swtpm12
;
621 g_autofree gchar
*pubek
= NULL
;
625 swtpm12
= swtpm12_new(swtpm_prg_l
, tpm_state_path
, swtpm_keyopt
, gl_LOGFILE
,
626 fds_to_pass
, n_fds_to_pass
);
629 swtpm
= &swtpm12
->swtpm
;
631 ret
= swtpm
->cops
->start(swtpm
);
633 logerr(gl_LOGFILE
, "Could not start the TPM 1.2.\n");
637 ret
= swtpm12
->ops
->run_swtpm_bios(swtpm
);
641 if ((flags
& SETUP_CREATE_EK_F
)) {
642 ret
= swtpm12
->ops
->create_endorsement_key_pair(swtpm
, &pubek
, &pubek_len
);
646 logit(gl_LOGFILE
, "Successfully created EK.\n");
648 /* can only take owernship if created an EK */
649 if ((flags
& SETUP_TAKEOWN_F
)) {
650 ret
= tpm12_take_ownership(flags
, ownerpass
, srkpass
, pubek
, pubek_len
, swtpm12
);
654 logit(gl_LOGFILE
, "Successfully took ownership of the TPM.\n");
657 /* can only create EK cert if created an EK */
658 if ((flags
& SETUP_EK_CERT_F
)) {
659 g_autofree gchar
*ekparam
= print_as_hex((unsigned char *)pubek
, pubek_len
);
661 ret
= tpm12_create_certs(flags
, config_file
, certsdir
, ekparam
, vmid
, swtpm12
,
668 if ((flags
& SETUP_LOCK_NVRAM_F
)) {
669 ret
= swtpm12
->ops
->nv_lock(swtpm
);
671 logit(gl_LOGFILE
, "Successfully locked NVRAM access.\n");
675 swtpm
->cops
->destroy(swtpm
);
683 /* Check whether we are allowed to overwrite existing state.
684 * This function returns 2 if the state exists but flag is set to not to overwrite it,
685 * 0 in case we can overwrite it, 1 if the state exists.
687 static int check_state_overwrite(gchar
**swtpm_prg_l
, unsigned int flags
,
688 const char *tpm_state_path
)
691 g_autofree gchar
*standard_output
= NULL
;
693 g_autoptr(GError
) error
= NULL
;
694 g_autofree gchar
**argv
= NULL
;
695 g_autofree gchar
*statearg
= g_strdup_printf("backend-uri=%s", tpm_state_path
);
696 g_autofree gchar
*logop
= NULL
;
697 g_autofree gchar
**my_argv
= NULL
;
699 my_argv
= concat_arrays((gchar
*[]) {
706 if (flags
& SETUP_TPM2_F
)
707 my_argv
= concat_arrays(my_argv
, (gchar
*[]) { "--tpm2", NULL
}, TRUE
);
709 if (gl_LOGFILE
!= NULL
) {
710 logop
= g_strdup_printf("file=%s", gl_LOGFILE
);
711 my_argv
= concat_arrays(my_argv
, (gchar
*[]){"--log", logop
, NULL
}, TRUE
);
714 argv
= concat_arrays(swtpm_prg_l
, my_argv
, FALSE
);
716 success
= g_spawn_sync(NULL
, argv
, NULL
, G_SPAWN_STDERR_TO_DEV_NULL
, NULL
, NULL
,
717 &standard_output
, NULL
, &exit_status
, &error
);
719 logerr(gl_LOGFILE
, "Could not start swtpm '%s': %s\n", swtpm_prg_l
[0], error
->message
);
723 if (exit_status
!= 0) {
724 logerr(gl_LOGFILE
, "%s exit with status %d: %s\n",
725 swtpm_prg_l
[0], exit_status
, standard_output
);
729 if (g_strstr_len(standard_output
, -1, TPM_PERMANENT_ALL_NAME
) != NULL
) {
730 /* State file exists */
731 if (flags
& SETUP_STATE_NOT_OVERWRITE_F
) {
732 logit(gl_LOGFILE
, "Not overwriting existing state file.\n");
735 if (flags
& SETUP_STATE_OVERWRITE_F
)
737 logerr(gl_LOGFILE
, "Found existing TPM state '%s'.\n", TPM_PERMANENT_ALL_NAME
);
744 static void versioninfo(void)
746 printf("TPM emulator setup tool version %d.%d.%d\n",
747 SWTPM_VER_MAJOR
, SWTPM_VER_MINOR
, SWTPM_VER_MICRO
);
750 static void usage(const char *prgname
, const char *default_config_file
)
754 "Usage: %s [options]\n"
756 "The following options are supported:\n"
758 "--runas <user> : Run this program under the given user's account.\n"
760 "--tpm-state <dir>: Path where the TPM's state will be written to;\n"
761 " this is a mandatory argument. Prefix with dir:// to"
762 " use directory backend, or file:// to use linear file.\n"
764 "--tpmstate <dir> : This is an alias for --tpm-state <dir>.\n"
766 "--tpm <executable>\n"
767 " : Path to the TPM executable; this is an optional argument and\n"
768 " by default 'swtpm' in the PATH is used.\n"
770 "--swtpm_ioctl <executable>\n"
771 " : Path to the swtpm_ioctl executable; this is deprecated\n"
774 "--tpm2 : Setup a TPM 2; by default a TPM 1.2 is setup.\n"
776 "--createek : Create the EK; for a TPM 2 an RSA and ECC EK will be\n"
779 "--allow-signing : Create an EK that can be used for signing;\n"
780 " this option requires --tpm2.\n"
781 " Note: Careful, this option will create a non-standard EK!\n"
783 "--decryption : Create an EK that can be used for key encipherment;\n"
784 " this is the default unless --allow-signing is given;\n"
785 " this option requires --tpm2.\n"
787 "--ecc : This option allows to create a TPM 2's ECC key as storage\n"
788 " primary key; a TPM 2 always gets an RSA and an ECC EK key.\n"
790 "--take-ownership : Take ownership; this option implies --createek\n"
791 " --ownerpass <password>\n"
792 " : Provide custom owner password; default is %s\n"
793 " --owner-well-known:\n"
794 " : Use an owner password of 20 zero bytes\n"
795 " --srkpass <password>\n"
796 " : Provide custom SRK password; default is %s\n"
797 " --srk-well-known:\n"
798 " : Use an SRK password of 20 zero bytes\n"
799 "--create-ek-cert : Create an EK certificate; this implies --createek\n"
801 "--create-platform-cert\n"
802 " : Create a platform certificate; this implies --create-ek-cert\n"
804 "--create-spk : Create storage primary key; this requires --tpm2\n"
806 "--lock-nvram : Lock NVRAM access\n"
808 "--display : At the end display as much info as possible about the\n"
809 " configuration of the TPM\n"
811 "--config <config file>\n"
812 " : Path to configuration file; default is %s\n"
814 "--logfile <logfile>\n"
815 " : Path to log file; default is logging to stderr\n"
817 "--keyfile <keyfile>\n"
818 " : Path to a key file containing the encryption key for the\n"
819 " TPM to encrypt its persistent state with. The content\n"
820 " must be a 32 hex digit number representing a 128bit AES key.\n"
821 " This parameter will be passed to the TPM using\n"
822 " '--key file=<file>'.\n"
824 "--keyfile-fd <fd>: Like --keyfile but a file descriptor is given to read the\n"
825 " encryption key from.\n"
827 "--pwdfile <pwdfile>\n"
828 " : Path to a file containing a passphrase from which the\n"
829 " TPM will derive the 128bit AES key. The passphrase can be\n"
831 " This parameter will be passed to the TPM using\n"
832 " '--key pwdfile=<file>'.\n"
834 "--pwdfile-fd <fd>: Like --pwdfile but a file descriptor is given to to read\n"
835 " the passphrase from.\n"
837 "--cipher <cipher>: The cipher to use; either aes-128-cbc or aes-256-cbc;\n"
838 " the default is aes-128-cbc; the same cipher must be\n"
839 " used on the swtpm command line\n"
841 "--overwrite : Overwrite existing TPM state by re-initializing it; if this\n"
842 " option is not given, this program will return an error if\n"
843 " existing state is detected\n"
845 "--not-overwrite : Do not overwrite existing TPM state but silently end\n"
847 "--pcr-banks <banks>\n"
848 " : Set of PCR banks to activate. Provide a comma separated list\n"
849 " like 'sha1,sha256'. '-' to skip and leave all banks active.\n"
852 "--rsa-keysize <keysize>\n"
853 " : The RSA key size of the EK key; 3072 bits may be supported\n"
854 " if libtpms supports it.\n"
857 "--write-ek-cert-files <directory>\n"
858 " : Write EK cert files into the given directory\n"
860 "--tcsd-system-ps-file <file>\n"
861 " : This option is deprecated and has no effect.\n"
863 "--print-capabilities\n"
864 " : Print JSON formatted capabilites added after v0.1 and exit.\n"
866 "--create-config-files [[overwrite][,root]]\n"
867 " : Create swtpm_setup and swtpm-localca config files for a\n"
869 " overwrite: overwrite any existing files\n"
870 " root: allow to create files under root's home directory\n"
871 " skip-if-exist: if any file exists exit without error\n"
873 "--version : Display version and exit\n"
875 "--help,-h : Display this help screen\n\n",
877 DEFAULT_OWNER_PASSWORD
,
878 DEFAULT_SRK_PASSWORD
,
885 static int get_supported_tpm_versions(gchar
**swtpm_prg_l
, gboolean
*swtpm_has_tpm12
,
886 gboolean
*swtpm_has_tpm2
)
889 g_autofree gchar
*standard_output
= NULL
;
891 g_autoptr(GError
) error
= NULL
;
892 g_autofree gchar
**argv
= NULL
;
893 gchar
*my_argv
[] = { "--print-capabilities", NULL
};
894 g_autofree gchar
*logop
= NULL
;
896 argv
= concat_arrays(swtpm_prg_l
, my_argv
, FALSE
);
898 if (gl_LOGFILE
!= NULL
) {
899 logop
= g_strdup_printf("file=%s", gl_LOGFILE
);
900 argv
= concat_arrays(argv
, (gchar
*[]){"--log", logop
, NULL
}, TRUE
);
903 success
= g_spawn_sync(NULL
, argv
, NULL
, G_SPAWN_STDERR_TO_DEV_NULL
, NULL
, NULL
,
904 &standard_output
, NULL
, &exit_status
, &error
);
906 logerr(gl_LOGFILE
, "Could not start swtpm '%s': %s\n", swtpm_prg_l
[0], error
->message
);
910 *swtpm_has_tpm12
= g_strstr_len(standard_output
, -1, "\"tpm-1.2\"") != NULL
;
911 *swtpm_has_tpm2
= g_strstr_len(standard_output
, -1, "\"tpm-2.0\"") != NULL
;
916 /* Get the support RSA key sizes.
917 * This function returns an array of ints like the following
918 * - [ 1024, 2048, 3072 ]
919 * - [] (empty array, indicating only 2048 bit RSA keys are supported)
921 static int get_rsa_keysizes(unsigned long flags
, gchar
**swtpm_prg_l
,
922 unsigned int **keysizes
, size_t *n_keysizes
)
925 gchar
*standard_output
= NULL
;
927 GError
*error
= NULL
;
929 const gchar
*needle
= "\"rsa-keysize-";
930 unsigned int keysize
;
934 g_autofree gchar
*logop
= NULL
;
938 if (flags
& SETUP_TPM2_F
) {
939 gchar
*my_argv
[] = { "--tpm2", "--print-capabilities", NULL
};
941 argv
= concat_arrays(swtpm_prg_l
, my_argv
, FALSE
);
943 if (gl_LOGFILE
!= NULL
) {
944 logop
= g_strdup_printf("file=%s", gl_LOGFILE
);
945 argv
= concat_arrays(argv
, (gchar
*[]){"--log", logop
, NULL
}, TRUE
);
948 success
= g_spawn_sync(NULL
, argv
, NULL
, G_SPAWN_STDERR_TO_DEV_NULL
, NULL
, NULL
,
949 &standard_output
, NULL
, &exit_status
, &error
);
951 logerr(gl_LOGFILE
, "Could not start swtpm '%s': %s\n", swtpm_prg_l
[0], error
->message
);
957 /* A crude way of parsing the json output just looking for "rsa-keysize-%u" */
958 while ((p
= g_strstr_len(p
, -1, needle
)) != NULL
) {
960 n
= sscanf(p
, "%u\"", &keysize
);
962 *keysizes
= g_realloc(*keysizes
, (*n_keysizes
+ 1) * sizeof(unsigned int));
963 (*keysizes
)[*n_keysizes
] = keysize
;
972 g_free(standard_output
);
977 /* Return the RSA key size capabilities in a NULL-terminated array */
978 static int get_rsa_keysize_caps(unsigned long flags
, gchar
**swtpm_prg_l
,
979 gchar
***keysize_strs
)
981 unsigned int *keysizes
= NULL
;
982 size_t n_keysizes
= 0;
984 int ret
= get_rsa_keysizes(flags
, swtpm_prg_l
, &keysizes
, &n_keysizes
);
988 *keysize_strs
= g_malloc0(sizeof(char *) * (n_keysizes
+ 1));
989 for (i
= 0, j
= 0; i
< n_keysizes
; i
++) {
990 if (keysizes
[i
] >= 2048)
991 (*keysize_strs
)[j
++] = g_strdup_printf("tpm2-rsa-keysize-%u", keysizes
[i
]);
999 /* Print teh JSON object of swtpm_setup's capabilities */
1000 static int print_capabilities(char **swtpm_prg_l
, gboolean swtpm_has_tpm12
,
1001 gboolean swtpm_has_tpm2
)
1003 g_autofree gchar
*param
= g_strdup("");
1004 gchar
**keysize_strs
= NULL
;
1009 ret
= get_rsa_keysize_caps(SETUP_TPM2_F
, swtpm_prg_l
, &keysize_strs
);
1013 for (i
= 0; keysize_strs
[i
] != NULL
; i
++) {
1014 tmp
= g_strdup_printf("%s, \"%s\"", param
, keysize_strs
[i
]);
1019 printf("{ \"type\": \"swtpm_setup\", "
1020 "\"features\": [ %s%s\"cmdarg-keyfile-fd\", \"cmdarg-pwdfile-fd\", \"tpm12-not-need-root\""
1021 ", \"cmdarg-write-ek-cert-files\", \"cmdarg-create-config-files\""
1023 "\"version\": \"" VERSION
"\" "
1025 swtpm_has_tpm12
? "\"tpm-1.2\", " : "",
1026 swtpm_has_tpm2
? "\"tpm-2.0\", " : "",
1029 g_strfreev(keysize_strs
);
1034 static int change_process_owner(const char *user
)
1037 unsigned long long uid
= strtoull(user
, &endptr
, 10);
1039 struct passwd
*passwd
;
1042 if (*endptr
!= '\0') {
1043 /* assuming a name */
1044 passwd
= getpwnam(user
);
1045 if (passwd
== NULL
) {
1046 logerr(gl_LOGFILE
, "Error: User '%s' does not exist.\n", user
);
1050 if (initgroups(passwd
->pw_name
, passwd
->pw_gid
) != 0) {
1051 logerr(gl_LOGFILE
, "Error: initgroups() failed: %s\n", strerror(errno
));
1055 gid
= passwd
->pw_gid
;
1056 uid
= passwd
->pw_uid
;
1058 if (uid
> 0xffffffff) {
1059 logerr(gl_LOGFILE
, "Error: uid %s outside valid range.\n", user
);
1065 if (setgid(gid
) != 0) {
1066 logerr(gl_LOGFILE
, "Error: setgid(%d) failed: %s\n", gid
, strerror(errno
));
1070 if (setuid(uid
) != 0) {
1071 logerr(gl_LOGFILE
, "Error: setuid(%d) failed: %s\n", uid
, strerror(errno
));
1081 static int handle_create_config_files(const char *optarg
)
1083 g_auto(GStrv
) tokens
= NULL
;
1084 gboolean overwrite
= FALSE
;
1085 gboolean root_flag
= FALSE
;
1086 gboolean skip_if_exist
= FALSE
;
1089 tokens
= g_strsplit_set(optarg
, ", ", -1);
1090 overwrite
= g_strv_contains((const gchar
**)tokens
, "overwrite");
1091 root_flag
= g_strv_contains((const gchar
**)tokens
, "root");
1092 skip_if_exist
= g_strv_contains((const gchar
**)tokens
, "skip-if-exist");
1093 if (overwrite
&& skip_if_exist
) {
1094 fprintf(stderr
, "Error: overwrite and skip-if-exist cannot both be used\n");
1099 return create_config_files(overwrite
, root_flag
, skip_if_exist
);
1102 int main(int argc
, char *argv
[])
1104 int opt
, option_index
= 0;
1105 static const struct option long_options
[] = {
1106 {"tpm-state", required_argument
, NULL
, 't'},
1107 {"tpmstate", required_argument
, NULL
, 't'}, /* alias for tpm-state */
1108 {"tpm", required_argument
, NULL
, 'T'},
1109 {"swtpm_ioctl", required_argument
, NULL
, '_'},
1110 {"tpm2", no_argument
, NULL
, '2'},
1111 {"ecc", no_argument
, NULL
, 'e'},
1112 {"createek", no_argument
, NULL
, 'c'},
1113 {"create-spk", no_argument
, NULL
, 'C'},
1114 {"take-ownership", no_argument
, NULL
, 'o'},
1115 {"ownerpass", required_argument
, NULL
, 'O'},
1116 {"owner-well-known", no_argument
, NULL
, 'w'},
1117 {"srkpass", required_argument
, NULL
, 'S'},
1118 {"srk-well-known", no_argument
, NULL
, 's'},
1119 {"create-ek-cert", no_argument
, NULL
, 'E'},
1120 {"create-platform-cert", no_argument
, NULL
, 'P'},
1121 {"lock-nvram", no_argument
, NULL
, 'L'},
1122 {"display", no_argument
, NULL
, 'i'},
1123 {"config", required_argument
, NULL
, 'f'},
1124 {"vmid", required_argument
, NULL
, 'm'},
1125 {"keyfile", required_argument
, NULL
, 'x'},
1126 {"keyfile-fd", required_argument
, NULL
, 'X'},
1127 {"pwdfile", required_argument
, NULL
, 'k'},
1128 {"pwdfile-fd", required_argument
, NULL
, 'K'},
1129 {"cipher", required_argument
, NULL
, 'p'},
1130 {"runas", required_argument
, NULL
, 'r'},
1131 {"logfile", required_argument
, NULL
, 'l'},
1132 {"overwrite", no_argument
, NULL
, 'v'},
1133 {"not-overwrite", no_argument
, NULL
, 'V'},
1134 {"allow-signing", no_argument
, NULL
, 'a'},
1135 {"decryption", no_argument
, NULL
, 'd'},
1136 {"pcr-banks", required_argument
, NULL
, 'b'},
1137 {"rsa-keysize", required_argument
, NULL
, 'A'},
1138 {"write-ek-cert-files", required_argument
, NULL
, '3'},
1139 {"create-config-files", optional_argument
, NULL
, 'u'},
1140 {"tcsd-system-ps-file", required_argument
, NULL
, 'F'},
1141 {"version", no_argument
, NULL
, '1'},
1142 {"print-capabilities", no_argument
, NULL
, 'y'},
1143 {"help", no_argument
, NULL
, 'h'},
1146 unsigned long flags
= 0;
1147 g_autofree gchar
*swtpm_prg
= NULL
;
1148 g_autofree gchar
*tpm_state_path
= NULL
;
1149 struct swtpm_backend_ops
*backend_ops
= &swtpm_backend_dir
;
1150 void *backend_state
= NULL
;
1151 g_autofree gchar
*config_file
= NULL
;
1152 g_autofree gchar
*ownerpass
= NULL
;
1153 gboolean got_ownerpass
= FALSE
;
1154 g_autofree gchar
*srkpass
= NULL
;
1155 gboolean got_srkpass
= FALSE
;
1156 g_autofree gchar
*vmid
= NULL
;
1157 g_autofree gchar
*pcr_banks
= NULL
;
1158 gboolean printcapabilities
= FALSE
;
1159 g_autofree gchar
*keyfile
= NULL
;
1160 long int keyfile_fd
= -1;
1161 g_autofree gchar
*pwdfile
= NULL
;
1162 long int pwdfile_fd
= -1;
1163 g_autofree gchar
*cipher
= g_strdup("aes-128-cbc");
1164 g_autofree gchar
*rsa_keysize_str
= g_strdup_printf("%d", DEFAULT_RSA_KEYSIZE
);
1165 unsigned int rsa_keysize
;
1166 g_autofree gchar
*swtpm_keyopt
= NULL
;
1167 g_autofree gchar
*runas
= NULL
;
1168 g_autofree gchar
*certsdir
= NULL
;
1169 g_autofree gchar
*user_certsdir
= NULL
;
1171 gchar
**swtpm_prg_l
= NULL
;
1172 gchar
**tmp_l
= NULL
;
1174 struct stat statbuf
;
1175 const struct passwd
*curr_user
;
1176 struct group
*curr_grp
;
1178 gboolean swtpm_has_tpm12
= FALSE
;
1179 gboolean swtpm_has_tpm2
= FALSE
;
1180 int fds_to_pass
[1] = { -1 };
1181 unsigned n_fds_to_pass
= 0;
1182 char tmpbuffer
[200];
1186 g_autoptr(GError
) error
= NULL
;
1188 if (init(&config_file
) < 0)
1191 swtpm_prg
= g_find_program_in_path("swtpm");
1193 tmp
= g_strconcat(swtpm_prg
, " socket", NULL
);
1198 while ((opt
= getopt_long(argc
, argv
, "h?",
1199 long_options
, &option_index
)) != -1) {
1201 case 't': /* --tpmstate, --tpm-state */
1202 g_free(tpm_state_path
);
1203 if (strncmp(optarg
, "dir://", 6) == 0) {
1204 tpm_state_path
= g_strdup(optarg
);
1205 } else if (strncmp(optarg
, "file://", 7) == 0) {
1206 tpm_state_path
= g_strdup(optarg
);
1207 backend_ops
= &swtpm_backend_file
;
1209 /* always prefix with dir:// so we can pass verbatim to swtpm */
1210 tpm_state_path
= g_strconcat("dir://", optarg
, NULL
);
1213 case 'T': /* --tpm */
1215 swtpm_prg
= g_strdup(optarg
);
1217 case '_': /* --swtpm_ioctl */
1218 fprintf(stdout
, "Warning: --swtpm_ioctl is deprecated and has no effect.");
1220 case '2': /* --tpm2 */
1221 flags
|= SETUP_TPM2_F
;
1223 case 'e': /* --ecc */
1224 flags
|= SETUP_TPM2_ECC_F
;
1226 case 'c': /* --createek */
1227 flags
|= SETUP_CREATE_EK_F
;
1229 case 'C': /* --create-spk */
1230 flags
|= SETUP_CREATE_SPK_F
;
1232 case 'o': /* --take-ownership */
1233 flags
|= SETUP_CREATE_EK_F
| SETUP_TAKEOWN_F
;
1235 case 'O': /* --ownerpass */
1237 ownerpass
= g_strdup(optarg
);
1238 got_ownerpass
= TRUE
;
1240 case 'w': /* --owner-well-known */
1241 flags
|= SETUP_OWNERPASS_ZEROS_F
;
1242 got_ownerpass
= TRUE
;
1244 case 'S': /* --srk-pass */
1246 srkpass
= g_strdup(optarg
);
1249 case 's': /* --srk-well-known */
1250 flags
|= SETUP_SRKPASS_ZEROS_F
;
1253 case 'E': /* --create-ek-cert */
1254 flags
|= SETUP_CREATE_EK_F
| SETUP_EK_CERT_F
;
1256 case 'P': /* --create-platform-cert */
1257 flags
|= SETUP_CREATE_EK_F
| SETUP_PLATFORM_CERT_F
;
1259 case 'L': /* --lock-nvram */
1260 flags
|= SETUP_LOCK_NVRAM_F
;
1262 case 'i': /* --display */
1263 flags
|= SETUP_DISPLAY_RESULTS_F
;
1265 case 'f': /* --config */
1266 g_free(config_file
);
1267 config_file
= g_strdup(optarg
);
1269 case 'm': /* --vmid */
1271 vmid
= g_strdup(optarg
);
1273 case 'x': /* --keyfile */
1275 keyfile
= g_strdup(optarg
);
1277 case 'X': /* --pwdfile-fd' */
1278 keyfile_fd
= strtoull(optarg
, &endptr
, 10);
1279 if (*endptr
!= '\0' && keyfile_fd
>= INT_MAX
) {
1280 fprintf(stderr
, "Invalid file descriptor '%s'\n", optarg
);
1284 case 'k': /* --pwdfile */
1286 pwdfile
= g_strdup(optarg
);
1288 case 'K': /* --pwdfile-fd' */
1289 pwdfile_fd
= strtoull(optarg
, &endptr
, 10);
1290 if (*endptr
!= '\0' || pwdfile_fd
>= INT_MAX
) {
1291 fprintf(stderr
, "Invalid file descriptor '%s'\n", optarg
);
1295 case 'p': /* --cipher */
1297 cipher
= g_strdup(optarg
);
1299 case 'r': /* --runas */
1301 runas
= g_strdup(optarg
);
1303 case 'l': /* --logfile */
1305 gl_LOGFILE
= g_strdup(optarg
);
1307 case 'v': /* --overwrite */
1308 flags
|= SETUP_STATE_OVERWRITE_F
;
1310 case 'V': /* --not-overwrite */
1311 flags
|= SETUP_STATE_NOT_OVERWRITE_F
;
1313 case 'a': /* --allow-signing */
1314 flags
|= SETUP_ALLOW_SIGNING_F
;
1316 case 'd': /* --decryption */
1317 flags
|= SETUP_DECRYPTION_F
;
1319 case 'b': /* --pcr-banks */
1320 tmp
= g_strconcat(pcr_banks
? pcr_banks
: "",
1321 pcr_banks
? "," : "", g_strstrip(optarg
), NULL
);
1325 case 'A': /* --rsa-keysize */
1326 g_free(rsa_keysize_str
);
1327 rsa_keysize_str
= strdup(optarg
);
1329 case '3': /* --write-ek-cert-files */
1330 g_free(user_certsdir
);
1331 user_certsdir
= g_strdup(optarg
);
1332 flags
|= SETUP_WRITE_EK_CERT_FILES_F
;
1335 if (optarg
== NULL
&& optind
< argc
&& argv
[optind
][0] != '0')
1336 optarg
= argv
[optind
++];
1337 ret
= handle_create_config_files(optarg
);
1339 case 'F': /* --tcsd-system-ps-file */
1340 printf("Warning: --tcsd-system-ps-file is deprecated and has no effect.");
1342 case '1': /* --version */
1346 case 'y': /* --print-capabilities */
1347 printcapabilities
= TRUE
;
1350 case 'h': /* --help */
1351 usage(argv
[0], config_file
);
1356 fprintf(stderr
, "Unknown option code %d\n", opt
);
1357 usage(argv
[0], config_file
);
1362 if (swtpm_prg
== NULL
) {
1364 "Default TPM 'swtpm' could not be found and was not provided using --tpm\n.");
1368 swtpm_prg_l
= split_cmdline(swtpm_prg
);
1369 tmp
= g_find_program_in_path(swtpm_prg_l
[0]);
1371 logerr(gl_LOGFILE
, "swtpm at %s is not an executable.\n", swtpm_prg_l
[0]);
1377 ret
= get_supported_tpm_versions(swtpm_prg_l
, &swtpm_has_tpm12
, &swtpm_has_tpm2
);
1381 if (printcapabilities
) {
1382 ret
= print_capabilities(swtpm_prg_l
, swtpm_has_tpm12
, swtpm_has_tpm2
);
1386 if ((flags
& SETUP_TPM2_F
) != 0 && !swtpm_has_tpm2
) {
1387 logerr(gl_LOGFILE
, "swtpm at %s does not support TPM 2\n", swtpm_prg_l
[0]);
1389 } else if ((flags
& SETUP_TPM2_F
) == 0 && !swtpm_has_tpm12
){
1390 logerr(gl_LOGFILE
, "swtpm at %s does not support TPM 1.2\n", swtpm_prg_l
[0]);
1395 ret
= change_process_owner(runas
);
1401 ownerpass
= g_strdup(DEFAULT_OWNER_PASSWORD
);
1403 srkpass
= g_strdup(DEFAULT_SRK_PASSWORD
);
1405 /* check pcr_banks */
1406 tmp_l
= g_strsplit(pcr_banks
? pcr_banks
: "", ",", -1);
1407 for (i
= 0, n
= 0; tmp_l
[i
]; i
++)
1408 n
+= strlen(tmp_l
[i
]);
1411 pcr_banks
= g_strdup(DEFAULT_PCR_BANKS
);
1413 if (gl_LOGFILE
!= NULL
) {
1415 if (stat(gl_LOGFILE
, &statbuf
) == 0 &&
1416 (statbuf
.st_mode
& S_IFMT
) == S_IFLNK
) {
1417 fprintf(stderr
, "Logfile must not be a symlink.\n");
1420 tmpfile
= fopen(gl_LOGFILE
, "a");
1421 if (tmpfile
== NULL
) {
1422 fprintf(stderr
, "Cannot write to logfile %s.\n", gl_LOGFILE
);
1428 curr_user
= getpwuid(getuid());
1430 // Check tpm_state_path directory and access rights
1431 if (tpm_state_path
== NULL
) {
1432 logerr(gl_LOGFILE
, "--tpm-state must be provided\n");
1436 backend_state
= backend_ops
->parse_backend(tpm_state_path
);
1440 if (backend_ops
->check_access(backend_state
, R_OK
|W_OK
, curr_user
) != 0)
1443 if ((flags
& SETUP_WRITE_EK_CERT_FILES_F
)) {
1444 if (check_directory_access(user_certsdir
, W_OK
, curr_user
) != 0)
1448 if (flags
& SETUP_TPM2_F
) {
1449 if (flags
& SETUP_TAKEOWN_F
) {
1450 logerr(gl_LOGFILE
, "Taking ownership is not supported for TPM 2.\n");
1454 if (flags
& SETUP_TPM2_ECC_F
) {
1455 logerr(gl_LOGFILE
, "--ecc requires --tpm2.\n");
1458 if (flags
& SETUP_CREATE_SPK_F
) {
1459 logerr(gl_LOGFILE
, "--create-spk requires --tpm2.\n");
1464 ret
= check_state_overwrite(swtpm_prg_l
, flags
, tpm_state_path
);
1467 } else if (ret
== 2) {
1472 ret
= backend_ops
->delete_state(backend_state
);
1476 if (access(config_file
, R_OK
) != 0) {
1477 logerr(gl_LOGFILE
, "User %s cannot read config file %s.\n",
1478 curr_user
? curr_user
->pw_name
: "<unknown>", config_file
);
1482 if (cipher
!= NULL
) {
1483 if (strcmp(cipher
, "aes-128-cbc") != 0 &&
1484 strcmp(cipher
, "aes-cbc") != 0 &&
1485 strcmp(cipher
, "aes-256-cbc") != 0) {
1486 logerr(gl_LOGFILE
, "Unsupported cipher %s.\n", cipher
);
1489 tmp
= g_strdup_printf(",mode=%s", cipher
);
1494 if (keyfile
!= NULL
) {
1495 if (access(keyfile
, R_OK
) != 0) {
1496 logerr(gl_LOGFILE
, "User %s cannot read keyfile %s.\n",
1497 curr_user
? curr_user
->pw_name
: "<unknown>", keyfile
);
1500 swtpm_keyopt
= g_strdup_printf("file=%s%s", keyfile
, cipher
);
1501 logit(gl_LOGFILE
, " The TPM's state will be encrypted with a provided key.\n");
1502 } else if (pwdfile
!= NULL
) {
1503 if (access(pwdfile
, R_OK
) != 0) {
1504 logerr(gl_LOGFILE
, "User %s cannot read passphrase file %s.\n",
1505 curr_user
? curr_user
->pw_name
: "<unknown>", pwdfile
);
1508 swtpm_keyopt
= g_strdup_printf("pwdfile=%s%s", pwdfile
, cipher
);
1509 logit(gl_LOGFILE
, " The TPM's state will be encrypted using a key derived from a passphrase.\n");
1510 } else if (keyfile_fd
>= 0) {
1511 fds_to_pass
[n_fds_to_pass
++] = keyfile_fd
;
1512 swtpm_keyopt
= g_strdup_printf("fd=%ld%s", keyfile_fd
, cipher
);
1513 logit(gl_LOGFILE
, " The TPM's state will be encrypted with a provided key (fd).\n");
1514 } else if (pwdfile_fd
>= 0) {
1515 fds_to_pass
[n_fds_to_pass
++] = pwdfile_fd
;
1516 swtpm_keyopt
= g_strdup_printf("pwdfd=%ld%s", pwdfile_fd
, cipher
);
1517 logit(gl_LOGFILE
, " The TPM's state will be encrypted using a key derived from a passphrase (fd).\n");
1520 if (strcmp(rsa_keysize_str
, "max") == 0) {
1521 unsigned int *keysizes
= NULL
;
1524 ret
= get_rsa_keysizes(flags
, swtpm_prg_l
, &keysizes
, &n_keysizes
);
1527 g_free(rsa_keysize_str
);
1528 if (n_keysizes
> 0) {
1529 /* last one is the biggest one */
1530 rsa_keysize_str
= g_strdup_printf("%u", keysizes
[n_keysizes
- 1]);
1532 rsa_keysize_str
= g_strdup("2048");
1536 if (strcmp(rsa_keysize_str
, "2048") == 0 || strcmp(rsa_keysize_str
, "3072") == 0) {
1537 unsigned int *keysizes
= NULL
;
1539 gboolean found
= FALSE
;
1541 ret
= get_rsa_keysizes(flags
, swtpm_prg_l
, &keysizes
, &n_keysizes
);
1545 rsa_keysize
= strtoull(rsa_keysize_str
, NULL
, 10);
1546 for (i
= 0; i
< n_keysizes
&& found
== FALSE
; i
++)
1547 found
= (keysizes
[i
] == rsa_keysize
);
1548 if (!found
&& rsa_keysize
!= 2048) {
1549 logerr(gl_LOGFILE
, "%u bit RSA keys are not supported by libtpms.\n", rsa_keysize
);
1554 logit(gl_LOGFILE
, "Unsupported RSA key size %s.\n", rsa_keysize_str
);
1559 tm
= localtime(&now
);
1560 if (strftime(tmpbuffer
, sizeof(tmpbuffer
), "%a %d %h %Y %I:%M:%S %p %Z", tm
) == 0) {
1561 logerr(gl_LOGFILE
, "Could not format time/date string.\n");
1564 curr_grp
= getgrgid(getgid());
1565 logit(gl_LOGFILE
, "Starting vTPM manufacturing as %s:%s @ %s\n",
1566 curr_user
? curr_user
->pw_name
: "<unknown>",
1567 curr_grp
? curr_grp
->gr_name
: "<unknown>",
1570 if (flags
& (SETUP_EK_CERT_F
| SETUP_PLATFORM_CERT_F
)) {
1571 certsdir
= g_dir_make_tmp("swtpm_setup.certs.XXXXXX", &error
);
1572 if (certsdir
== NULL
) {
1573 logerr(gl_LOGFILE
, "Could not create temporary directory for certs: %s\n",
1579 if ((flags
& SETUP_TPM2_F
) == 0) {
1580 ret
= init_tpm(flags
, swtpm_prg_l
, config_file
, tpm_state_path
, ownerpass
, srkpass
, vmid
,
1581 swtpm_keyopt
, fds_to_pass
, n_fds_to_pass
, certsdir
, user_certsdir
);
1583 ret
= init_tpm2(flags
, swtpm_prg_l
, config_file
, tpm_state_path
, vmid
, pcr_banks
,
1584 swtpm_keyopt
, fds_to_pass
, n_fds_to_pass
, rsa_keysize
, certsdir
,
1589 logit(gl_LOGFILE
, "Successfully authored TPM state.\n");
1591 logerr(gl_LOGFILE
, "An error occurred. Authoring the TPM state failed.\n");
1592 backend_ops
->delete_state(backend_state
);
1596 tm
= localtime(&now
);
1597 if (strftime(tmpbuffer
, sizeof(tmpbuffer
), "%a %d %h %Y %I:%M:%S %p %Z", tm
) == 0) {
1598 logerr(gl_LOGFILE
, "Could not format time/date string.\n");
1601 logit(gl_LOGFILE
, "Ending vTPM manufacturing @ %s\n",
1605 if (certsdir
&& g_rmdir(certsdir
) != 0)
1606 logerr(gl_LOGFILE
, "Could not remove temporary directory for certs: %s\n",
1609 if (backend_ops
&& backend_state
)
1610 backend_ops
->free_backend(backend_state
);
1611 g_strfreev(swtpm_prg_l
);