swtpm_setup: Add support for --reconfigure flag to change active PCR banks

Add support for --reconfigure option for the swtpm_setup to be able to
change the active PCR banks. This option only works with --tpm2 and does
not allow to pass several other options such --create-ek or
--create-ek-cert or --create-platform-cert that would alter the state of
the TPM 2 in other ways.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
Stefan Berger 2021-10-29 13:04:07 -04:00 committed by Stefan Berger
parent 15b9ca6bc3
commit 25d4ac2d3a
5 changed files with 154 additions and 60 deletions

View File

@ -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<cmdarg-reconfigure-pcr-banks> (since v0.7)
The I<--reconfigure> option is supported and allows the reconfiguration of
the active PCR banks.
=item B<tpm2-rsa-keysize-2048, ...> (since v0.4)
The shown RSA key sizes are supported for a TPM 2's EK key. If none of the

View File

@ -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 : "<unknown>",
curr_grp ? curr_grp->gr_name : "<unknown>",
tmpbuffer);

View File

@ -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}"

View File

@ -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}"

View File

@ -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"