mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
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>
This commit is contained in:
committed by
Steffen Eiden
parent
7be364aa84
commit
8c4b2872b8
+3
-1
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user