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

Reply via email to