<tpm model='tpm-tis'>
<backend type='emulator' version='2.0'>
<encryption secret='6dd3e4a5-1d76-44ce-961f-f119f5aad935'/>
+ <active_pcr_banks>
+ <sha256/>
+ </active_pcr_banks>
</backend>
</tpm>
</devices>
This attribute only works with the ``emulator`` backend. The accepted values
are ``yes`` and ``no``. :since:`Since 7.0.0`
+``active_pcr_banks``
+ The ``active_pcr_banks`` node is used to define which of the PCR banks
+ of a TPM 2.0 to activate. Valid names are for example sha1, sha256, sha384,
+ and sha512. If this node is provided, the set of PCR banks are activated
+ before every start of a VM and this step is logged in the swtpm's log.
+ This attribute requires that swtpm_setup v0.7 or later is installed
+ and may not have any effect otherwise. The selection of PCR banks only works
+ with the ``emulator`` backend. since:`Since 7.10.0`
+
``encryption``
The ``encryption`` element allows the state of a TPM emulator to be
encrypted. The ``secret`` must reference a secret object that holds the
<value>emulator</value>
</attribute>
<ref name="tpm-backend-emulator-encryption"/>
+ <ref name="tpm-backend-emulator-active-pcr-banks"/>
<optional>
<attribute name="persistent_state">
<choice>
</optional>
</define>
+ <define name="tpm-backend-emulator-active-pcr-banks">
+ <optional>
+ <element name="active_pcr_banks">
+ <interleave>
+ <optional>
+ <element name="sha1">
+ <empty/>
+ </element>
+ </optional>
+ <optional>
+ <element name="sha256">
+ <empty/>
+ </element>
+ </optional>
+ <optional>
+ <element name="sha384">
+ <empty/>
+ </element>
+ </optional>
+ <optional>
+ <element name="sha512">
+ <empty/>
+ </element>
+ </optional>
+ </interleave>
+ </element>
+ </optional>
+ </define>
+
<define name="vsock">
<element name="vsock">
<optional>
"2.0",
);
+VIR_ENUM_IMPL(virDomainTPMPcrBank,
+ VIR_DOMAIN_TPM_PCR_BANK_LAST,
+ "sha1",
+ "sha256",
+ "sha384",
+ "sha512",
+);
+
VIR_ENUM_IMPL(virDomainIOMMUModel,
VIR_DOMAIN_IOMMU_MODEL_LAST,
"intel",
* <tpm model='tpm-tis'>
* <backend type='emulator' version='2.0'>
* <encryption secret='32ee7e76-2178-47a1-ab7b-269e6e348015'/>
+ * <active_pcr_banks>
+ * <sha256/>
+ * <sha384/>
+ * </active_pcr_banks>
* </backend>
* </tpm>
*
virDomainTPMDef *def;
VIR_XPATH_NODE_AUTORESTORE(ctxt)
int nbackends;
+ int nnodes;
+ size_t i;
g_autofree char *path = NULL;
g_autofree char *model = NULL;
g_autofree char *backend = NULL;
g_autofree char *secretuuid = NULL;
g_autofree char *persistent_state = NULL;
g_autofree xmlNodePtr *backends = NULL;
+ g_autofree xmlNodePtr *nodes = NULL;
+ int bank;
def = g_new0(virDomainTPMDef, 1);
goto error;
}
}
+ if (def->version == VIR_DOMAIN_TPM_VERSION_2_0) {
+ if ((nnodes = virXPathNodeSet("./backend/active_pcr_banks/*", ctxt, &nodes)) < 0)
+ break;
+ for (i = 0; i < nnodes; i++) {
+ if ((bank = virDomainTPMPcrBankTypeFromString((const char *)nodes[i]->name)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unsupported PCR banks '%s'"),
+ nodes[i]->name);
+ goto error;
+ }
+ def->data.emulator.activePcrBanks |= (1 << bank);
+ }
+ }
break;
case VIR_DOMAIN_TPM_TYPE_LAST:
goto error;
virBufferAsprintf(buf, "<encryption secret='%s'/>\n",
virUUIDFormat(def->data.emulator.secretuuid, uuidstr));
virBufferAdjustIndent(buf, -2);
+ }
+ if (def->data.emulator.activePcrBanks) {
+ size_t i;
+ virBufferAddLit(buf, ">\n");
+ virBufferAdjustIndent(buf, 2);
+ virBufferAddLit(buf, "<active_pcr_banks>\n");
+ virBufferAdjustIndent(buf, 2);
+ for (i = VIR_DOMAIN_TPM_PCR_BANK_SHA1; i < VIR_DOMAIN_TPM_PCR_BANK_LAST; i++) {
+ if ((def->data.emulator.activePcrBanks & (1 << i)))
+ virBufferAsprintf(buf, "<%s/>\n",
+ virDomainTPMPcrBankTypeToString(i));
+ }
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</active_pcr_banks>\n");
+ virBufferAdjustIndent(buf, -2);
+ }
+ if (def->data.emulator.hassecretuuid ||
+ def->data.emulator.activePcrBanks)
virBufferAddLit(buf, "</backend>\n");
- } else {
+ else
virBufferAddLit(buf, "/>\n");
- }
break;
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
VIR_DOMAIN_TPM_VERSION_LAST
} virDomainTPMVersion;
+typedef enum {
+ VIR_DOMAIN_TPM_PCR_BANK_SHA1,
+ VIR_DOMAIN_TPM_PCR_BANK_SHA256,
+ VIR_DOMAIN_TPM_PCR_BANK_SHA384,
+ VIR_DOMAIN_TPM_PCR_BANK_SHA512,
+
+ VIR_DOMAIN_TPM_PCR_BANK_LAST
+} virDomainPcrBank;
+
#define VIR_DOMAIN_TPM_DEFAULT_DEVICE "/dev/tpm0"
struct _virDomainTPMDef {
unsigned char secretuuid[VIR_UUID_BUFLEN];
bool hassecretuuid;
bool persistent_state;
+ unsigned int activePcrBanks;
} emulator;
} data;
};
VIR_ENUM_DECL(virDomainTPMModel);
VIR_ENUM_DECL(virDomainTPMBackend);
VIR_ENUM_DECL(virDomainTPMVersion);
+VIR_ENUM_DECL(virDomainTPMPcrBank);
VIR_ENUM_DECL(virDomainMemoryModel);
VIR_ENUM_DECL(virDomainMemoryBackingModel);
VIR_ENUM_DECL(virDomainMemorySource);
virDomainTPMDefFree;
virDomainTPMModelTypeFromString;
virDomainTPMModelTypeToString;
+virDomainTPMPcrBankTypeFromString;
+virDomainTPMPcrBankTypeToString;
virDomainUSBDeviceDefForeach;
virDomainVideoDefaultRAM;
virDomainVideoDefClear;
}
+static char *
+qemuTPMPcrBankBitmapToStr(unsigned int pcrBanks)
+{
+ g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+ const char *comma = "";
+ size_t i;
+
+ for (i = VIR_DOMAIN_TPM_PCR_BANK_SHA1; i < VIR_DOMAIN_TPM_PCR_BANK_LAST; i++) {
+ if (pcrBanks & (1 << i)) {
+ virBufferAsprintf(&buf, "%s%s",
+ comma, virDomainTPMPcrBankTypeToString(i));
+ comma = ",";
+ }
+ }
+ return virBufferContentAndReset(&buf);
+}
+
+
+/*
+ * qemuTPMEmulatorReconfigure
+ *
+ *
+ * @storagepath: path to the directory for TPM state
+ * @swtpm_user: The userid to switch to when setting up the TPM;
+ * typically this should be the uid of 'tss' or 'root'
+ * @swtpm_group: The group id to switch to
+ * @activePcrBanks: The string describing the active PCR banks
+ * @logfile: The file to write the log into; it must be writable
+ * for the user given by userid or 'tss'
+ * @tpmversion: The version of the TPM, either a TPM 1.2 or TPM 2
+ * @secretuuid: The secret's UUID needed for state encryption
+ *
+ * Reconfigure the active PCR banks of a TPM 2.
+ */
+static int
+qemuTPMEmulatorReconfigure(const char *storagepath,
+ uid_t swtpm_user,
+ gid_t swtpm_group,
+ unsigned int activePcrBanks,
+ const char *logfile,
+ const virDomainTPMVersion tpmversion,
+ const unsigned char *secretuuid)
+{
+ g_autoptr(virCommand) cmd = NULL;
+ int exitstatus;
+ g_autofree char *activePcrBanksStr;
+ g_autofree char *swtpm_setup = virTPMGetSwtpmSetup();
+ VIR_AUTOCLOSE pwdfile_fd = -1;
+
+ if (!swtpm_setup)
+ return -1;
+
+ if (tpmversion != VIR_DOMAIN_TPM_VERSION_2_0 ||
+ (activePcrBanksStr = qemuTPMPcrBankBitmapToStr(activePcrBanks)) == NULL ||
+ !virTPMSwtpmSetupCapsGet(VIR_TPM_SWTPM_SETUP_FEATURE_CMDARG_RECONFIGURE_PCR_BANKS))
+ return 0;
+
+ cmd = virCommandNew(swtpm_setup);
+ if (!cmd)
+ return -1;
+
+ virCommandSetUID(cmd, swtpm_user);
+ virCommandSetGID(cmd, swtpm_group);
+
+ virCommandAddArgList(cmd, "--tpm2", NULL);
+
+ if (qemuTPMVirCommandAddEncryption(cmd, swtpm_setup, secretuuid) < 0)
+ return -1;
+
+ virCommandAddArgList(cmd,
+ "--tpm-state", storagepath,
+ "--logfile", logfile,
+ "--pcr-banks", activePcrBanksStr,
+ "--reconfigure",
+ NULL);
+
+ virCommandClearCaps(cmd);
+
+ if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus != 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not run '%s --reconfigure'. exitstatus: %d; "
+ "Check error log '%s' for details."),
+ swtpm_setup, exitstatus, logfile);
+ return -1;
+ }
+
+ return 0;
+}
+
+
/*
* qemuTPMEmulatorBuildCommand:
*
secretuuid, incomingMigration) < 0)
goto error;
+ if (!incomingMigration &&
+ qemuTPMEmulatorReconfigure(tpm->data.emulator.storagepath,
+ swtpm_user, swtpm_group,
+ tpm->data.emulator.activePcrBanks,
+ tpm->data.emulator.logfile, tpm->version,
+ secretuuid) < 0)
+ goto error;
+
unlink(tpm->data.emulator.source.data.nix.path);
cmd = virCommandNew(swtpm);
"cmdarg-pwdfile-fd",
"cmdarg-create-config-files",
"tpm12-not-need-root",
+ "cmdarg-reconfigure-pcr-banks",
);
/**
VIR_TPM_SWTPM_SETUP_FEATURE_CMDARG_PWDFILE_FD,
VIR_TPM_SWTPM_SETUP_FEATURE_CMDARG_CREATE_CONFIG_FILES,
VIR_TPM_SWTPM_SETUP_FEATURE_TPM12_NOT_NEED_ROOT,
+ VIR_TPM_SWTPM_SETUP_FEATURE_CMDARG_RECONFIGURE_PCR_BANKS,
VIR_TPM_SWTPM_SETUP_FEATURE_LAST
} virTPMSwtpmSetupFeature;
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<tpm model='tpm-tis'>
- <backend type='emulator' version='2.0'/>
+ <backend type='emulator' version='2.0'>
+ <active_pcr_banks>
+ <sha256/>
+ <sha512/>
+ </active_pcr_banks>
+ </backend>
</tpm>
<memballoon model='virtio'/>
</devices>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<tpm model='tpm-tis'>
- <backend type='emulator' version='2.0'/>
+ <backend type='emulator' version='2.0'>
+ <active_pcr_banks>
+ <sha256/>
+ <sha512/>
+ </active_pcr_banks>
+ </backend>
</tpm>
<audio id='1' type='none'/>
<memballoon model='virtio'>