File Index
Files and directories
Sign in
FILE

blk-crypto-sysfs.c

File preview with syntax highlighting.

linux-6.19.14/block/blk-crypto-sysfs.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright 2021 Google LLC
  4 *
  5 * sysfs support for blk-crypto.  This file contains the code which exports the
  6 * crypto capabilities of devices via /sys/block/$disk/queue/crypto/.
  7 */
  8
  9#include <linux/blk-crypto-profile.h>
 10
 11#include "blk-crypto-internal.h"
 12
 13struct blk_crypto_kobj {
 14	struct kobject kobj;
 15	struct blk_crypto_profile *profile;
 16};
 17
 18struct blk_crypto_attr {
 19	struct attribute attr;
 20	ssize_t (*show)(struct blk_crypto_profile *profile,
 21			struct blk_crypto_attr *attr, char *page);
 22};
 23
 24static struct blk_crypto_profile *kobj_to_crypto_profile(struct kobject *kobj)
 25{
 26	return container_of(kobj, struct blk_crypto_kobj, kobj)->profile;
 27}
 28
 29static struct blk_crypto_attr *attr_to_crypto_attr(struct attribute *attr)
 30{
 31	return container_of(attr, struct blk_crypto_attr, attr);
 32}
 33
 34static ssize_t hw_wrapped_keys_show(struct blk_crypto_profile *profile,
 35				    struct blk_crypto_attr *attr, char *page)
 36{
 37	/* Always show supported, since the file doesn't exist otherwise. */
 38	return sysfs_emit(page, "supported\n");
 39}
 40
 41static ssize_t max_dun_bits_show(struct blk_crypto_profile *profile,
 42				 struct blk_crypto_attr *attr, char *page)
 43{
 44	return sysfs_emit(page, "%u\n", 8 * profile->max_dun_bytes_supported);
 45}
 46
 47static ssize_t num_keyslots_show(struct blk_crypto_profile *profile,
 48				 struct blk_crypto_attr *attr, char *page)
 49{
 50	return sysfs_emit(page, "%u\n", profile->num_slots);
 51}
 52
 53static ssize_t raw_keys_show(struct blk_crypto_profile *profile,
 54			     struct blk_crypto_attr *attr, char *page)
 55{
 56	/* Always show supported, since the file doesn't exist otherwise. */
 57	return sysfs_emit(page, "supported\n");
 58}
 59
 60#define BLK_CRYPTO_RO_ATTR(_name) \
 61	static struct blk_crypto_attr _name##_attr = __ATTR_RO(_name)
 62
 63BLK_CRYPTO_RO_ATTR(hw_wrapped_keys);
 64BLK_CRYPTO_RO_ATTR(max_dun_bits);
 65BLK_CRYPTO_RO_ATTR(num_keyslots);
 66BLK_CRYPTO_RO_ATTR(raw_keys);
 67
 68static umode_t blk_crypto_is_visible(struct kobject *kobj,
 69				     struct attribute *attr, int n)
 70{
 71	struct blk_crypto_profile *profile = kobj_to_crypto_profile(kobj);
 72	struct blk_crypto_attr *a = attr_to_crypto_attr(attr);
 73
 74	if (a == &hw_wrapped_keys_attr &&
 75	    !(profile->key_types_supported & BLK_CRYPTO_KEY_TYPE_HW_WRAPPED))
 76		return 0;
 77	if (a == &raw_keys_attr &&
 78	    !(profile->key_types_supported & BLK_CRYPTO_KEY_TYPE_RAW))
 79		return 0;
 80
 81	return 0444;
 82}
 83
 84static struct attribute *blk_crypto_attrs[] = {
 85	&hw_wrapped_keys_attr.attr,
 86	&max_dun_bits_attr.attr,
 87	&num_keyslots_attr.attr,
 88	&raw_keys_attr.attr,
 89	NULL,
 90};
 91
 92static const struct attribute_group blk_crypto_attr_group = {
 93	.attrs = blk_crypto_attrs,
 94	.is_visible = blk_crypto_is_visible,
 95};
 96
 97/*
 98 * The encryption mode attributes.  To avoid hard-coding the list of encryption
 99 * modes, these are initialized at boot time by blk_crypto_sysfs_init().
100 */
101static struct blk_crypto_attr __blk_crypto_mode_attrs[BLK_ENCRYPTION_MODE_MAX];
102static struct attribute *blk_crypto_mode_attrs[BLK_ENCRYPTION_MODE_MAX + 1];
103
104static umode_t blk_crypto_mode_is_visible(struct kobject *kobj,
105					  struct attribute *attr, int n)
106{
107	struct blk_crypto_profile *profile = kobj_to_crypto_profile(kobj);
108	struct blk_crypto_attr *a = attr_to_crypto_attr(attr);
109	int mode_num = a - __blk_crypto_mode_attrs;
110
111	if (profile->modes_supported[mode_num])
112		return 0444;
113	return 0;
114}
115
116static ssize_t blk_crypto_mode_show(struct blk_crypto_profile *profile,
117				    struct blk_crypto_attr *attr, char *page)
118{
119	int mode_num = attr - __blk_crypto_mode_attrs;
120
121	return sysfs_emit(page, "0x%x\n", profile->modes_supported[mode_num]);
122}
123
124static const struct attribute_group blk_crypto_modes_attr_group = {
125	.name = "modes",
126	.attrs = blk_crypto_mode_attrs,
127	.is_visible = blk_crypto_mode_is_visible,
128};
129
130static const struct attribute_group *blk_crypto_attr_groups[] = {
131	&blk_crypto_attr_group,
132	&blk_crypto_modes_attr_group,
133	NULL,
134};
135
136static ssize_t blk_crypto_attr_show(struct kobject *kobj,
137				    struct attribute *attr, char *page)
138{
139	struct blk_crypto_profile *profile = kobj_to_crypto_profile(kobj);
140	struct blk_crypto_attr *a = attr_to_crypto_attr(attr);
141
142	return a->show(profile, a, page);
143}
144
145static const struct sysfs_ops blk_crypto_attr_ops = {
146	.show = blk_crypto_attr_show,
147};
148
149static void blk_crypto_release(struct kobject *kobj)
150{
151	kfree(container_of(kobj, struct blk_crypto_kobj, kobj));
152}
153
154static const struct kobj_type blk_crypto_ktype = {
155	.default_groups = blk_crypto_attr_groups,
156	.sysfs_ops	= &blk_crypto_attr_ops,
157	.release	= blk_crypto_release,
158};
159
160/*
161 * If the request_queue has a blk_crypto_profile, create the "crypto"
162 * subdirectory in sysfs (/sys/block/$disk/queue/crypto/).
163 */
164int blk_crypto_sysfs_register(struct gendisk *disk)
165{
166	struct request_queue *q = disk->queue;
167	struct blk_crypto_kobj *obj;
168	int err;
169
170	if (!q->crypto_profile)
171		return 0;
172
173	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
174	if (!obj)
175		return -ENOMEM;
176	obj->profile = q->crypto_profile;
177
178	err = kobject_init_and_add(&obj->kobj, &blk_crypto_ktype,
179				   &disk->queue_kobj, "crypto");
180	if (err) {
181		kobject_put(&obj->kobj);
182		return err;
183	}
184	q->crypto_kobject = &obj->kobj;
185	return 0;
186}
187
188void blk_crypto_sysfs_unregister(struct gendisk *disk)
189{
190	kobject_put(disk->queue->crypto_kobject);
191}
192
193static int __init blk_crypto_sysfs_init(void)
194{
195	int i;
196
197	BUILD_BUG_ON(BLK_ENCRYPTION_MODE_INVALID != 0);
198	for (i = 1; i < BLK_ENCRYPTION_MODE_MAX; i++) {
199		struct blk_crypto_attr *attr = &__blk_crypto_mode_attrs[i];
200
201		attr->attr.name = blk_crypto_modes[i].name;
202		attr->attr.mode = 0444;
203		attr->show = blk_crypto_mode_show;
204		blk_crypto_mode_attrs[i - 1] = &attr->attr;
205	}
206	return 0;
207}
208subsys_initcall(blk_crypto_sysfs_init);
~/ Read-only file preview.