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