120f01f16SEric Biggers // SPDX-License-Identifier: GPL-2.0 220f01f16SEric Biggers /* 320f01f16SEric Biggers * Copyright 2021 Google LLC 420f01f16SEric Biggers * 520f01f16SEric Biggers * sysfs support for blk-crypto. This file contains the code which exports the 620f01f16SEric Biggers * crypto capabilities of devices via /sys/block/$disk/queue/crypto/. 720f01f16SEric Biggers */ 820f01f16SEric Biggers 920f01f16SEric Biggers #include <linux/blk-crypto-profile.h> 1020f01f16SEric Biggers 1120f01f16SEric Biggers #include "blk-crypto-internal.h" 1220f01f16SEric Biggers 1320f01f16SEric Biggers struct blk_crypto_kobj { 1420f01f16SEric Biggers struct kobject kobj; 1520f01f16SEric Biggers struct blk_crypto_profile *profile; 1620f01f16SEric Biggers }; 1720f01f16SEric Biggers 1820f01f16SEric Biggers struct blk_crypto_attr { 1920f01f16SEric Biggers struct attribute attr; 2020f01f16SEric Biggers ssize_t (*show)(struct blk_crypto_profile *profile, 2120f01f16SEric Biggers struct blk_crypto_attr *attr, char *page); 2220f01f16SEric Biggers }; 2320f01f16SEric Biggers 2420f01f16SEric Biggers static struct blk_crypto_profile *kobj_to_crypto_profile(struct kobject *kobj) 2520f01f16SEric Biggers { 2620f01f16SEric Biggers return container_of(kobj, struct blk_crypto_kobj, kobj)->profile; 2720f01f16SEric Biggers } 2820f01f16SEric Biggers 2920f01f16SEric Biggers static struct blk_crypto_attr *attr_to_crypto_attr(struct attribute *attr) 3020f01f16SEric Biggers { 3120f01f16SEric Biggers return container_of(attr, struct blk_crypto_attr, attr); 3220f01f16SEric Biggers } 3320f01f16SEric Biggers 3420f01f16SEric Biggers static ssize_t max_dun_bits_show(struct blk_crypto_profile *profile, 3520f01f16SEric Biggers struct blk_crypto_attr *attr, char *page) 3620f01f16SEric Biggers { 3720f01f16SEric Biggers return sysfs_emit(page, "%u\n", 8 * profile->max_dun_bytes_supported); 3820f01f16SEric Biggers } 3920f01f16SEric Biggers 4020f01f16SEric Biggers static ssize_t num_keyslots_show(struct blk_crypto_profile *profile, 4120f01f16SEric Biggers struct blk_crypto_attr *attr, char *page) 4220f01f16SEric Biggers { 4320f01f16SEric Biggers return sysfs_emit(page, "%u\n", profile->num_slots); 4420f01f16SEric Biggers } 4520f01f16SEric Biggers 4620f01f16SEric Biggers #define BLK_CRYPTO_RO_ATTR(_name) \ 4720f01f16SEric Biggers static struct blk_crypto_attr _name##_attr = __ATTR_RO(_name) 4820f01f16SEric Biggers 4920f01f16SEric Biggers BLK_CRYPTO_RO_ATTR(max_dun_bits); 5020f01f16SEric Biggers BLK_CRYPTO_RO_ATTR(num_keyslots); 5120f01f16SEric Biggers 5220f01f16SEric Biggers static struct attribute *blk_crypto_attrs[] = { 5320f01f16SEric Biggers &max_dun_bits_attr.attr, 5420f01f16SEric Biggers &num_keyslots_attr.attr, 5520f01f16SEric Biggers NULL, 5620f01f16SEric Biggers }; 5720f01f16SEric Biggers 5820f01f16SEric Biggers static const struct attribute_group blk_crypto_attr_group = { 5920f01f16SEric Biggers .attrs = blk_crypto_attrs, 6020f01f16SEric Biggers }; 6120f01f16SEric Biggers 6220f01f16SEric Biggers /* 6320f01f16SEric Biggers * The encryption mode attributes. To avoid hard-coding the list of encryption 6420f01f16SEric Biggers * modes, these are initialized at boot time by blk_crypto_sysfs_init(). 6520f01f16SEric Biggers */ 6620f01f16SEric Biggers static struct blk_crypto_attr __blk_crypto_mode_attrs[BLK_ENCRYPTION_MODE_MAX]; 6720f01f16SEric Biggers static struct attribute *blk_crypto_mode_attrs[BLK_ENCRYPTION_MODE_MAX + 1]; 6820f01f16SEric Biggers 6920f01f16SEric Biggers static umode_t blk_crypto_mode_is_visible(struct kobject *kobj, 7020f01f16SEric Biggers struct attribute *attr, int n) 7120f01f16SEric Biggers { 7220f01f16SEric Biggers struct blk_crypto_profile *profile = kobj_to_crypto_profile(kobj); 7320f01f16SEric Biggers struct blk_crypto_attr *a = attr_to_crypto_attr(attr); 7420f01f16SEric Biggers int mode_num = a - __blk_crypto_mode_attrs; 7520f01f16SEric Biggers 7620f01f16SEric Biggers if (profile->modes_supported[mode_num]) 7720f01f16SEric Biggers return 0444; 7820f01f16SEric Biggers return 0; 7920f01f16SEric Biggers } 8020f01f16SEric Biggers 8120f01f16SEric Biggers static ssize_t blk_crypto_mode_show(struct blk_crypto_profile *profile, 8220f01f16SEric Biggers struct blk_crypto_attr *attr, char *page) 8320f01f16SEric Biggers { 8420f01f16SEric Biggers int mode_num = attr - __blk_crypto_mode_attrs; 8520f01f16SEric Biggers 8620f01f16SEric Biggers return sysfs_emit(page, "0x%x\n", profile->modes_supported[mode_num]); 8720f01f16SEric Biggers } 8820f01f16SEric Biggers 8920f01f16SEric Biggers static const struct attribute_group blk_crypto_modes_attr_group = { 9020f01f16SEric Biggers .name = "modes", 9120f01f16SEric Biggers .attrs = blk_crypto_mode_attrs, 9220f01f16SEric Biggers .is_visible = blk_crypto_mode_is_visible, 9320f01f16SEric Biggers }; 9420f01f16SEric Biggers 9520f01f16SEric Biggers static const struct attribute_group *blk_crypto_attr_groups[] = { 9620f01f16SEric Biggers &blk_crypto_attr_group, 9720f01f16SEric Biggers &blk_crypto_modes_attr_group, 9820f01f16SEric Biggers NULL, 9920f01f16SEric Biggers }; 10020f01f16SEric Biggers 10120f01f16SEric Biggers static ssize_t blk_crypto_attr_show(struct kobject *kobj, 10220f01f16SEric Biggers struct attribute *attr, char *page) 10320f01f16SEric Biggers { 10420f01f16SEric Biggers struct blk_crypto_profile *profile = kobj_to_crypto_profile(kobj); 10520f01f16SEric Biggers struct blk_crypto_attr *a = attr_to_crypto_attr(attr); 10620f01f16SEric Biggers 10720f01f16SEric Biggers return a->show(profile, a, page); 10820f01f16SEric Biggers } 10920f01f16SEric Biggers 11020f01f16SEric Biggers static const struct sysfs_ops blk_crypto_attr_ops = { 11120f01f16SEric Biggers .show = blk_crypto_attr_show, 11220f01f16SEric Biggers }; 11320f01f16SEric Biggers 11420f01f16SEric Biggers static void blk_crypto_release(struct kobject *kobj) 11520f01f16SEric Biggers { 11620f01f16SEric Biggers kfree(container_of(kobj, struct blk_crypto_kobj, kobj)); 11720f01f16SEric Biggers } 11820f01f16SEric Biggers 11920f01f16SEric Biggers static struct kobj_type blk_crypto_ktype = { 12020f01f16SEric Biggers .default_groups = blk_crypto_attr_groups, 12120f01f16SEric Biggers .sysfs_ops = &blk_crypto_attr_ops, 12220f01f16SEric Biggers .release = blk_crypto_release, 12320f01f16SEric Biggers }; 12420f01f16SEric Biggers 12520f01f16SEric Biggers /* 12620f01f16SEric Biggers * If the request_queue has a blk_crypto_profile, create the "crypto" 12720f01f16SEric Biggers * subdirectory in sysfs (/sys/block/$disk/queue/crypto/). 12820f01f16SEric Biggers */ 129450deb93SChristoph Hellwig int blk_crypto_sysfs_register(struct gendisk *disk) 13020f01f16SEric Biggers { 131450deb93SChristoph Hellwig struct request_queue *q = disk->queue; 13220f01f16SEric Biggers struct blk_crypto_kobj *obj; 13320f01f16SEric Biggers int err; 13420f01f16SEric Biggers 13520f01f16SEric Biggers if (!q->crypto_profile) 13620f01f16SEric Biggers return 0; 13720f01f16SEric Biggers 13820f01f16SEric Biggers obj = kzalloc(sizeof(*obj), GFP_KERNEL); 13920f01f16SEric Biggers if (!obj) 14020f01f16SEric Biggers return -ENOMEM; 14120f01f16SEric Biggers obj->profile = q->crypto_profile; 14220f01f16SEric Biggers 143*2bd85221SChristoph Hellwig err = kobject_init_and_add(&obj->kobj, &blk_crypto_ktype, 144*2bd85221SChristoph Hellwig &disk->queue_kobj, "crypto"); 14520f01f16SEric Biggers if (err) { 14620f01f16SEric Biggers kobject_put(&obj->kobj); 14720f01f16SEric Biggers return err; 14820f01f16SEric Biggers } 14920f01f16SEric Biggers q->crypto_kobject = &obj->kobj; 15020f01f16SEric Biggers return 0; 15120f01f16SEric Biggers } 15220f01f16SEric Biggers 153450deb93SChristoph Hellwig void blk_crypto_sysfs_unregister(struct gendisk *disk) 15420f01f16SEric Biggers { 155450deb93SChristoph Hellwig kobject_put(disk->queue->crypto_kobject); 15620f01f16SEric Biggers } 15720f01f16SEric Biggers 15820f01f16SEric Biggers static int __init blk_crypto_sysfs_init(void) 15920f01f16SEric Biggers { 16020f01f16SEric Biggers int i; 16120f01f16SEric Biggers 16220f01f16SEric Biggers BUILD_BUG_ON(BLK_ENCRYPTION_MODE_INVALID != 0); 16320f01f16SEric Biggers for (i = 1; i < BLK_ENCRYPTION_MODE_MAX; i++) { 16420f01f16SEric Biggers struct blk_crypto_attr *attr = &__blk_crypto_mode_attrs[i]; 16520f01f16SEric Biggers 16620f01f16SEric Biggers attr->attr.name = blk_crypto_modes[i].name; 16720f01f16SEric Biggers attr->attr.mode = 0444; 16820f01f16SEric Biggers attr->show = blk_crypto_mode_show; 16920f01f16SEric Biggers blk_crypto_mode_attrs[i - 1] = &attr->attr; 17020f01f16SEric Biggers } 17120f01f16SEric Biggers return 0; 17220f01f16SEric Biggers } 17320f01f16SEric Biggers subsys_initcall(blk_crypto_sysfs_init); 174