Run 'swtpm socket --print-capabilities' and 'swtpm_setup --print-capabilities' to get the JSON object of the features the programs are supporting and parse them into a bitmap. Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxx> --- include/libvirt/virterror.h | 2 + src/libvirt_private.syms | 2 + src/util/virerror.c | 2 + src/util/virtpm.c | 136 +++++++++++++++++++++++++++++++++++- src/util/virtpm.h | 15 ++++ 5 files changed, 155 insertions(+), 2 deletions(-) diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 102a2573bf..6f4110185a 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -134,6 +134,8 @@ typedef enum { VIR_FROM_FIREWALLD = 68, /* Error from firewalld */ VIR_FROM_DOMAIN_CHECKPOINT = 69, /* Error from domain checkpoint */ + VIR_FROM_TPM = 70, /* Error from TPM */ + # ifdef VIR_ENUM_SENTINELS VIR_ERR_DOMAIN_LAST # endif diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 4cdbb80596..cf80ea3e44 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3181,6 +3181,8 @@ virTPMEmulatorInit; virTPMGetSwtpm; virTPMGetSwtpmIoctl; virTPMGetSwtpmSetup; +virTPMSwtpmFeatureTypeFromString; +virTPMSwtpmSetupFeatureTypeFromString; # util/virtypedparam.h diff --git a/src/util/virerror.c b/src/util/virerror.c index dfba8c5712..77f76a9abf 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -142,6 +142,8 @@ VIR_ENUM_IMPL(virErrorDomain, "Resource control", "FirewallD", "Domain Checkpoint", + + "TPM", /* 70 */ ); diff --git a/src/util/virtpm.c b/src/util/virtpm.c index bef6cff3dd..99abbf3f8b 100644 --- a/src/util/virtpm.c +++ b/src/util/virtpm.c @@ -27,8 +27,24 @@ #include "viralloc.h" #include "virfile.h" #include "virtpm.h" +#include "vircommand.h" +#include "virbitmap.h" +#include "virjson.h" +#include "virlog.h" -#define VIR_FROM_THIS VIR_FROM_NONE +#define VIR_FROM_THIS VIR_FROM_TPM + +VIR_LOG_INIT("util.tpm"); + +VIR_ENUM_IMPL(virTPMSwtpmFeature, + VIR_TPM_SWTPM_FEATURE_LAST, + "cmdarg-pwd-fd", +); + +VIR_ENUM_IMPL(virTPMSwtpmSetupFeature, + VIR_TPM_SWTPM_SETUP_FEATURE_LAST, + "cmdarg-pwdfile-fd", +); /** * virTPMCreateCancelPath: @@ -74,18 +90,23 @@ virTPMCreateCancelPath(const char *devpath) } /* - * executables for the swtpm; to be found on the host + * executables for the swtpm; to be found on the host along with + * capabilties bitmap */ static virMutex swtpm_tools_lock = VIR_MUTEX_INITIALIZER; static char *swtpm_path; static struct stat swtpm_stat; +static virBitmapPtr swtpm_caps; static char *swtpm_setup; static struct stat swtpm_setup_stat; +static virBitmapPtr swtpm_setup_caps; static char *swtpm_ioctl; static struct stat swtpm_ioctl_stat; +typedef int (*TypeFromStringFn)(const char *); + char * virTPMGetSwtpm(void) { @@ -131,6 +152,101 @@ virTPMGetSwtpmIoctl(void) return s; } +/* virTPMExecGetCaps + * + * Execute the prepared command and parse the returned JSON object + * to get the capabilities supported by the executable. + * A JSON object like this is expected: + * + * { + * "type": "swtpm", + * "features": [ + * "cmdarg-seccomp", + * "cmdarg-key-fd", + * "cmdarg-pwd-fd" + * ] + * } + */ +static virBitmapPtr +virTPMExecGetCaps(virCommandPtr cmd, + TypeFromStringFn typeFromStringFn) +{ + int exitstatus; + virBitmapPtr bitmap; + VIR_AUTOFREE(char *) outbuf = NULL; + VIR_AUTOPTR(virJSONValue) json = NULL; + virJSONValuePtr featureList; + virJSONValuePtr item; + size_t idx; + const char *str; + int typ; + + virCommandSetOutputBuffer(cmd, &outbuf); + if (virCommandRun(cmd, &exitstatus) < 0) + return NULL; + + if (!(bitmap = virBitmapNewEmpty())) + return NULL; + + /* older version does not support --print-capabilties -- that's fine */ + if (exitstatus != 0) { + VIR_DEBUG("Found swtpm that doesn't support --print-capabilities"); + return bitmap; + } + + json = virJSONValueFromString(outbuf); + if (!json) + goto error_bad_json; + + featureList = virJSONValueObjectGetArray(json, "features"); + if (!featureList) + goto error_bad_json; + + if (!virJSONValueIsArray(featureList)) + goto error_bad_json; + + for (idx = 0; idx < virJSONValueArraySize(featureList); idx++) { + item = virJSONValueArrayGet(featureList, idx); + if (!item) + continue; + + str = virJSONValueGetString(item); + if (!str) + goto error_bad_json; + typ = typeFromStringFn(str); + if (typ < 0) + continue; + + if (virBitmapSetBitExpand(bitmap, typ) < 0) + goto cleanup; + } + + cleanup: + return bitmap; + + error_bad_json: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected JSON format: %s"), outbuf); + goto cleanup; +} + +static virBitmapPtr +virTPMGetCaps(TypeFromStringFn typeFromStringFn, + const char *exec, const char *param1) +{ + VIR_AUTOPTR(virCommand) cmd = NULL; + + if (!(cmd = virCommandNew(exec))) + return NULL; + + if (param1) + virCommandAddArg(cmd, param1); + virCommandAddArg(cmd, "--print-capabilities"); + virCommandClearCaps(cmd); + + return virTPMExecGetCaps(cmd, typeFromStringFn); +} + /* * virTPMEmulatorInit * @@ -145,16 +261,24 @@ virTPMEmulatorInit(void) const char *name; char **path; struct stat *stat; + const char *parm; + virBitmapPtr *caps; + TypeFromStringFn typeFromStringFn; } prgs[] = { { .name = "swtpm", .path = &swtpm_path, .stat = &swtpm_stat, + .parm = "socket", + .caps = &swtpm_caps, + .typeFromStringFn = virTPMSwtpmFeatureTypeFromString, }, { .name = "swtpm_setup", .path = &swtpm_setup, .stat = &swtpm_setup_stat, + .caps = &swtpm_setup_caps, + .typeFromStringFn = virTPMSwtpmSetupFeatureTypeFromString, }, { .name = "swtpm_ioctl", @@ -209,6 +333,14 @@ virTPMEmulatorInit(void) goto cleanup; } *prgs[i].path = path; + + if (prgs[i].caps) { + *prgs[i].caps = virTPMGetCaps(prgs[i].typeFromStringFn, + path, prgs[i].parm); + path = NULL; + if (!*prgs[i].caps) + goto cleanup; + } path = NULL; } } diff --git a/src/util/virtpm.h b/src/util/virtpm.h index 2311f04ae5..157b43ff17 100644 --- a/src/util/virtpm.h +++ b/src/util/virtpm.h @@ -26,3 +26,18 @@ char *virTPMGetSwtpm(void); char *virTPMGetSwtpmSetup(void); char *virTPMGetSwtpmIoctl(void); int virTPMEmulatorInit(void); + +typedef enum { + VIR_TPM_SWTPM_FEATURE_CMDARG_PWD_FD, + + VIR_TPM_SWTPM_FEATURE_LAST +} virTPMSwtpmFeature; + +typedef enum { + VIR_TPM_SWTPM_SETUP_FEATURE_CMDARG_PWDFILE_FD, + + VIR_TPM_SWTPM_SETUP_FEATURE_LAST +} virTPMSwtpmSetupFeature; + +VIR_ENUM_DECL(virTPMSwtpmFeature); +VIR_ENUM_DECL(virTPMSwtpmSetupFeature); -- 2.20.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list