Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/block/blk-crypto-sysfs.c
26242 views
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
13
struct blk_crypto_kobj {
14
struct kobject kobj;
15
struct blk_crypto_profile *profile;
16
};
17
18
struct 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
24
static 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
29
static struct blk_crypto_attr *attr_to_crypto_attr(struct attribute *attr)
30
{
31
return container_of(attr, struct blk_crypto_attr, attr);
32
}
33
34
static 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
41
static 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
47
static 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
53
static 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
63
BLK_CRYPTO_RO_ATTR(hw_wrapped_keys);
64
BLK_CRYPTO_RO_ATTR(max_dun_bits);
65
BLK_CRYPTO_RO_ATTR(num_keyslots);
66
BLK_CRYPTO_RO_ATTR(raw_keys);
67
68
static 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
84
static 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
92
static 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
*/
101
static struct blk_crypto_attr __blk_crypto_mode_attrs[BLK_ENCRYPTION_MODE_MAX];
102
static struct attribute *blk_crypto_mode_attrs[BLK_ENCRYPTION_MODE_MAX + 1];
103
104
static 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
116
static 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
124
static 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
130
static const struct attribute_group *blk_crypto_attr_groups[] = {
131
&blk_crypto_attr_group,
132
&blk_crypto_modes_attr_group,
133
NULL,
134
};
135
136
static 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
145
static const struct sysfs_ops blk_crypto_attr_ops = {
146
.show = blk_crypto_attr_show,
147
};
148
149
static void blk_crypto_release(struct kobject *kobj)
150
{
151
kfree(container_of(kobj, struct blk_crypto_kobj, kobj));
152
}
153
154
static 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
*/
164
int 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
188
void blk_crypto_sysfs_unregister(struct gendisk *disk)
189
{
190
kobject_put(disk->queue->crypto_kobject);
191
}
192
193
static 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
}
208
subsys_initcall(blk_crypto_sysfs_init);
209
210