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: Janosch Frank <frankja@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Link: https://lore.kernel.org/r/20241023075529.2561384-1-seiden@linux.ibm.com
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
This commit is contained in:
Steffen Eiden 2024-10-23 09:55:28 +02:00 committed by Heiko Carstens
parent bb4ad73a28
commit 28a51ee8eb
2 changed files with 88 additions and 0 deletions

View File

@ -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;

View File

@ -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: