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