Commit 28a51ee8 authored by Steffen Eiden's avatar Steffen Eiden Committed by Heiko Carstens
Browse files

s390/uv: Provide host-key hashes in sysfs



Utilize the new Query Ultravisor Keys UVC to give user space the
information which host-keys are installed on the system.

Create a new sysfs directory 'firmware/uv/keys' that contains the hash
of the host-key and the backup host-key of that system. Additionally,
the file 'all' contains the response from the UVC possibly containing
more key-hashes than currently known.

Reviewed-by: default avatarJanosch Frank <frankja@linux.ibm.com>
Signed-off-by: default avatarSteffen Eiden <seiden@linux.ibm.com>
Link: https://lore.kernel.org/r/20241023075529.2561384-1-seiden@linux.ibm.com


Signed-off-by: default avatarJanosch Frank <frankja@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent bb4ad73a
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#define UVC_RC_NEED_DESTROY	0x8000

#define UVC_CMD_QUI			0x0001
#define UVC_CMD_QUERY_KEYS		0x0002
#define UVC_CMD_INIT_UV			0x000f
#define UVC_CMD_CREATE_SEC_CONF		0x0100
#define UVC_CMD_DESTROY_SEC_CONF	0x0101
@@ -94,6 +95,7 @@ enum uv_cmds_inst {
	BIT_UVC_CMD_ADD_SECRET = 29,
	BIT_UVC_CMD_LIST_SECRETS = 30,
	BIT_UVC_CMD_LOCK_SECRETS = 31,
	BIT_UVC_CMD_QUERY_KEYS = 34,
};

enum uv_feat_ind {
@@ -145,6 +147,21 @@ struct uv_cb_qui {
	u8 reserved112[0x120 - 0x112];		/* 0x0112 */
} __packed __aligned(8);

struct uv_key_hash {
	u64 dword[4];
} __packed __aligned(8);

#define UVC_QUERY_KEYS_IDX_HK		0
#define UVC_QUERY_KEYS_IDX_BACK_HK	1

/* Query Ultravisor Keys */
struct uv_cb_query_keys {
	struct uv_cb_header header;		/* 0x0000 */
	u64 reserved08[3];			/* 0x0008 */
	struct uv_key_hash key_hashes[15];	/* 0x0020 */
} __packed __aligned(8);
static_assert(sizeof(struct uv_cb_query_keys) == 0x200);

/* Initialize Ultravisor */
struct uv_cb_init {
	struct uv_cb_header header;
+71 −0
Original line number Diff line number Diff line
@@ -722,10 +722,76 @@ static struct attribute *uv_query_attrs[] = {
	NULL,
};

static inline struct uv_cb_query_keys uv_query_keys(void)
{
	struct uv_cb_query_keys uvcb = {
		.header.cmd = UVC_CMD_QUERY_KEYS,
		.header.len = sizeof(uvcb)
	};

	uv_call(0, (uint64_t)&uvcb);
	return uvcb;
}

static inline ssize_t emit_hash(struct uv_key_hash *hash, char *buf, int at)
{
	return sysfs_emit_at(buf, at, "%016llx%016llx%016llx%016llx\n",
			    hash->dword[0], hash->dword[1], hash->dword[2], hash->dword[3]);
}

static ssize_t uv_keys_host_key(struct kobject *kobj,
				struct kobj_attribute *attr, char *buf)
{
	struct uv_cb_query_keys uvcb = uv_query_keys();

	return emit_hash(&uvcb.key_hashes[UVC_QUERY_KEYS_IDX_HK], buf, 0);
}

static struct kobj_attribute uv_keys_host_key_attr =
	__ATTR(host_key, 0444, uv_keys_host_key, NULL);

static ssize_t uv_keys_backup_host_key(struct kobject *kobj,
				       struct kobj_attribute *attr, char *buf)
{
	struct uv_cb_query_keys uvcb = uv_query_keys();

	return emit_hash(&uvcb.key_hashes[UVC_QUERY_KEYS_IDX_BACK_HK], buf, 0);
}

static struct kobj_attribute uv_keys_backup_host_key_attr =
	__ATTR(backup_host_key, 0444, uv_keys_backup_host_key, NULL);

static ssize_t uv_keys_all(struct kobject *kobj,
			   struct kobj_attribute *attr, char *buf)
{
	struct uv_cb_query_keys uvcb = uv_query_keys();
	ssize_t len = 0;
	int i;

	for (i = 0; i < ARRAY_SIZE(uvcb.key_hashes); i++)
		len += emit_hash(uvcb.key_hashes + i, buf, len);

	return len;
}

static struct kobj_attribute uv_keys_all_attr =
	__ATTR(all, 0444, uv_keys_all, NULL);

static struct attribute_group uv_query_attr_group = {
	.attrs = uv_query_attrs,
};

static struct attribute *uv_keys_attrs[] = {
	&uv_keys_host_key_attr.attr,
	&uv_keys_backup_host_key_attr.attr,
	&uv_keys_all_attr.attr,
	NULL,
};

static struct attribute_group uv_keys_attr_group = {
	.attrs = uv_keys_attrs,
};

static ssize_t uv_is_prot_virt_guest(struct kobject *kobj,
				     struct kobj_attribute *attr, char *buf)
{
@@ -751,6 +817,7 @@ static const struct attribute *uv_prot_virt_attrs[] = {
};

static struct kset *uv_query_kset;
static struct kset *uv_keys_kset;
static struct kobject *uv_kobj;

static int __init uv_sysfs_dir_init(const struct attribute_group *grp,
@@ -789,6 +856,10 @@ static int __init uv_sysfs_init(void)
	if (rc)
		goto out_ind_files;

	/* Get installed key hashes if available, ignore any errors */
	if (test_bit_inv(BIT_UVC_CMD_QUERY_KEYS, uv_info.inst_calls_list))
		uv_sysfs_dir_init(&uv_keys_attr_group, &uv_keys_kset, "keys");

	return 0;

out_ind_files: