diff --git a/man/man8/swtpm_setup.pod b/man/man8/swtpm_setup.pod index 59f98d6a..45679351 100644 --- a/man/man8/swtpm_setup.pod +++ b/man/man8/swtpm_setup.pod @@ -188,6 +188,11 @@ the I<--print-capabilities> option. The default size is 2048 bits for both TPM 1.2 and TPM 2. If 'max' is passed, the largest possible key size is used. +=item B<--reconfigure> (since v0.7) + +This option allows the reconfiguration of the active PCR banks of a +TPM 2 using the I<--pcr-banks> option. + =item B<--print-capabilities> (since v0.2) Print capabilities that were added to swtpm_setup after version 0.1. @@ -200,6 +205,7 @@ The output may contain the following: "cmdarg-pwdfile-fd", "cmdarg-write-ek-cert-files", "cmdarg-create-config-files", + "cmdarg-reconfigure-pcr-banks", "tpm2-rsa-keysize-2048", "tpm2-rsa-keysize-3072", "tpm12-not-need-root", @@ -231,6 +237,11 @@ The I<--write-ek-cert-files> option is supported. The I<--create-config-files> option is supported. +=item B (since v0.7) + +The I<--reconfigure> option is supported and allows the reconfiguration of +the active PCR banks. + =item B (since v0.4) The shown RSA key sizes are supported for a TPM 2's EK key. If none of the diff --git a/src/swtpm_setup/swtpm_setup.c b/src/swtpm_setup/swtpm_setup.c index ea4d6f5b..c3f02536 100644 --- a/src/swtpm_setup/swtpm_setup.c +++ b/src/swtpm_setup/swtpm_setup.c @@ -59,6 +59,7 @@ #define SETUP_DISPLAY_RESULTS_F (1 << 13) #define SETUP_DECRYPTION_F (1 << 14) #define SETUP_WRITE_EK_CERT_FILES_F (1 << 15) +#define SETUP_RECONFIGURE_F (1 << 16) /* default configuration file */ #define SWTPM_SETUP_CONF "swtpm_setup.conf" @@ -512,17 +513,19 @@ static int init_tpm2(unsigned long flags, gchar **swtpm_prg_l, const gchar *conf goto error; } - if ((flags & SETUP_CREATE_SPK_F)) { - ret = swtpm2->ops->create_spk(swtpm, !!(flags & SETUP_TPM2_ECC_F), rsa_keysize); + if (!(flags & SETUP_RECONFIGURE_F)) { + if ((flags & SETUP_CREATE_SPK_F)) { + ret = swtpm2->ops->create_spk(swtpm, !!(flags & SETUP_TPM2_ECC_F), rsa_keysize); + if (ret != 0) + goto destroy; + } + + ret = tpm2_create_eks_and_certs(flags, config_file, certsdir, vmid, rsa_keysize, swtpm2, + user_certsdir); if (ret != 0) goto destroy; } - ret = tpm2_create_eks_and_certs(flags, config_file, certsdir, vmid, rsa_keysize, swtpm2, - user_certsdir); - if (ret != 0) - goto destroy; - ret = tpm2_activate_pcr_banks(swtpm2, pcr_banks); if (ret != 0) goto destroy; @@ -910,6 +913,10 @@ static void usage(const char *prgname, const char *default_config_file) " root: allow to create files under root's home directory\n" " skip-if-exist: if any file exists exit without error\n" "\n" + "--reconfigure : Reconfigure an existing swtpm by reusing existing state.\n" + " The active PCR banks can be changed but no new keys will\n" + " be created.\n" + "\n" "--version : Display version and exit\n" "\n" "--help,-h : Display this help screen\n\n", @@ -1059,6 +1066,7 @@ static int print_capabilities(char **swtpm_prg_l, gboolean swtpm_has_tpm12, printf("{ \"type\": \"swtpm_setup\", " "\"features\": [ %s%s\"cmdarg-keyfile-fd\", \"cmdarg-pwdfile-fd\", \"tpm12-not-need-root\"" ", \"cmdarg-write-ek-cert-files\", \"cmdarg-create-config-files\"" + ", \"cmdarg-reconfigure-pcr-banks\"" "%s ], " "\"version\": \"" VERSION "\" " "}\n", @@ -1180,6 +1188,7 @@ int main(int argc, char *argv[]) {"tcsd-system-ps-file", required_argument, NULL, 'F'}, {"version", no_argument, NULL, '1'}, {"print-capabilities", no_argument, NULL, 'y'}, + {"reconfigure", no_argument, NULL, 'R'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; @@ -1386,6 +1395,9 @@ int main(int argc, char *argv[]) case 'y': /* --print-capabilities */ printcapabilities = TRUE; break; + case 'R': /* --reconfigure */ + flags |= SETUP_RECONFIGURE_F; + break; case '?': case 'h': /* --help */ usage(argv[0], config_file); @@ -1491,19 +1503,25 @@ int main(int argc, char *argv[]) logerr(gl_LOGFILE, "--create-spk requires --tpm2.\n"); goto error; } + if (flags & SETUP_RECONFIGURE_F) { + logerr(gl_LOGFILE, "--reconfigure requires --tpm2.\n"); + goto error; + } } - ret = check_state_overwrite(swtpm_prg_l, flags, tpm_state_path); - if (ret == 1) { - goto error; - } else if (ret == 2) { - ret = 0; - goto out; - } + if (!(flags & SETUP_RECONFIGURE_F)) { + ret = check_state_overwrite(swtpm_prg_l, flags, tpm_state_path); + if (ret == 1) { + goto error; + } else if (ret == 2) { + ret = 0; + goto out; + } - ret = backend_ops->delete_state(backend_state); - if (ret != 0) - goto error; + ret = backend_ops->delete_state(backend_state); + if (ret != 0) + goto error; + } if (access(config_file, R_OK) != 0) { logerr(gl_LOGFILE, "User %s cannot read config file %s.\n", @@ -1599,6 +1617,13 @@ int main(int argc, char *argv[]) goto error; } + if (flags & SETUP_RECONFIGURE_F) { + if (flags & (SETUP_CREATE_EK_F | SETUP_EK_CERT_F | SETUP_PLATFORM_CERT_F)) { + logerr(gl_LOGFILE, "Reconfiguration is not supported with creation of EK or certificates\n"); + goto error; + } + } + now = time(NULL); tm = localtime(&now); if (strftime(tmpbuffer, sizeof(tmpbuffer), "%a %d %h %Y %I:%M:%S %p %Z", tm) == 0) { @@ -1606,7 +1631,8 @@ int main(int argc, char *argv[]) goto error; } curr_grp = getgrgid(getgid()); - logit(gl_LOGFILE, "Starting vTPM manufacturing as %s:%s @ %s\n", + logit(gl_LOGFILE, "Starting vTPM %s as %s:%s @ %s\n", + flags & SETUP_RECONFIGURE_F ? "reconfiguration" : "manufacturing", curr_user ? curr_user->pw_name : "", curr_grp ? curr_grp->gr_name : "", tmpbuffer); diff --git a/tests/_test_print_capabilities b/tests/_test_print_capabilities index b677892b..794b5edd 100755 --- a/tests/_test_print_capabilities +++ b/tests/_test_print_capabilities @@ -43,7 +43,7 @@ if [ $? -ne 0 ]; then fi # The are some variable parameters at the end, use regex -exp='\{ "type": "swtpm_setup", "features": \[ "tpm-1.2",( "tpm-2.0",)? "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root", "cmdarg-write-ek-cert-files", "cmdarg-create-config-files"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \], "version": "[^"]*" \}' +exp='\{ "type": "swtpm_setup", "features": \[ "tpm-1.2",( "tpm-2.0",)? "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root", "cmdarg-write-ek-cert-files", "cmdarg-create-config-files", "cmdarg-reconfigure-pcr-banks"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \], "version": "[^"]*" \}' if ! [[ ${msg} =~ ${exp} ]]; then echo "Unexpected response from ${SWTPM_SETUP} to --print-capabilities:" echo "Actual : ${msg}" diff --git a/tests/_test_tpm2_print_capabilities b/tests/_test_tpm2_print_capabilities index f55add1e..02986f33 100755 --- a/tests/_test_tpm2_print_capabilities +++ b/tests/_test_tpm2_print_capabilities @@ -44,7 +44,7 @@ if [ $? -ne 0 ]; then fi # The are some variable parameters at the end, use regex -exp='\{ "type": "swtpm_setup", "features": \[( "tpm-1.2",)? "tpm-2.0", "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root", "cmdarg-write-ek-cert-files", "cmdarg-create-config-files"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \], "version": "[^"]*" \}' +exp='\{ "type": "swtpm_setup", "features": \[( "tpm-1.2",)? "tpm-2.0", "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root", "cmdarg-write-ek-cert-files", "cmdarg-create-config-files", "cmdarg-reconfigure-pcr-banks"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \], "version": "[^"]*" \}' if ! [[ ${msg} =~ ${exp} ]]; then echo "Unexpected response from ${SWTPM_SETUP} to --print-capabilities:" echo "Actual : ${msg}" diff --git a/tests/test_tpm2_swtpm_setup_create_cert b/tests/test_tpm2_swtpm_setup_create_cert index 6f431556..26f9f3da 100755 --- a/tests/test_tpm2_swtpm_setup_create_cert +++ b/tests/test_tpm2_swtpm_setup_create_cert @@ -122,53 +122,110 @@ done echo "Test 1: OK" +function swtpm_setup_reconfigure() { + local workdir="$1" + local pwdfile="$2" -# we need to create at least one cert: --create-ek-cert -$SWTPM_SETUP \ - --tpm2 \ - --ecc \ - --tpm-state "${workdir}" \ - --create-ek-cert \ - --config "${workdir}/swtpm_setup.conf" \ - --logfile "${workdir}/logfile" \ - --tpm "${SWTPM_EXE} socket ${SWTPM_TEST_SECCOMP_OPT}" \ - --overwrite \ - --write-ek-cert-files "${workdir}" + # Reconfigure the active PCR banks a few times; the size of the state + # file must not change but its content (hash) must change every time + # since activating the PCR banks changes a few bits in the permanent + # state, also when the state is not encrypted. + local PERMALL_FILE="${workdir}/tpm2-00.permall" + local permall_size=$(get_filesize "${PERMALL_FILE}") -if [ $? -ne 0 ]; then - echo "Error: Could not run $SWTPM_SETUP." - echo "Logfile output:" - cat "${workdir}/logfile" - exit 1 -fi + for pcrbanks in "sha1" "sha1,sha256" "sha1,sha256,sha384,sha512"; do + # hash must change between before and after + permall_hash=$(get_sha1_file "${PERMALL_FILE}") -if [ ! -r "${SIGNINGKEY}" ]; then - echo "Error: Signingkey file ${SIGNINGKEY} was not created." - exit 1 -fi + $SWTPM_SETUP \ + --tpm2 \ + --tpm-state "${workdir}" \ + --config "${workdir}/swtpm_setup.conf" \ + --logfile "${workdir}/logfile" \ + --tpm "${SWTPM_EXE} socket ${SWTPM_TEST_SECCOMP_OPT}" \ + --pcr-banks "${pcrbanks}" \ + --reconfigure \ + ${pwdfile:+--pwdfile "${pwdfile}"} + if [ $? -ne 0 ]; then + echo "Error: Could not run $SWTPM_SETUP --reconfigure." + echo "Logfile output:" + cat "${workdir}/logfile" + exit 1 + fi -if [ ! -r "${ISSUERCERT}" ]; then - echo "Error: Issuer cert file ${ISSUERCERT} was not created." - exit 1 -fi + local newhash=$(get_sha1_file "${PERMALL_FILE}") + if [ "${newhash}" = "${permall_hash}" ]; then + echo "Error: The hash of the permanent state did not change." + exit 1 + fi -if [ ! -r "${CERTSERIAL}" ]; then - echo "Error: Cert serial number file ${CERTSERIAL} was not created." - exit 1 -fi + local newsize=$(get_filesize "${PERMALL_FILE}") + if [ "${newsize}" != "${permall_size}" ]; then + echo "Error: The size of the permanent state file changed." + echo "Actual : ${tmp}" + echo "Expected: ${permall_size}" + fi + echo "Filesize: ${newsize}; hash: ${newhash}; pwdfile: ${pwdfile}" + done +} -certfile="${workdir}/ek-secp384r1.crt" -if [ ! -f "${certfile}" ]; then - echo "Error: EK file '${certfile}' was not written." - ls -l "${workdir}" - exit 1 -fi +# Create with certificates with and without encryption enabled and reconfigure +# the PCR banks +PWDFILE="${workdir}/pwd" +echo -n "password" > "${PWDFILE}" +rm -f "${workdir}/logfile" -if [ -z "$($CERTTOOL --inder --infile "${certfile}" -i | grep "384 bits")" ]; then - echo "Error: EK file '${certfile}' is not an ECC 384 bit key." - $CERTTOOL --inder --infile "${certfile}" -i - exit 1 -fi +for pwdfile in "" "${PWDFILE}"; do + $SWTPM_SETUP \ + --tpm2 \ + --ecc \ + --tpm-state "${workdir}" \ + --create-ek-cert \ + --create-platform-cert \ + --config "${workdir}/swtpm_setup.conf" \ + --logfile "${workdir}/logfile" \ + --tpm "${SWTPM_EXE} socket ${SWTPM_TEST_SECCOMP_OPT}" \ + --overwrite \ + --write-ek-cert-files "${workdir}" \ + ${pwdfile:+--pwdfile "${pwdfile}"} + + if [ $? -ne 0 ]; then + echo "Error: Could not run $SWTPM_SETUP." + echo "Logfile output:" + cat "${workdir}/logfile" + exit 1 + fi + + if [ ! -r "${SIGNINGKEY}" ]; then + echo "Error: Signingkey file ${SIGNINGKEY} was not created." + exit 1 + fi + + if [ ! -r "${ISSUERCERT}" ]; then + echo "Error: Issuer cert file ${ISSUERCERT} was not created." + exit 1 + fi + + if [ ! -r "${CERTSERIAL}" ]; then + echo "Error: Cert serial number file ${CERTSERIAL} was not created." + exit 1 + fi + + certfile="${workdir}/ek-secp384r1.crt" + if [ ! -f "${certfile}" ]; then + echo "Error: EK file '${certfile}' was not written." + ls -l "${workdir}" + exit 1 + fi + + if [ -z "$($CERTTOOL --inder --infile "${certfile}" -i | grep "384 bits")" ]; then + echo "Error: EK file '${certfile}' is not an ECC 384 bit key." + $CERTTOOL --inder --infile "${certfile}" -i + exit 1 + fi + + swtpm_setup_reconfigure "${workdir}" "${pwdfile}" +done echo "Test 2: OK"