forked from pool/s390-tools
* s390-tools-01-zkey-Add-support-for-retrieving-a-list-of-ultravisor-secrets.patch * s390-tools-02-zkey-Add-the--pvsecrets-list-command.patch * s390-tools-03-zkey-Add-PVSECRETS-AES-key-type.patch * s390-tools-04-zkey-Add-the-pvsecrets-import-command.patch * s390-tools-05-zkey-Reject-key-generation-and-APQN-association-for-PVSECRET-AES-keys.patch * s390-tools-06-zkey-Reject-re-enciphering-of-PVSECRET-AES-keys.patch * s390-tools-07-zkey-Support-validation-of-key-of-type-PVSECRET-AES.patch - Revendored vendor.tar.gz OBS-URL: https://build.opensuse.org/package/show/Base:System/s390-tools?expand=0&rev=245
300 lines
8.4 KiB
Diff
300 lines
8.4 KiB
Diff
From 8c4b2872b8e24c1a27d8201beb5979c66ac05268 Mon Sep 17 00:00:00 2001
|
|
From: Ingo Franzki <ifranzki@linux.ibm.com>
|
|
Date: Thu, 15 Feb 2024 09:08:43 +0100
|
|
Subject: [PATCH] zkey: Add support for retrieving a list of ultravisor secrets
|
|
|
|
Add functions to interface with the ultravisor device (/dev/uv) when
|
|
running in a secure execution guest to retrieve a list of available
|
|
secrets.
|
|
|
|
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
|
|
Reviewed-by: Jorg Schmidbauer <jschmidb@de.ibm.com>
|
|
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
|
|
---
|
|
zkey/Makefile | 4 +-
|
|
zkey/pvsecrets.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
zkey/pvsecrets.h | 89 ++++++++++++++++++++++++++
|
|
3 files changed, 253 insertions(+), 1 deletion(-)
|
|
create mode 100644 zkey/pvsecrets.c
|
|
create mode 100644 zkey/pvsecrets.h
|
|
|
|
diff --git a/zkey/Makefile b/zkey/Makefile
|
|
index 501c5ebf..cbecf125 100644
|
|
--- a/zkey/Makefile
|
|
+++ b/zkey/Makefile
|
|
@@ -92,9 +92,11 @@ keystore.o: keystore.c keystore.h properties.h pkey.h cca.h ep11.h utils.h
|
|
zkey-cryptsetup.o: check-dep-zkey-cryptsetup zkey-cryptsetup.c pkey.h cca.h \
|
|
ep11.h misc.h utils.h
|
|
kms.o: kms.c kms.h kms-plugin.h utils.h pkey.h
|
|
+pvsecrets.o: pvsecrets.h
|
|
|
|
zkey: LDLIBS = -ldl -lcrypto
|
|
-zkey: zkey.o pkey.o cca.o ep11.o properties.o keystore.o utils.o kms.o $(libs)
|
|
+zkey: zkey.o pkey.o cca.o ep11.o properties.o keystore.o utils.o kms.o \
|
|
+ pvsecrets.o $(libs)
|
|
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
|
|
|
zkey-cryptsetup: LDLIBS = -ldl -lcryptsetup -ljson-c -lcrypto
|
|
diff --git a/zkey/pvsecrets.c b/zkey/pvsecrets.c
|
|
new file mode 100644
|
|
index 00000000..2874fdf1
|
|
--- /dev/null
|
|
+++ b/zkey/pvsecrets.c
|
|
@@ -0,0 +1,161 @@
|
|
+/*
|
|
+ * zkey - Generate, re-encipher, and validate secure keys
|
|
+ *
|
|
+ * Copyright IBM Corp. 2024
|
|
+ *
|
|
+ * s390-tools is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the MIT license. See LICENSE for details.
|
|
+ */
|
|
+
|
|
+#include <err.h>
|
|
+#include <errno.h>
|
|
+#include <fcntl.h>
|
|
+#include <stdbool.h>
|
|
+#include <string.h>
|
|
+#include <stdint.h>
|
|
+#include <sys/ioctl.h>
|
|
+#include <sys/types.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+#include "lib/util_base.h"
|
|
+#include "lib/util_file.h"
|
|
+#include "lib/util_libc.h"
|
|
+#include "lib/util_panic.h"
|
|
+#include "lib/util_path.h"
|
|
+
|
|
+#include "pvsecrets.h"
|
|
+
|
|
+#define pr_verbose(verbose, fmt...) do { \
|
|
+ if (verbose) \
|
|
+ warnx(fmt); \
|
|
+ } while (0)
|
|
+
|
|
+/**
|
|
+ * Opens the ultravisor device and returns its file descriptor.
|
|
+ * This only succeeds when running in a secure execution guest.
|
|
+ * A failure of this function indicates that it is not running in a secure
|
|
+ * execution guest.
|
|
+ *
|
|
+ * @param verbose if true, verbose messages are printed
|
|
+ *
|
|
+ * @returns the file descriptor or -1 to indicate an error
|
|
+ */
|
|
+int uv_open_device(bool verbose)
|
|
+{
|
|
+ unsigned int pvguest = 0, max_retr_secrets = 0;
|
|
+ char *path = NULL;
|
|
+ int uv_fd, err;
|
|
+
|
|
+ uv_fd = open(UVDEVICE, O_RDWR);
|
|
+ if (uv_fd < 0) {
|
|
+ err = errno;
|
|
+ warnx("File '%s:' %s\n", UVDEVICE, strerror(errno));
|
|
+ if (err == EACCES)
|
|
+ warnx("Only the 'root' user is allowed to perform "
|
|
+ "this command");
|
|
+ else
|
|
+ warnx("Ensure that you are running in a secure "
|
|
+ "execution guest, and that the 'uvdevice' "
|
|
+ "kernel module is loaded.");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ path = util_path_sysfs(SYSFS_UV);
|
|
+ if (util_file_read_ui(&pvguest, 10, SYSFS_UV_PV_GUEST, path) != 0 ||
|
|
+ pvguest != 1) {
|
|
+ warnx("You are not running in a secure execution guest.");
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ if (util_file_read_ui(&max_retr_secrets, 10, SYSFS_UV_MAX_SECRETS,
|
|
+ path) != 0 ||
|
|
+ max_retr_secrets == 0) {
|
|
+ warnx("The ultravisor device is at a too old version, or "
|
|
+ "the ultravisor does not support retrievable secrets.");
|
|
+ goto error;
|
|
+ }
|
|
+ free(path);
|
|
+
|
|
+ pr_verbose(verbose, "Device '%s' has been opened successfully",
|
|
+ UVDEVICE);
|
|
+ return uv_fd;
|
|
+
|
|
+error:
|
|
+ free(path);
|
|
+ close(uv_fd);
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Retrieves a list of secrets from the ultravisor. Calls the supplied callback
|
|
+ * function for each secret found.
|
|
+ *
|
|
+ * @param uv_fd the file descriptor of the ultravisor device
|
|
+ * @param cb the callback function
|
|
+ * @param cb_private private data to pass to the callback function
|
|
+ * @param verbose if true, verbose messages are printed
|
|
+ *
|
|
+ * @returns 0 on success, a negative errno in case of an error
|
|
+ */
|
|
+static int uv_list_secrets(int uv_fd, int (*cb)(u16 idx, u16 type, u32 len,
|
|
+ const u8 id[UV_SECRET_ID_LEN],
|
|
+ void *cb_private),
|
|
+ void *cb_private, bool verbose)
|
|
+{
|
|
+ struct uvio_list_secrets *list;
|
|
+ struct uvio_ioctl_cb io;
|
|
+ unsigned int i;
|
|
+ int rc;
|
|
+
|
|
+ util_assert(uv_fd != -1, "Internal error: uv_fd is -1");
|
|
+ util_assert(cb != NULL, "Internal error: cb is NULL");
|
|
+
|
|
+ list = util_zalloc(UVIO_LIST_SECRETS_MAX_LEN);
|
|
+
|
|
+ memset(&io, 0, sizeof(io));
|
|
+ io.argument_addr = list;
|
|
+ io.argument_len = UVIO_LIST_SECRETS_MAX_LEN;
|
|
+
|
|
+ rc = ioctl(uv_fd, UVIO_IOCTL_LIST_SECRETS, &io);
|
|
+ if (rc != 0) {
|
|
+ rc = -errno;
|
|
+
|
|
+ pr_verbose(verbose, "ioctl UVIO_IOCTL_LIST_SECRETS: %s",
|
|
+ strerror(-rc));
|
|
+
|
|
+ if (rc == -ENOTTY || rc == -EINVAL)
|
|
+ warnx("The ultravisor device is at a too old version");
|
|
+
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (io.uv_rc != UVIO_RC_SUCCESS) {
|
|
+ pr_verbose(verbose, "ioctl UVIO_IOCTL_LIST_SECRETS' uv_rc: %u",
|
|
+ io.uv_rc);
|
|
+ rc = -EIO;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ pr_verbose(verbose, "Number of secrets: %u", list->num_secrets_stored);
|
|
+
|
|
+ for (i = 0; i < list->num_secrets_stored &&
|
|
+ i < ARRAY_SIZE(list->secret_entries); i++) {
|
|
+ if (list->secret_entries[i].secret_type <=
|
|
+ UV_SECRET_TYPE_AP_ASSOCIATION)
|
|
+ continue;
|
|
+
|
|
+ rc = cb(list->secret_entries[i].secret_idx,
|
|
+ list->secret_entries[i].secret_type,
|
|
+ list->secret_entries[i].secret_len,
|
|
+ list->secret_entries[i].secret_id,
|
|
+ cb_private);
|
|
+ if (rc != 0)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+out:
|
|
+ free(list);
|
|
+
|
|
+ return rc;
|
|
+}
|
|
diff --git a/zkey/pvsecrets.h b/zkey/pvsecrets.h
|
|
new file mode 100644
|
|
index 00000000..2667e859
|
|
--- /dev/null
|
|
+++ b/zkey/pvsecrets.h
|
|
@@ -0,0 +1,89 @@
|
|
+/*
|
|
+ * zkey - Generate, re-encipher, and validate secure keys
|
|
+ *
|
|
+ * This header file defines functions for the PV secrets support as well
|
|
+ * as the interface to the uv kernel module.
|
|
+ *
|
|
+ * Copyright IBM Corp. 2024
|
|
+ *
|
|
+ * s390-tools is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the MIT license. See LICENSE for details.
|
|
+ */
|
|
+
|
|
+#ifndef PVSECRETS_H
|
|
+#define PVSECRETS_H
|
|
+
|
|
+#include "lib/zt_common.h"
|
|
+
|
|
+/*
|
|
+ * Definitions for the /dev/uv kernel module interface
|
|
+ */
|
|
+#define UVDEVICE "/dev/uv"
|
|
+#define SYSFS_UV "firmware/uv"
|
|
+#define SYSFS_UV_PV_GUEST "%s/prot_virt_guest"
|
|
+#define SYSFS_UV_MAX_SECRETS "%s/query/max_retr_secrets"
|
|
+
|
|
+struct uvio_ioctl_cb {
|
|
+ u32 flags;
|
|
+ u16 uv_rc; /* UV header rc value */
|
|
+ u16 uv_rrc; /* UV header rrc value */
|
|
+ void *argument_addr; /* Userspace address of uvio argument */
|
|
+ u32 argument_len;
|
|
+ u8 reserved14[0x40 - 0x14]; /* must be zero */
|
|
+};
|
|
+
|
|
+#define UVIO_IOCTL_LIST_SECRETS_NR 3
|
|
+
|
|
+#define UVIO_TYPE_UVC 'u'
|
|
+#define UVIO_IOCTL(nr) _IOWR(UVIO_TYPE_UVC, \
|
|
+ nr, struct uvio_ioctl_cb)
|
|
+#define UVIO_IOCTL_LIST_SECRETS UVIO_IOCTL( \
|
|
+ UVIO_IOCTL_LIST_SECRETS_NR)
|
|
+
|
|
+#define UVIO_RC_SUCCESS 0x0001
|
|
+#define UVIO_RC_MORE_DATA 0x0100
|
|
+
|
|
+#define UV_SECRET_TYPE_INVALID 0x00
|
|
+#define UV_SECRET_TYPE_NULL 0x01
|
|
+#define UV_SECRET_TYPE_AP_ASSOCIATION 0x02
|
|
+#define UV_SECRET_TYPE_PLAIN_TEXT 0x03
|
|
+#define UV_SECRET_TYPE_AES_128 0x04
|
|
+#define UV_SECRET_TYPE_AES_192 0x05
|
|
+#define UV_SECRET_TYPE_AES_256 0x06
|
|
+#define UV_SECRET_TYPE_AES_XTS_128 0x07
|
|
+#define UV_SECRET_TYPE_AES_XTS_256 0x08
|
|
+#define UV_SECRET_TYPE_HMAC_SHA_256 0x09
|
|
+#define UV_SECRET_TYPE_HMAC_SHA_512 0x0a
|
|
+#define UV_SECRET_TYPE_ECDSA_P256 0x11
|
|
+#define UV_SECRET_TYPE_ECDSA_P384 0x12
|
|
+#define UV_SECRET_TYPE_ECDSA_P521 0x13
|
|
+#define UV_SECRET_TYPE_EDDSA_ED25519 0x14
|
|
+#define UV_SECRET_TYPE_EDDSA_ED448 0x15
|
|
+
|
|
+#define UV_SECRET_ID_LEN 32
|
|
+
|
|
+#define UVIO_LIST_SECRETS_MAX_LEN 0x8000
|
|
+
|
|
+struct uvio_list_secret_entry {
|
|
+ u16 secret_idx;
|
|
+ u16 secret_type;
|
|
+ u32 secret_len;
|
|
+ u64 reserved;
|
|
+ u8 secret_id[UV_SECRET_ID_LEN];
|
|
+} __packed;
|
|
+
|
|
+#define UVIO_MAX_SECRET_ENTRIES ((UVIO_LIST_SECRETS_MAX_LEN - 16) / \
|
|
+ sizeof(struct uvio_list_secret_entry))
|
|
+
|
|
+struct uvio_list_secrets {
|
|
+ u16 num_secrets_stored;
|
|
+ u16 num_secrets_total;
|
|
+ u16 next_secret_idx;
|
|
+ u16 reserved1;
|
|
+ u64 reserved2;
|
|
+ struct uvio_list_secret_entry secret_entries[UVIO_MAX_SECRET_ENTRIES];
|
|
+} __packed;
|
|
+
|
|
+int uv_open_device(bool verbose);
|
|
+
|
|
+#endif
|