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