]> git.proxmox.com Git - swtpm.git/commitdiff
swtpm_setup: Add support for --reconfigure flag to change active PCR banks
authorStefan Berger <stefanb@linux.ibm.com>
Fri, 29 Oct 2021 17:04:07 +0000 (13:04 -0400)
committerStefan Berger <stefanb@us.ibm.com>
Fri, 5 Nov 2021 10:39:49 +0000 (06:39 -0400)
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>
man/man8/swtpm_setup.pod
src/swtpm_setup/swtpm_setup.c
tests/_test_print_capabilities
tests/_test_tpm2_print_capabilities
tests/test_tpm2_swtpm_setup_create_cert

index 59f98d6abcad6e9179290162e68aa52e75561d43..45679351c4dbf2d43a3d74cc06ab74d7c6a44305 100644 (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
index ea4d6f5beca317477ec4423d447c554688dac49c..c3f025361d2ab9411e3fc9eace137b3f094466be 100644 (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);
index b677892be2e4582f8169d68a6bccc263444b3d01..794b5edd02899e2bc694522da40552f684feb070 100755 (executable)
@@ -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}"
index f55add1e40c1826b05880ee2e7189395ccfbaac5..02986f338a2a2d98255fb6c48b59a87ea3dbc280 100755 (executable)
@@ -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}"
index 6f43155694b62f98d76281b9164f3158e06cab6b..26f9f3dafb07a9a3d8b74614fed1c1d6461da951 100755 (executable)
@@ -122,53 +122,110 @@ done
 
 echo "Test 1: OK"
 
+function swtpm_setup_reconfigure() {
+       local workdir="$1"
+       local pwdfile="$2"
+
+       # 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}")
+
+       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}")
+
+               $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
+
+               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
+
+               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
+}
 
-# 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}"
-
-if [ $? -ne 0 ]; then
-       echo "Error: Could not run $SWTPM_SETUP."
-       echo "Logfile output:"
-       cat "${workdir}/logfile"
-       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 [ ! -r "${SIGNINGKEY}" ]; then
-       echo "Error: Signingkey file ${SIGNINGKEY} was not created."
-       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 [ ! -r "${ISSUERCERT}" ]; then
-       echo "Error: Issuer cert file ${ISSUERCERT} was not created."
-       exit 1
-fi
+       if [ $? -ne 0 ]; then
+               echo "Error: Could not run $SWTPM_SETUP."
+               echo "Logfile output:"
+               cat "${workdir}/logfile"
+               exit 1
+       fi
 
-if [ ! -r "${CERTSERIAL}" ]; then
-       echo "Error: Cert serial number file ${CERTSERIAL} was not created."
-       exit 1
-fi
+       if [ ! -r "${SIGNINGKEY}" ]; then
+               echo "Error: Signingkey file ${SIGNINGKEY} 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 [ ! -r "${ISSUERCERT}" ]; then
+               echo "Error: Issuer cert file ${ISSUERCERT} was not created."
+               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
+       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"