1// SPDX-License-Identifier: GPL-2.0 2/* 3 * drivers/hyperhold/hp_device.c 4 * 5 * Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. 6 */ 7 8#define pr_fmt(fmt) "[HYPERHOLD]" fmt 9 10#include <linux/random.h> 11#include <linux/blk-crypto.h> 12 13#include "hp_device.h" 14 15#define HP_CIPHER_MODE BLK_ENCRYPTION_MODE_AES_256_XTS 16#define HP_CIPHER_NAME "xts(aes)" 17#define HP_KEY_SIZE (64) 18#define HP_IV_SIZE (16) 19 20union hp_iv { 21 __le64 index; 22 __le64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; 23}; 24 25void unbind_bdev(struct hp_device *dev) 26{ 27 int ret; 28 29 if (!dev->bdev) 30 goto close; 31 if (!dev->old_block_size) 32 goto put; 33 ret = set_blocksize(dev->bdev, dev->old_block_size); 34 if (ret) 35 pr_err("set old block size %d failed, err = %d!\n", 36 dev->old_block_size, ret); 37 dev->old_block_size = 0; 38put: 39 blkdev_put(dev->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); 40 dev->bdev = NULL; 41close: 42 if (dev->filp) 43 filp_close(dev->filp, NULL); 44 dev->filp = NULL; 45 46 pr_info("hyperhold bdev unbinded.\n"); 47} 48 49bool bind_bdev(struct hp_device *dev, const char *name) 50{ 51 struct inode *inode = NULL; 52 int ret; 53 54 dev->filp = filp_open(name, O_RDWR | O_LARGEFILE, 0); 55 if (IS_ERR(dev->filp)) { 56 pr_err("open file %s failed, err = %ld!\n", name, PTR_ERR(dev->filp)); 57 dev->filp = NULL; 58 goto err; 59 } 60 inode = dev->filp->f_mapping->host; 61 if (!S_ISBLK(inode->i_mode)) { 62 pr_err("%s is not a block device!\n", name); 63 goto err; 64 } 65 dev->bdev = blkdev_get_by_dev(inode->i_rdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL, dev); 66 if (IS_ERR(dev->bdev)) { 67 ret = PTR_ERR(dev->bdev); 68 dev->bdev = NULL; 69 pr_err("get blkdev %s failed, err = %d!\n", name, ret); 70 goto err; 71 } 72 dev->old_block_size = block_size(dev->bdev); 73 ret = set_blocksize(dev->bdev, PAGE_SIZE); 74 if (ret) { 75 pr_err("set %s block size failed, err = %d!\n", name, ret); 76 goto err; 77 } 78 dev->dev_size = (u64)i_size_read(inode); 79 dev->sec_size = SECTOR_SIZE; 80 81 pr_info("hyperhold bind bdev %s of size %llu / %u succ.\n", 82 name, dev->dev_size, dev->sec_size); 83 84 return true; 85err: 86 unbind_bdev(dev); 87 88 return false; 89} 90 91int soft_crypt_page(struct crypto_skcipher *ctfm, struct page *dst_page, 92 struct page *src_page, unsigned int op) 93{ 94 struct skcipher_request *req = NULL; 95 DECLARE_CRYPTO_WAIT(wait); 96 struct scatterlist dst, src; 97 int ret = 0; 98 union hp_iv iv; 99 100 memset(&iv, 0, sizeof(union hp_iv)); 101 iv.index = cpu_to_le64(src_page->index); 102 103 req = skcipher_request_alloc(ctfm, GFP_NOIO); 104 if (!req) { 105 pr_err("alloc skcipher request failed!\n"); 106 return -ENOMEM; 107 } 108 109 skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, 110 crypto_req_done, &wait); 111 sg_init_table(&dst, 1); 112 sg_set_page(&dst, dst_page, PAGE_SIZE, 0); 113 sg_init_table(&src, 1); 114 sg_set_page(&src, src_page, PAGE_SIZE, 0); 115 skcipher_request_set_crypt(req, &src, &dst, PAGE_SIZE, &iv); 116 if (op == HP_DEV_ENCRYPT) 117 ret = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); 118 else if (op == HP_DEV_DECRYPT) 119 ret = crypto_wait_req(crypto_skcipher_decrypt(req), &wait); 120 else 121 BUG(); 122 123 skcipher_request_free(req); 124 125 if (ret) 126 pr_err("%scrypt failed!\n", op == HP_DEV_ENCRYPT ? "en" : "de"); 127 128 return ret; 129} 130 131static struct crypto_skcipher *soft_crypto_init(const u8 *key) 132{ 133 char *cipher = HP_CIPHER_NAME; 134 u32 key_len = HP_KEY_SIZE; 135 struct crypto_skcipher *ctfm = NULL; 136 int ret; 137 138 ctfm = crypto_alloc_skcipher(cipher, 0, 0); 139 if (IS_ERR(ctfm)) { 140 pr_err("alloc ctfm failed, ret = %ld!\n", PTR_ERR(ctfm)); 141 ctfm = NULL; 142 goto err; 143 } 144 crypto_skcipher_clear_flags(ctfm, ~0); 145 crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); 146 ret = crypto_skcipher_setkey(ctfm, key, key_len); 147 if (ret) { 148 pr_err("ctfm setkey failed, ret = %d!\n", ret); 149 goto err; 150 } 151 152 return ctfm; 153err: 154 if (ctfm) 155 crypto_free_skcipher(ctfm); 156 157 return NULL; 158} 159 160#ifdef CONFIG_BLK_INLINE_ENCRYPTION 161void inline_crypt_bio(struct blk_crypto_key *blk_key, struct bio *bio) 162{ 163 union hp_iv iv; 164 165 memset(&iv, 0, sizeof(union hp_iv)); 166 iv.index = cpu_to_le64(bio->bi_iter.bi_sector); 167 168 bio_crypt_set_ctx(bio, blk_key, iv.dun, GFP_NOIO); 169} 170 171static struct blk_crypto_key *inline_crypto_init(const u8 *key) 172{ 173 struct blk_crypto_key *blk_key = NULL; 174 u32 dun_bytes = HP_IV_SIZE - sizeof(__le64); 175 int ret; 176 177 blk_key = kzalloc(sizeof(struct blk_crypto_key), GFP_KERNEL); 178 if (!blk_key) { 179 pr_err("blk key alloc failed!\n"); 180 goto err; 181 } 182 ret = blk_crypto_init_key(blk_key, key, HP_CIPHER_MODE, dun_bytes, PAGE_SIZE); 183 if (ret) { 184 pr_err("blk key init failed, ret = %d!\n", ret); 185 goto err; 186 } 187 188 return blk_key; 189err: 190 if (blk_key) 191 kfree_sensitive(blk_key); 192 193 return NULL; 194} 195#else 196void inline_crypt_bio(struct blk_crypto_key *blk_key, struct bio *bio) {} 197static struct blk_crypto_key *inline_crypto_init(const u8 *key) 198{ 199 pr_err("CONFIG_BLK_INLINE_ENCRYPTION is not enabled!\n"); 200 return NULL; 201} 202#endif 203 204bool crypto_init(struct hp_device *dev, bool soft) 205{ 206 u8 key[HP_KEY_SIZE]; 207 bool ret = false; 208 209 get_random_bytes(key, HP_KEY_SIZE); 210 if (soft) { 211 dev->ctfm = soft_crypto_init(key); 212 ret = dev->ctfm; 213 } else { 214 dev->blk_key = inline_crypto_init(key); 215 ret = dev->blk_key; 216 if (ret) 217 pr_warn("soft crypt has been turned off, now apply hard crypt!\n"); 218 } 219 memzero_explicit(key, HP_KEY_SIZE); 220 221 return ret; 222} 223 224void crypto_deinit(struct hp_device *dev) 225{ 226 if (dev->ctfm) { 227 crypto_free_skcipher(dev->ctfm); 228 dev->ctfm = NULL; 229 } 230 if (dev->blk_key) { 231 kfree_sensitive(dev->blk_key); 232 dev->blk_key = NULL; 233 } 234} 235