mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-21 19:02:25 +00:00
qemu: tpm: Extend TPM domain XML with PCR banks to activate
Extend the TPM backend XML with a node 'active_pcr_banks' that allows a user to specify the PCR banks to activate before starting a VM. Valid choices for PCR banks are sha1, sha256, sha384 and sha512. When the XML node is provided, the set of active PCR banks is 'enforced' by running swtpm_setup before every start of the VM. The activation requires that swtpm_setup v0.7 or later is installed and may not have any effect otherwise. <tpm model='tpm-tis'> <backend type='emulator' version='2.0'> <active_pcr_banks> <sha256/> <sha384/> </active_pcr_banks> </backend> </tpm> Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2016599 Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
506c3a39d6
commit
a5bbe1a8b6
@ -7539,6 +7539,9 @@ Example: usage of the TPM Emulator
|
||||
<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>
|
||||
@ -7598,6 +7601,15 @@ Example: usage of the TPM Emulator
|
||||
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
|
||||
|
@ -5323,6 +5323,7 @@
|
||||
<value>emulator</value>
|
||||
</attribute>
|
||||
<ref name="tpm-backend-emulator-encryption"/>
|
||||
<ref name="tpm-backend-emulator-active-pcr-banks"/>
|
||||
<optional>
|
||||
<attribute name="persistent_state">
|
||||
<choice>
|
||||
@ -5366,6 +5367,35 @@
|
||||
</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>
|
||||
|
@ -1258,6 +1258,14 @@ VIR_ENUM_IMPL(virDomainTPMVersion,
|
||||
"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",
|
||||
@ -11735,6 +11743,10 @@ virDomainSmartcardDefParseXML(virDomainXMLOption *xmlopt,
|
||||
* <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>
|
||||
*
|
||||
@ -11753,6 +11765,8 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
|
||||
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;
|
||||
@ -11760,6 +11774,8 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
|
||||
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);
|
||||
|
||||
@ -11841,6 +11857,19 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
|
||||
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;
|
||||
@ -25440,10 +25469,27 @@ virDomainTPMDefFormat(virBuffer *buf,
|
||||
virBufferAsprintf(buf, "<encryption secret='%s'/>\n",
|
||||
virUUIDFormat(def->data.emulator.secretuuid, uuidstr));
|
||||
virBufferAdjustIndent(buf, -2);
|
||||
virBufferAddLit(buf, "</backend>\n");
|
||||
} else {
|
||||
virBufferAddLit(buf, "/>\n");
|
||||
}
|
||||
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
|
||||
virBufferAddLit(buf, "/>\n");
|
||||
break;
|
||||
case VIR_DOMAIN_TPM_TYPE_LAST:
|
||||
break;
|
||||
|
@ -1363,6 +1363,15 @@ typedef enum {
|
||||
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 {
|
||||
@ -1381,6 +1390,7 @@ struct _virDomainTPMDef {
|
||||
unsigned char secretuuid[VIR_UUID_BUFLEN];
|
||||
bool hassecretuuid;
|
||||
bool persistent_state;
|
||||
unsigned int activePcrBanks;
|
||||
} emulator;
|
||||
} data;
|
||||
};
|
||||
@ -3941,6 +3951,7 @@ VIR_ENUM_DECL(virDomainRNGBackend);
|
||||
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);
|
||||
|
@ -667,6 +667,8 @@ virDomainTPMBackendTypeToString;
|
||||
virDomainTPMDefFree;
|
||||
virDomainTPMModelTypeFromString;
|
||||
virDomainTPMModelTypeToString;
|
||||
virDomainTPMPcrBankTypeFromString;
|
||||
virDomainTPMPcrBankTypeToString;
|
||||
virDomainUSBDeviceDefForeach;
|
||||
virDomainVideoDefaultRAM;
|
||||
virDomainVideoDefClear;
|
||||
|
@ -565,6 +565,96 @@ qemuTPMEmulatorRunSetup(const char *storagepath,
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
*
|
||||
@ -619,6 +709,14 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
|
||||
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);
|
||||
|
@ -47,6 +47,7 @@ VIR_ENUM_IMPL(virTPMSwtpmSetupFeature,
|
||||
"cmdarg-pwdfile-fd",
|
||||
"cmdarg-create-config-files",
|
||||
"tpm12-not-need-root",
|
||||
"cmdarg-reconfigure-pcr-banks",
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -40,6 +40,7 @@ typedef enum {
|
||||
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;
|
||||
|
@ -23,7 +23,12 @@
|
||||
<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>
|
||||
|
@ -28,7 +28,12 @@
|
||||
<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'>
|
||||
|
Loading…
x
Reference in New Issue
Block a user