From: Akio Kakuno <[email protected]>
- Add ARM CCA support to the qemu driver for aarch64 systems.
[XML example]
<domain>
...
<launchsecurity type='cca'>
<measurement-algo>sha256</measurement-algo>
</launchsecurity>
...
</domain>
Signed-off-by: Kazuhiro Abe <[email protected]>
---
docs/formatdomain.rst | 46 ++++++++++++++++++++++++++++++++++
src/conf/domain_capabilities.h | 6 +++++
src/conf/domain_conf.c | 25 ++++++++++++++++++
src/conf/domain_conf.h | 9 +++++++
src/conf/domain_validate.c | 1 +
src/conf/virconftypes.h | 2 ++
src/qemu/qemu_capabilities.c | 4 +++
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_cgroup.c | 2 ++
src/qemu/qemu_command.c | 30 ++++++++++++++++++++++
src/qemu/qemu_driver.c | 2 ++
src/qemu/qemu_firmware.c | 1 +
src/qemu/qemu_namespace.c | 2 ++
src/qemu/qemu_process.c | 4 +++
src/qemu/qemu_validate.c | 4 +++
src/security/security_dac.c | 2 ++
16 files changed, 141 insertions(+)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 04ef319a73..19c6006980 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -9728,6 +9728,52 @@ Example configuration:
``/var/run/tdx-qgs/qgs.socket`` is used as default. User in TD guest cannot
get TD quoting for attestation if this subelement is not provided.
+The contents of the ``<launchSecurity type='cca'>`` element is used to create
+RealmVM using the Arm CCA feature (Confidential Compute Architecture).
+CCA :since:`Since 11.0.0` enhances the virtualization capabilities of the
+platform by separating the management of resources from access to those
resources.
+This is achieved by extending the TrustZone of Cortex-A's Normal and Secure
+world concepts and adding the Realm world and the underlying Root world.
+The Secure Monitor runs in the root world and manages the transition between
+these security states. For more information see the Learn the architecture -
+Arm Confidential Compute Architecture software stack:
+`<https://developer.arm.com/documentation/den0127/latest>`__
+
+::
+
+ <domain>
+ ...
+ <launchSecurity type='cca' measurement-log='yes'>
+ <measurement-algo>sha256</measurement-algo>
+ <personalization-value>...</personalization-value>
+ </launchSecurity>
+ ...
+ </domain>
+
+The ``<launchSecurity/>`` element accepts the following attributes:
+
+``measurement-algo``
+ The optional ``measurement-algo`` element determines algorithm used to
+ describe blob hashes.
+ The default value, when omitted, is determined by QEMU.
+
+``personalization-value``
+ The optional ``personalization-value`` element is used to configure
+ the Realm Personalization Value (RPV). The Realm Personalization
+ Value (RPV) is provided by the user to distinguish Realms that have
+ the same initial measurement. The personalization-value for libvirt
+ must be an 88-character string representing the Base64 encoding of
+ the 64-byte hexadecimal value defined in the RMM specification.
+ Ensure that you encode the 64-byte hex value from the RMM specification
+ using Base64 before providing it to libvirt.
+ The default value, when omitted, is determined by QEMU.
+
+``measurement-log``
+ The optional ``measurement-log`` element provides a way to create
+ an event log in the format defined by the Trusted Computing Group
+ for TPM2.
+ The default value, when omitted, is determined by QEMU.
+
Example configs
===============
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 437981c711..0ce68b44ef 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -245,6 +245,12 @@ struct _virSGXCapability {
virSGXSection *sgxSections;
};
+typedef struct _virCCACapability virCCACapability;
+struct _virCCACapability {
+ size_t nCcaMeasurementAlgo;
+ char **ccaMeasurementAlgo;
+};
+
STATIC_ASSERT_ENUM(VIR_DOMAIN_CRYPTO_MODEL_LAST);
STATIC_ASSERT_ENUM(VIR_DOMAIN_CRYPTO_TYPE_LAST);
STATIC_ASSERT_ENUM(VIR_DOMAIN_CRYPTO_BACKEND_LAST);
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9ca5c2450c..3a8f9c0316 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1545,6 +1545,7 @@ VIR_ENUM_IMPL(virDomainLaunchSecurity,
"sev-snp",
"s390-pv",
"tdx",
+ "cca",
);
VIR_ENUM_IMPL(virDomainPstoreBackend,
@@ -3972,6 +3973,10 @@ virDomainSecDefFree(virDomainSecDef *def)
g_free(def->data.tdx.mrownerconfig);
g_free(def->data.tdx.qgs_unix_path);
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
+ g_free(def->data.cca.measurement_algo);
+ g_free(def->data.cca.personalization_value);
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
@@ -14316,6 +14321,21 @@ virDomainTDXDefParseXML(virDomainTDXDef *def,
}
+static int
+virDomainCCADefParseXML(virDomainCCADef *def,
+ xmlXPathContextPtr ctxt)
+{
+ def->measurement_algo = virXPathString("string(./measurement-algo)", ctxt);
+ def->personalization_value =
virXPathString("string(./personalization-value)", ctxt);
+
+ if (virXMLPropTristateBool(ctxt->node, "measurement-log",
VIR_XML_PROP_NONE,
+ &def->measurement_log) < 0)
+ return -1;
+
+ return 0;
+}
+
+
static virDomainSecDef *
virDomainSecDefParseXML(xmlNodePtr lsecNode,
xmlXPathContextPtr ctxt)
@@ -14345,6 +14365,10 @@ virDomainSecDefParseXML(xmlNodePtr lsecNode,
break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
+ if (virDomainCCADefParseXML(&sec->data.cca, ctxt) < 0)
+ return NULL;
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
default:
@@ -28021,6 +28045,7 @@ virDomainSecDefFormat(virBuffer *buf, virDomainSecDef
*sec)
break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index cb35ff06bd..dfe903e85e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2976,6 +2976,7 @@ typedef enum {
VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP,
VIR_DOMAIN_LAUNCH_SECURITY_PV,
VIR_DOMAIN_LAUNCH_SECURITY_TDX,
+ VIR_DOMAIN_LAUNCH_SECURITY_CCA,
VIR_DOMAIN_LAUNCH_SECURITY_LAST,
} virDomainLaunchSecurity;
@@ -3029,12 +3030,20 @@ struct _virDomainTDXDef {
#define VIR_DOMAIN_TDX_POLICY_ALLOWED_MASK (VIR_DOMAIN_TDX_POLICY_DEBUG
| \
VIR_DOMAIN_TDX_POLICY_SEPT_VE_DISABLE)
+struct _virDomainCCADef {
+ char *measurement_algo;
+ char *personalization_value;
+ virTristateBool measurement_log;
+};
+
+
struct _virDomainSecDef {
virDomainLaunchSecurity sectype;
union {
virDomainSEVDef sev;
virDomainSEVSNPDef sev_snp;
virDomainTDXDef tdx;
+ virDomainCCADef cca;
} data;
};
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 7346a61731..0a82f63aee 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -2000,6 +2000,7 @@ virDomainDefLaunchSecurityValidate(const virDomainDef
*def)
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
break;
}
diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
index 6e2573035a..475ec99a4e 100644
--- a/src/conf/virconftypes.h
+++ b/src/conf/virconftypes.h
@@ -224,6 +224,8 @@ typedef struct _virDomainSEVSNPDef virDomainSEVSNPDef;
typedef struct _virDomainTDXDef virDomainTDXDef;
+typedef struct _virDomainCCADef virDomainCCADef;
+
typedef struct _virDomainSecDef virDomainSecDef;
typedef struct _virDomainShmemDef virDomainShmemDef;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 92b863a826..9a2eadb673 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -755,6 +755,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
"disk-timed-stats", /* QEMU_CAPS_DISK_TIMED_STATS */
"query-accelerators", /* QEMU_CAPS_QUERY_ACCELERATORS */
"mshv", /* QEMU_CAPS_MSHV */
+ "rme-guest", /* QEMU_CAPS_CCA_GUEST */
);
@@ -840,6 +841,8 @@ struct _virQEMUCaps {
virSGXCapability *sgxCapabilities;
+ virCCACapability *ccaCapabilities;
+
virDomainCapsFeatureHyperv *hypervCapabilities;
/* Capabilities which may differ depending on the accelerator. */
@@ -1462,6 +1465,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
{ "tpm-emulator", QEMU_CAPS_DEVICE_TPM_EMULATOR },
{ "tpm-passthrough", QEMU_CAPS_DEVICE_TPM_PASSTHROUGH },
{ "acpi-generic-initiator", QEMU_CAPS_ACPI_GENERIC_INITIATOR },
+ { "rme-guest", QEMU_CAPS_CCA_GUEST },
};
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index f180844e66..71e3440180 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -730,6 +730,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for
syntax-check */
QEMU_CAPS_DISK_TIMED_STATS, /* timed stats support ('stats-intervals'
property of disk frontends) */
QEMU_CAPS_QUERY_ACCELERATORS, /* query-accelerators command */
QEMU_CAPS_MSHV, /* -accel mshv */
+ QEMU_CAPS_CCA_GUEST, /* -object rme-guest */
QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 7dadef0739..9adb4bed1c 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -874,6 +874,8 @@ qemuSetupDevicesCgroup(virDomainObj *vm)
if (qemuSetupSEVCgroup(vm) < 0)
return -1;
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
break;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 0de0a79b46..d12c84e048 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7244,6 +7244,9 @@ qemuBuildMachineCommandLine(virCommand *cmd,
case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
virBufferAddLit(&buf, ",confidential-guest-support=lsec0");
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
+ virBufferAddLit(&buf, ",confidential-guest-support=rme0");
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
virReportEnumRangeError(virDomainLaunchSecurity,
def->sec->sectype);
@@ -10052,6 +10055,29 @@ qemuBuildTDXCommandLine(virCommand *cmd,
virDomainTDXDef *tdx)
}
+static int
+qemuBuildCCACommandLine(virCommand *cmd, virDomainCCADef *cca)
+{
+ g_autoptr(virJSONValue) props = NULL;
+
+ VIR_DEBUG("measurement_algorithm=%s personalization_value=%s
measurement_log=%d",
+ cca->measurement_algo, cca->personalization_value,
+ cca->measurement_log);
+
+ if (qemuMonitorCreateObjectProps(&props, "rme-guest", "rme0",
+ "S:measurement-algorithm",
cca->measurement_algo,
+ "S:personalization-value",
cca->personalization_value,
+ "T:measurement-log", cca->measurement_log,
+ NULL) < 0)
+ return -1;
+
+ if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0)
+ return -1;
+
+ return 0;
+}
+
+
static int
qemuBuildSecCommandLine(virDomainObj *vm, virCommand *cmd,
virDomainSecDef *sec)
@@ -10071,6 +10097,10 @@ qemuBuildSecCommandLine(virDomainObj *vm, virCommand
*cmd,
case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
return qemuBuildTDXCommandLine(cmd, &sec->data.tdx);
+
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
+ return qemuBuildCCACommandLine(cmd, &sec->data.cca);
+
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
virReportEnumRangeError(virDomainLaunchSecurity, sec->sectype);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3f154969b8..619d80bc24 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -19452,6 +19452,8 @@ qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
if (qemuDomainGetSEVInfo(vm, list, flags) < 0)
goto cleanup;
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
break;
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 52205b72f8..9391956521 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1401,6 +1401,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
index c689cc3e40..6ba7e5cab4 100644
--- a/src/qemu/qemu_namespace.c
+++ b/src/qemu/qemu_namespace.c
@@ -672,6 +672,8 @@ qemuDomainSetupLaunchSecurity(virDomainObj *vm,
VIR_DEBUG("Set up launch security for SEV");
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
break;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index a53bb40783..ebf1e27ccf 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7144,6 +7144,8 @@ qemuProcessPrepareDomain(virQEMUDriver *driver,
if (qemuProcessUpdateSEVInfo(vm) < 0)
return -1;
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
break;
@@ -7217,6 +7219,8 @@ qemuProcessPrepareLaunchSecurityGuestInput(virDomainObj
*vm)
return qemuProcessPrepareSEVGuestInput(vm);
case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
+ return 0;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
return 0;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 184c23d307..167a4b532f 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -1512,6 +1512,10 @@ qemuValidateDomainDef(const virDomainDef *def,
return -1;
}
break;
+
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
+ break;
+
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
virReportEnumRangeError(virDomainLaunchSecurity,
def->sec->sectype);
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 2f788b872a..3c85f0bc15 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -2018,6 +2018,7 @@ virSecurityDACRestoreAllLabel(virSecurityManager *mgr,
break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
@@ -2265,6 +2266,7 @@ virSecurityDACSetAllLabel(virSecurityManager *mgr,
break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
+ case VIR_DOMAIN_LAUNCH_SECURITY_CCA:
break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
--
2.43.0