diff --git a/man/man8/swtpm.pod b/man/man8/swtpm.pod index eb8fdf638..a501b43e4 100644 --- a/man/man8/swtpm.pod +++ b/man/man8/swtpm.pod @@ -297,7 +297,7 @@ The I action is only available if libseccomp supports logging. This option is only available on Linux and only if swtpm was compiled with libseccomp support. -=item B<--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none][,disable-auto-shutdown]> +=item B<--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none][,disable-auto-shutdown][,recreate-svn-base-secret]> The I flag enables the TPM to accept TPM commands right after start without requiring an INIT to be sent to it through the command channel @@ -318,6 +318,11 @@ avoid increasing the dictionary attack (DA) lockout counter and ultimately a DA lockout by the TPM 2 due to omission of sending a required TPM2_Shutdown() before TPM 2 reset or swtpm process termination. +The I causes the SVN-limited hierarchy 'base secret' +to be recreated. The side effect of recreating this secret is that previous +firmware SVN secrets cannot be created anymore and objects (keys) associated +with the SVN-limited hierachy cannot be used anymore. + =item B<--print-capabilities> (since v0.2) Print capabilities that were added to swtpm after version 0.1. The output @@ -346,7 +351,8 @@ may contain the following: "cmdarg-print-profiles", "profile-opt-remove-disabled", "cmdarg-print-info", - "tpmstate-opt-lock" + "tpmstate-opt-lock", + "flags-opt-recreate-svn-base-secret" ], "version": "0.7.0" } @@ -443,6 +449,10 @@ The option I<--print-info> is supported. The option parameter I for the I<--tpmstate> option is supported. +=item B (since v0.10) + +The I<--flags> option supports the I flag. + =back =item B<--print-states> (since v0.7) diff --git a/src/swtpm/capabilities.c b/src/swtpm/capabilities.c index c3f94b38d..3882f1f08 100644 --- a/src/swtpm/capabilities.c +++ b/src/swtpm/capabilities.c @@ -271,7 +271,7 @@ int capabilities_print_json(bool cusetpm, TPMLIB_TPMVersion tpmversion) "{ " "\"type\": \"swtpm\", " "\"features\": [ " - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" " ], " "\"profiles\": { %s}, " "\"version\": \"" VERSION "\" " @@ -296,6 +296,7 @@ int capabilities_print_json(bool cusetpm, TPMLIB_TPMVersion tpmversion) is_tpm2 ? ", \"profile-opt-remove-disabled\"" : "", true ? ", \"cmdarg-print-info\"" : "", true ? ", \"tpmstate-opt-lock\"" : "", + is_tpm2 ? ", \"flags-opt-recreate-svn-base-secret\"" : "", profiles ? profiles : "" ); diff --git a/src/swtpm/common.c b/src/swtpm/common.c index dbe6e9adf..6d9925ed6 100644 --- a/src/swtpm/common.c +++ b/src/swtpm/common.c @@ -259,6 +259,9 @@ static const OptionDesc flags_opt_desc[] = { }, { .name = "disable-auto-shutdown", .type = OPT_TYPE_BOOLEAN, + }, { + .name = "recreate-svn-base-secret", + .type = OPT_TYPE_BOOLEAN, }, END_OPTION_DESC }; @@ -1301,7 +1304,8 @@ int handle_locality_options(const char *options, uint32_t *flags) } static int parse_flags_options(const char *options, bool *need_init_cmd, - uint16_t *startupType, bool *disable_auto_shutdown) + uint16_t *startupType, bool *disable_auto_shutdown, + bool *recreate_svn_base_secret) { OptionValues *ovs = NULL; char *error = NULL; @@ -1329,6 +1333,9 @@ static int parse_flags_options(const char *options, bool *need_init_cmd, if (*startupType != _TPM_ST_NONE) *need_init_cmd = false; + if (option_get_bool(ovs, "recreate-svn-base-secret", false)) + *recreate_svn_base_secret = true; + option_values_free(ovs); return 0; @@ -1349,13 +1356,14 @@ static int parse_flags_options(const char *options, bool *need_init_cmd, * Returns 0 on success, -1 on failure. */ int handle_flags_options(const char *options, bool *need_init_cmd, - uint16_t *startupType, bool *disable_auto_shutdown) + uint16_t *startupType, bool *disable_auto_shutdown, + bool *recreate_svn_base_secret) { if (!options) return 0; if (parse_flags_options(options, need_init_cmd, startupType, - disable_auto_shutdown) < 0) + disable_auto_shutdown, recreate_svn_base_secret) < 0) return -1; return 0; diff --git a/src/swtpm/common.h b/src/swtpm/common.h index 2ec144026..c2c9f150e 100644 --- a/src/swtpm/common.h +++ b/src/swtpm/common.h @@ -55,7 +55,8 @@ struct server; int handle_server_options(const char *options, struct server **s); int handle_locality_options(const char *options, uint32_t *flags); int handle_flags_options(const char *options, bool *need_init_cmd, - uint16_t *startupType, bool *disable_auto_shutdown); + uint16_t *startupType, bool *disable_auto_shutdown, + bool *recreate_base_secret); #ifdef WITH_SECCOMP int handle_seccomp_options(const char *options, unsigned int *seccomp_action); #else diff --git a/src/swtpm/ctrlchannel.c b/src/swtpm/ctrlchannel.c index 0beb0ccbf..b1828d9b3 100644 --- a/src/swtpm/ctrlchannel.c +++ b/src/swtpm/ctrlchannel.c @@ -577,7 +577,7 @@ int ctrlchannel_process_fd(int fd, res = tpmlib_start(be32toh(init_p->u.req.init_flags), mlp->tpmversion, mlp->storage_locked, - mlp->json_profile); + mlp->json_profile, &mlp->recreate_svn_base_secret); if (res) { logprintf(STDERR_FILENO, "Error: Could not initialize the TPM\n"); diff --git a/src/swtpm/cuse_tpm.c b/src/swtpm/cuse_tpm.c index 153ddd7d9..2558985fa 100644 --- a/src/swtpm/cuse_tpm.c +++ b/src/swtpm/cuse_tpm.c @@ -125,6 +125,9 @@ static bool g_storage_locked; /* whether to release the lock on outgoing migration */ static bool g_release_lock_outgoing; +/* whether to recreate the SVN base secret of a TPM 2 */ +static bool g_recreate_svn_base_secret; + /* how many times to retry locking; use for fallback after releasing the lock on outgoing migration. */ static unsigned int g_locking_retries; @@ -255,12 +258,13 @@ static void usage(FILE *file, const char *prgname, const char *iface) " mode allows a user to set the file mode bits of the state\n" " files; the default mode is 0640;\n" " lock enables file-locking by the storage backend;\n" - "--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none][,disable-auto-shutdown]\n" + "--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none][,disable-auto-shutdown][,recreate-svn-base-secret]\n" " : not-need-init: commands can be sent without needing to\n" " send an INIT via control channel;\n" " startup-...: send Startup command with this type;\n" " disable-auto-shutdown disables automatic sending of\n" " TPM2_Shutdown before TPM 2 reset or swtpm termination;\n" + " recreate-svn-base-secret recreates the SVN base secret;\n" "-r|--runas : after creating the CUSE device, change to the given\n" " user\n" "-R|--chroot : chroot to the given directory at startup\n" @@ -515,7 +519,8 @@ static void worker_thread(gpointer data, gpointer user_data SWTPM_ATTR_UNUSED) * @res: the result from starting the TPM */ static int tpm_start(uint32_t flags, TPMLIB_TPMVersion l_tpmversion, - const char *json_profile, TPM_RESULT *res) + const char *json_profile, TPM_RESULT *res, + bool *recreate_svn_base_secret) { DIR *dir; const char *uri = tpmstate_get_backend_uri(); @@ -556,7 +561,8 @@ static int tpm_start(uint32_t flags, TPMLIB_TPMVersion l_tpmversion, g_storage_locked = !g_incoming_migration; - *res = tpmlib_start(flags, l_tpmversion, g_storage_locked, json_profile); + *res = tpmlib_start(flags, l_tpmversion, g_storage_locked, json_profile, + recreate_svn_base_secret); if (*res != TPM_SUCCESS) goto error_del_pool; @@ -1191,7 +1197,7 @@ static void ptm_ioctl(fuse_req_t req, int cmd, void *arg, tpm_running = false; if (tpm_start(init_p->u.req.init_flags, tpmversion, - g_json_profile, &res) < 0) { + g_json_profile, &res, &g_recreate_svn_base_secret) < 0) { logprintf(STDERR_FILENO, "Error: Could not initialize the TPM.\n"); } else { @@ -1868,7 +1874,8 @@ int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *ifac handle_seccomp_options(param.seccompdata, ¶m.seccomp_action) < 0 || handle_locality_options(param.localitydata, &locality_flags) < 0 || handle_flags_options(param.flagsdata, &need_init_cmd, - ¶m.startupType, &g_disable_auto_shutdown) < 0 || + ¶m.startupType, &g_disable_auto_shutdown, + &g_recreate_svn_base_secret) < 0 || handle_migration_options(param.migrationdata, &g_incoming_migration, &g_release_lock_outgoing) < 0 || handle_profile_options(param.profiledata, &g_json_profile) < 0) { @@ -1919,7 +1926,8 @@ int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *ifac g_mutex_lock(FILE_OPS_LOCK); if (!need_init_cmd || (infoflags && tpmstate_get_backend_uri())) { - if (tpm_start(0, tpmversion, g_json_profile, &res) < 0) { + if (tpm_start(0, tpmversion, g_json_profile, &res, + &g_recreate_svn_base_secret) < 0) { ret = -1; goto err_unlock; } diff --git a/src/swtpm/mainloop.h b/src/swtpm/mainloop.h index fbd153c37..1342e249c 100644 --- a/src/swtpm/mainloop.h +++ b/src/swtpm/mainloop.h @@ -68,6 +68,8 @@ struct mainLoopParams { bool storage_locked; /* whether to release the lock on outgoing migration */ bool release_lock_outgoing; + /* whether to recreate the SVN base secret of the TPM 2 */ + bool recreate_svn_base_secret; /* how many times to retry locking; use for fallback after releasing the lock on outgoing migration. */ unsigned int locking_retries; diff --git a/src/swtpm/swtpm.c b/src/swtpm/swtpm.c index aedf06db0..89f794f8a 100644 --- a/src/swtpm/swtpm.c +++ b/src/swtpm/swtpm.c @@ -172,12 +172,13 @@ static void usage(FILE *file, const char *prgname, const char *iface) " mode allows a user to set the file mode bits of the socket; the\n" " value must be given in octal number format;\n" " uid and gid set the ownership of the Unixio socket's file;\n" - "--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none][,disable-auto-shutdown]\n" + "--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none][,disable-auto-shutdown][,recreate-svn-base-secret]\n" " : not-need-init: commands can be sent without needing to\n" " send an INIT via control channel;\n" " startup-...: send Startup command with this type;\n" " disable-auto-shutdown disables automatic sending of\n" " TPM2_Shutdown before TPM 2 reset or swtpm termination;\n" + " recreate-svn-base-secret recreates the SVN base secret;\n" "-r|--runas : change to the given user\n" "-R|--chroot \n" " : chroot to the given directory at startup\n" @@ -241,6 +242,7 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface) .disable_auto_shutdown = false, .incoming_migration = false, .storage_locked = false, + .recreate_svn_base_secret = false, }; g_autofree gchar *jsoninfo = NULL; struct server *server = NULL; @@ -542,7 +544,8 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface) handle_tpmstate_options(tpmstatedata) < 0 || handle_seccomp_options(seccompdata, &seccomp_action) < 0 || handle_flags_options(flagsdata, &need_init_cmd, - &mlp.startupType, &mlp.disable_auto_shutdown) < 0 || + &mlp.startupType, &mlp.disable_auto_shutdown, + &mlp.recreate_svn_base_secret) < 0 || handle_migration_options(migrationdata, &mlp.incoming_migration, &mlp.release_lock_outgoing) < 0 || handle_profile_options(profiledata, &mlp.json_profile) < 0) { @@ -585,7 +588,7 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface) mlp.storage_locked = !mlp.incoming_migration; if ((rc = tpmlib_start(0, mlp.tpmversion, mlp.storage_locked, - mlp.json_profile))) + mlp.json_profile, &mlp.recreate_svn_base_secret))) goto error_no_tpm; tpm_running = true; SWTPM_G_FREE(mlp.json_profile); diff --git a/src/swtpm/swtpm_chardev.c b/src/swtpm/swtpm_chardev.c index 86180abc9..2f74f2574 100644 --- a/src/swtpm/swtpm_chardev.c +++ b/src/swtpm/swtpm_chardev.c @@ -194,7 +194,7 @@ static void usage(FILE *file, const char *prgname, const char *iface) "--locality [reject-locality-4][,allow-set-locality]\n" " : reject-locality-4: reject any command in locality 4\n" " allow-set-locality: accept SetLocality command\n" - "--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none][,disable-auto-shutdown]\n" + "--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none][,disable-auto-shutdown][,recreate-svn-base-secret]\n" " : not-need-init: commands can be sent without needing to\n" " send an INIT via control channel; not needed when using\n" " --vtpm-proxy\n" @@ -202,6 +202,7 @@ static void usage(FILE *file, const char *prgname, const char *iface) " when --vtpm-proxy is used, startup-clear is used\n" " disable-auto-shutdown disables automatic sending of\n" " TPM2_Shutdown before TPM 2 reset or swtpm termination;\n" + " recreate-svn-base-secret recreates the SVN base secret;\n" "--tpm2 : choose TPM2 functionality\n" #ifdef WITH_SECCOMP # ifndef SCMP_ACT_LOG @@ -299,6 +300,7 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i .disable_auto_shutdown = false, .incoming_migration = false, .storage_locked = false, + .recreate_svn_base_secret = false, }; g_autofree gchar *jsoninfo = NULL; unsigned long val; @@ -606,7 +608,8 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i handle_tpmstate_options(tpmstatedata) < 0 || handle_seccomp_options(seccompdata, &seccomp_action) < 0 || handle_flags_options(flagsdata, &need_init_cmd, - &mlp.startupType, &mlp.disable_auto_shutdown) < 0 || + &mlp.startupType, &mlp.disable_auto_shutdown, + &mlp.recreate_svn_base_secret) < 0 || handle_migration_options(migrationdata, &mlp.incoming_migration, &mlp.release_lock_outgoing) < 0 || handle_profile_options(profiledata, &mlp.json_profile) < 0) { @@ -635,7 +638,7 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i mlp.storage_locked = !mlp.incoming_migration; if ((rc = tpmlib_start(0, mlp.tpmversion, mlp.storage_locked, - mlp.json_profile))) + mlp.json_profile, &mlp.recreate_svn_base_secret))) goto error_no_tpm; tpm_running = true; SWTPM_G_FREE(mlp.json_profile); diff --git a/src/swtpm/tpmlib.c b/src/swtpm/tpmlib.c index 367fdb95f..92dc93263 100644 --- a/src/swtpm/tpmlib.c +++ b/src/swtpm/tpmlib.c @@ -274,7 +274,8 @@ static int tpmlib_maybe_configure_openssl(TPMLIB_TPMVersion tpmversion) } TPM_RESULT tpmlib_start(uint32_t flags, TPMLIB_TPMVersion tpmversion, - bool lock_nvram, const char *json_profile) + bool lock_nvram, const char *json_profile, + bool *recreate_svn_base_secret) { TPM_RESULT res; @@ -319,6 +320,11 @@ TPM_RESULT tpmlib_start(uint32_t flags, TPMLIB_TPMVersion tpmversion, } } + if (*recreate_svn_base_secret) { + TPMLIB_RecreateSvnBaseSecret(); + *recreate_svn_base_secret = false; + } + if (tpmlib_maybe_configure_openssl(tpmversion)) { res = TPM_FAIL; goto error_terminate; diff --git a/src/swtpm/tpmlib.h b/src/swtpm/tpmlib.h index 90f9cb869..810648e51 100644 --- a/src/swtpm/tpmlib.h +++ b/src/swtpm/tpmlib.h @@ -48,7 +48,8 @@ enum TPMLIB_StateType tpmlib_blobtype_to_statetype(uint32_t blobtype); TPM_RESULT tpmlib_register_callbacks(struct libtpms_callbacks *cbs); TPM_RESULT tpmlib_choose_tpm_version(TPMLIB_TPMVersion tpmversion); TPM_RESULT tpmlib_start(uint32_t flags, TPMLIB_TPMVersion tpmversion, - bool lock_nvram, const char *profile); + bool lock_nvram, const char *profile, + bool *recreate_svn_base_secret); int tpmlib_get_tpm_property(enum TPMLIB_TPMProperty prop); uint32_t tpmlib_get_cmd_ordinal(const unsigned char *request, size_t req_len); bool tpmlib_is_request_cancelable(TPMLIB_TPMVersion tpmversion, diff --git a/tests/_test_tpm2_print_capabilities b/tests/_test_tpm2_print_capabilities index bb8ddc2cc..a8e206ba0 100755 --- a/tests/_test_tpm2_print_capabilities +++ b/tests/_test_tpm2_print_capabilities @@ -32,7 +32,7 @@ exp='\{ "type": "swtpm", '\ '"nvram-backend-dir", "nvram-backend-file"'\ '(, "rsa-keysize-1024")?(, "rsa-keysize-2048")?(, "rsa-keysize-3072")?, "cmdarg-profile", '\ '"cmdarg-print-profiles", "profile-opt-remove-disabled", "cmdarg-print-info", '\ -'"tpmstate-opt-lock" \], '\ +'"tpmstate-opt-lock", "flags-opt-recreate-svn-base-secret" \], '\ '"profiles": \{ "names": \[ [^]]*\], "algorithms": \{ [^\}]*\}, "commands": \{ [^\}]*\} }, '\ '"version": "[^"]*" \}' if ! [[ ${msg} =~ ${exp} ]]; then