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