We're only returning the set of fields needed to perform an attestation, per the SEV API docs. Signed-off-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> --- src/qemu/qemu_monitor.c | 13 ++++++++++ src/qemu/qemu_monitor.h | 9 +++++++ src/qemu/qemu_monitor_json.c | 46 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 9 +++++++ tests/qemumonitorjsontest.c | 43 +++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 75e0e4ed92..dda6ae9796 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4366,6 +4366,19 @@ qemuMonitorGetSEVMeasurement(qemuMonitor *mon) } +int +qemuMonitorGetSEVInfo(qemuMonitor *mon, + unsigned int *apiMajor, + unsigned int *apiMinor, + unsigned int *buildID, + unsigned int *policy) +{ + QEMU_CHECK_MONITOR(mon); + + return qemuMonitorJSONGetSEVInfo(mon, apiMajor, apiMinor, buildID, policy); +} + + int qemuMonitorGetPRManagerInfo(qemuMonitor *mon, GHashTable **retinfo) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index edc2b01a66..29746f0b8e 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1445,6 +1445,15 @@ int qemuMonitorBlockdevMediumInsert(qemuMonitor *mon, char * qemuMonitorGetSEVMeasurement(qemuMonitor *mon); +int +qemuMonitorGetSEVInfo(qemuMonitor *mon, + unsigned int *apiMajor, + unsigned int *apiMinor, + unsigned int *buildID, + unsigned int *policy) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5); + typedef struct _qemuMonitorPRManagerInfo qemuMonitorPRManagerInfo; struct _qemuMonitorPRManagerInfo { bool connected; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index e00d785c20..a3d6eca569 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8216,6 +8216,52 @@ qemuMonitorJSONGetSEVMeasurement(qemuMonitor *mon) } +/** + * Retrive info about the SEV setup, returning those fields that + * are required to do a launch attestation, as per + * + * HMAC(0x04 || API_MAJOR || API_MINOR || BUILD || GCTX.POLICY || GCTX.LD || MNONCE; GCTX.TIK) + * + * specified in section 6.5.1 of AMD Secure Encrypted + * Virtualization API. + * + * { "execute": "query-sev" } + * { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0, + * "build-id" : 0, "policy" : 0, "state" : "running", + * "handle" : 1 } } + */ +int +qemuMonitorJSONGetSEVInfo(qemuMonitor *mon, + unsigned int *apiMajor, + unsigned int *apiMinor, + unsigned int *buildID, + unsigned int *policy) +{ + g_autoptr(virJSONValue) cmd = NULL; + g_autoptr(virJSONValue) reply = NULL; + virJSONValue *data; + + if (!(cmd = qemuMonitorJSONMakeCommand("query-sev", NULL))) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + return -1; + + if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0) + return -1; + + data = virJSONValueObjectGetObject(reply, "return"); + + if (virJSONValueObjectGetNumberUint(data, "api-major", apiMajor) < 0 || + virJSONValueObjectGetNumberUint(data, "api-minor", apiMinor) < 0 || + virJSONValueObjectGetNumberUint(data, "build-id", buildID) < 0 || + virJSONValueObjectGetNumberUint(data, "policy", policy) < 0) + return -1; + + return 0; +} + + /* * Example return data * diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 64064b0519..e88dfc9d50 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -459,6 +459,15 @@ qemuMonitorJSONSystemWakeup(qemuMonitor *mon); char * qemuMonitorJSONGetSEVMeasurement(qemuMonitor *mon); +int +qemuMonitorJSONGetSEVInfo(qemuMonitor *mon, + unsigned int *apiMajor, + unsigned int *apiMinor, + unsigned int *buildID, + unsigned int *policy) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5); + int qemuMonitorJSONGetVersion(qemuMonitor *mon, int *major, diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 1ad2912b08..1b0bd0870d 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -2884,6 +2884,48 @@ testQemuMonitorJSONqemuMonitorJSONGetCPUModelBaseline(const void *opaque) } +static int +testQemuMonitorJSONGetSEVInfo(const void *opaque) +{ + const testGenericData *data = opaque; + virDomainXMLOption *xmlopt = data->xmlopt; + g_autoptr(qemuMonitorTest) test = NULL; + unsigned int apiMajor = 0; + unsigned int apiMinor = 0; + unsigned int buildID = 0; + unsigned int policy = 0; + + if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema))) + return -1; + + if (qemuMonitorTestAddItem(test, "query-sev", + "{" + " \"return\": {" + " \"enabled\": false," + " \"api-minor\": 8," + " \"handle\": 0," + " \"state\": \"uninit\"," + " \"api-major\": 1," + " \"build-id\": 834," + " \"policy\": 3" + " }," + " \"id\": \"libvirt-15\"" + "}") < 0) + return -1; + + if (qemuMonitorGetSEVInfo(qemuMonitorTestGetMonitor(test), + &apiMajor, &apiMinor, &buildID, &policy) < 0) + return -1; + + if (apiMajor != 1 || apiMinor != 8 || buildID != 834 || policy != 3) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + "Unexpected SEV info values"); + return -1; + } + + return 0; +} + static int mymain(void) { @@ -2979,6 +3021,7 @@ mymain(void) DO_TEST(CPU); DO_TEST(GetNonExistingCPUData); DO_TEST(GetIOThreads); + DO_TEST(GetSEVInfo); DO_TEST(Transaction); DO_TEST(BlockExportAdd); DO_TEST(BlockdevReopen); -- 2.33.1