xref: /linux/drivers/md/dm-inlinecrypt.c (revision e7f57d2c47e265ef64e1dab84fc8f70dae2dd150)
1*e7f57d2cSEric Biggers // SPDX-License-Identifier: GPL-2.0-only
2*e7f57d2cSEric Biggers /*
3*e7f57d2cSEric Biggers  * Copyright 2024 Google LLC
4*e7f57d2cSEric Biggers  */
5*e7f57d2cSEric Biggers 
6*e7f57d2cSEric Biggers #include <linux/blk-crypto.h>
7*e7f57d2cSEric Biggers #include <linux/ctype.h>
8*e7f57d2cSEric Biggers #include <linux/device-mapper.h>
9*e7f57d2cSEric Biggers #include <linux/hex.h>
10*e7f57d2cSEric Biggers #include <linux/module.h>
11*e7f57d2cSEric Biggers #include <keys/user-type.h>
12*e7f57d2cSEric Biggers 
13*e7f57d2cSEric Biggers #define DM_MSG_PREFIX	"inlinecrypt"
14*e7f57d2cSEric Biggers 
15*e7f57d2cSEric Biggers static const struct dm_inlinecrypt_cipher {
16*e7f57d2cSEric Biggers 	const char *name;
17*e7f57d2cSEric Biggers 	enum blk_crypto_mode_num mode_num;
18*e7f57d2cSEric Biggers } dm_inlinecrypt_ciphers[] = {
19*e7f57d2cSEric Biggers 	{
20*e7f57d2cSEric Biggers 		.name = "aes-xts-plain64",
21*e7f57d2cSEric Biggers 		.mode_num = BLK_ENCRYPTION_MODE_AES_256_XTS,
22*e7f57d2cSEric Biggers 	},
23*e7f57d2cSEric Biggers };
24*e7f57d2cSEric Biggers 
25*e7f57d2cSEric Biggers /**
26*e7f57d2cSEric Biggers  * struct inlinecrypt_ctx - private data of an inlinecrypt target
27*e7f57d2cSEric Biggers  * @dev: the underlying device
28*e7f57d2cSEric Biggers  * @start: starting sector of the range of @dev which this target actually maps.
29*e7f57d2cSEric Biggers  *	   For this purpose a "sector" is 512 bytes.
30*e7f57d2cSEric Biggers  * @cipher_string: the name of the encryption algorithm being used
31*e7f57d2cSEric Biggers  * @key_size: size of the encryption key in bytes
32*e7f57d2cSEric Biggers  * @iv_offset: starting offset for IVs.  IVs are generated as if the target were
33*e7f57d2cSEric Biggers  *	       preceded by @iv_offset 512-byte sectors.
34*e7f57d2cSEric Biggers  * @sector_size: crypto sector size in bytes (usually 4096)
35*e7f57d2cSEric Biggers  * @sector_bits: log2(sector_size)
36*e7f57d2cSEric Biggers  * @key: the encryption key to use
37*e7f57d2cSEric Biggers  * @max_dun: the maximum DUN that may be used (computed from other params)
38*e7f57d2cSEric Biggers  */
39*e7f57d2cSEric Biggers struct inlinecrypt_ctx {
40*e7f57d2cSEric Biggers 	struct dm_dev *dev;
41*e7f57d2cSEric Biggers 	sector_t start;
42*e7f57d2cSEric Biggers 	const char *cipher_string;
43*e7f57d2cSEric Biggers 	unsigned int key_size;
44*e7f57d2cSEric Biggers 	u64 iv_offset;
45*e7f57d2cSEric Biggers 	unsigned int sector_size;
46*e7f57d2cSEric Biggers 	unsigned int sector_bits;
47*e7f57d2cSEric Biggers 	struct blk_crypto_key key;
48*e7f57d2cSEric Biggers 	u64 max_dun;
49*e7f57d2cSEric Biggers };
50*e7f57d2cSEric Biggers 
51*e7f57d2cSEric Biggers static const struct dm_inlinecrypt_cipher *
52*e7f57d2cSEric Biggers lookup_cipher(const char *cipher_string)
53*e7f57d2cSEric Biggers {
54*e7f57d2cSEric Biggers 	int i;
55*e7f57d2cSEric Biggers 
56*e7f57d2cSEric Biggers 	for (i = 0; i < ARRAY_SIZE(dm_inlinecrypt_ciphers); i++) {
57*e7f57d2cSEric Biggers 		if (strcmp(cipher_string, dm_inlinecrypt_ciphers[i].name) == 0)
58*e7f57d2cSEric Biggers 			return &dm_inlinecrypt_ciphers[i];
59*e7f57d2cSEric Biggers 	}
60*e7f57d2cSEric Biggers 	return NULL;
61*e7f57d2cSEric Biggers }
62*e7f57d2cSEric Biggers 
63*e7f57d2cSEric Biggers static void inlinecrypt_dtr(struct dm_target *ti)
64*e7f57d2cSEric Biggers {
65*e7f57d2cSEric Biggers 	struct inlinecrypt_ctx *ctx = ti->private;
66*e7f57d2cSEric Biggers 
67*e7f57d2cSEric Biggers 	if (ctx->dev) {
68*e7f57d2cSEric Biggers 		if (ctx->key.size)
69*e7f57d2cSEric Biggers 			blk_crypto_evict_key(ctx->dev->bdev, &ctx->key);
70*e7f57d2cSEric Biggers 		dm_put_device(ti, ctx->dev);
71*e7f57d2cSEric Biggers 	}
72*e7f57d2cSEric Biggers 	kfree_sensitive(ctx->cipher_string);
73*e7f57d2cSEric Biggers 	kfree_sensitive(ctx);
74*e7f57d2cSEric Biggers }
75*e7f57d2cSEric Biggers 
76*e7f57d2cSEric Biggers #ifdef CONFIG_KEYS
77*e7f57d2cSEric Biggers 
78*e7f57d2cSEric Biggers static bool contains_whitespace(const char *str)
79*e7f57d2cSEric Biggers {
80*e7f57d2cSEric Biggers 	while (*str)
81*e7f57d2cSEric Biggers 		if (isspace(*str++))
82*e7f57d2cSEric Biggers 			return true;
83*e7f57d2cSEric Biggers 	return false;
84*e7f57d2cSEric Biggers }
85*e7f57d2cSEric Biggers 
86*e7f57d2cSEric Biggers static int set_key_user(struct key *key, char *bin_key,
87*e7f57d2cSEric Biggers 			const unsigned int bin_key_size)
88*e7f57d2cSEric Biggers {
89*e7f57d2cSEric Biggers 	const struct user_key_payload *ukp;
90*e7f57d2cSEric Biggers 
91*e7f57d2cSEric Biggers 	ukp = user_key_payload_locked(key);
92*e7f57d2cSEric Biggers 	if (!ukp)
93*e7f57d2cSEric Biggers 		return -EKEYREVOKED;
94*e7f57d2cSEric Biggers 
95*e7f57d2cSEric Biggers 	if (bin_key_size != ukp->datalen)
96*e7f57d2cSEric Biggers 		return -EINVAL;
97*e7f57d2cSEric Biggers 
98*e7f57d2cSEric Biggers 	memcpy(bin_key, ukp->data, bin_key_size);
99*e7f57d2cSEric Biggers 
100*e7f57d2cSEric Biggers 	return 0;
101*e7f57d2cSEric Biggers }
102*e7f57d2cSEric Biggers 
103*e7f57d2cSEric Biggers static int inlinecrypt_get_keyring_key(const char *key_string, u8 *bin_key,
104*e7f57d2cSEric Biggers 					const unsigned int bin_key_size)
105*e7f57d2cSEric Biggers {
106*e7f57d2cSEric Biggers 	char *key_desc;
107*e7f57d2cSEric Biggers 	int ret;
108*e7f57d2cSEric Biggers 	struct key_type *type;
109*e7f57d2cSEric Biggers 	struct key *key;
110*e7f57d2cSEric Biggers 	int (*set_key)(struct key *key, char *bin_key,
111*e7f57d2cSEric Biggers 				   const unsigned int bin_key_size);
112*e7f57d2cSEric Biggers 
113*e7f57d2cSEric Biggers 	/*
114*e7f57d2cSEric Biggers 	 * Reject key_string with whitespace. dm core currently lacks code for
115*e7f57d2cSEric Biggers 	 * proper whitespace escaping in arguments on DM_TABLE_STATUS path.
116*e7f57d2cSEric Biggers 	 */
117*e7f57d2cSEric Biggers 	if (contains_whitespace(key_string)) {
118*e7f57d2cSEric Biggers 		DMERR("whitespace chars not allowed in key string");
119*e7f57d2cSEric Biggers 		return -EINVAL;
120*e7f57d2cSEric Biggers 	}
121*e7f57d2cSEric Biggers 
122*e7f57d2cSEric Biggers 	/* look for next ':' separating key_type from key_description */
123*e7f57d2cSEric Biggers 	key_desc = strchr(key_string, ':');
124*e7f57d2cSEric Biggers 	if (!key_desc || key_desc == key_string || !strlen(key_desc + 1))
125*e7f57d2cSEric Biggers 		return -EINVAL;
126*e7f57d2cSEric Biggers 
127*e7f57d2cSEric Biggers 	if (!strncmp(key_string, "logon:", key_desc - key_string + 1)) {
128*e7f57d2cSEric Biggers 		type = &key_type_logon;
129*e7f57d2cSEric Biggers 		set_key = set_key_user;
130*e7f57d2cSEric Biggers 	} else {
131*e7f57d2cSEric Biggers 		return -EINVAL;
132*e7f57d2cSEric Biggers 	}
133*e7f57d2cSEric Biggers 
134*e7f57d2cSEric Biggers 	key = request_key(type, key_desc + 1, NULL);
135*e7f57d2cSEric Biggers 	if (IS_ERR(key))
136*e7f57d2cSEric Biggers 		return PTR_ERR(key);
137*e7f57d2cSEric Biggers 
138*e7f57d2cSEric Biggers 	down_read(&key->sem);
139*e7f57d2cSEric Biggers 
140*e7f57d2cSEric Biggers 	ret = set_key(key, (char *)bin_key, bin_key_size);
141*e7f57d2cSEric Biggers 
142*e7f57d2cSEric Biggers 	up_read(&key->sem);
143*e7f57d2cSEric Biggers 	key_put(key);
144*e7f57d2cSEric Biggers 
145*e7f57d2cSEric Biggers 	return ret;
146*e7f57d2cSEric Biggers }
147*e7f57d2cSEric Biggers 
148*e7f57d2cSEric Biggers static int get_key_size(char **key_string)
149*e7f57d2cSEric Biggers {
150*e7f57d2cSEric Biggers 	char *colon, dummy;
151*e7f57d2cSEric Biggers 	int ret;
152*e7f57d2cSEric Biggers 
153*e7f57d2cSEric Biggers 	if (*key_string[0] != ':') {
154*e7f57d2cSEric Biggers 		ret = strlen(*key_string);
155*e7f57d2cSEric Biggers 
156*e7f57d2cSEric Biggers 		if (ret > 2 * BLK_CRYPTO_MAX_ANY_KEY_SIZE
157*e7f57d2cSEric Biggers 			|| ret  % 2
158*e7f57d2cSEric Biggers 			|| !ret) {
159*e7f57d2cSEric Biggers 			DMERR("Invalid keysize");
160*e7f57d2cSEric Biggers 			return -EINVAL;
161*e7f57d2cSEric Biggers 		}
162*e7f57d2cSEric Biggers 		return ret >> 1;
163*e7f57d2cSEric Biggers 	}
164*e7f57d2cSEric Biggers 
165*e7f57d2cSEric Biggers 	/* look for next ':' in key string */
166*e7f57d2cSEric Biggers 	colon = strpbrk(*key_string + 1, ":");
167*e7f57d2cSEric Biggers 	if (!colon)
168*e7f57d2cSEric Biggers 		return -EINVAL;
169*e7f57d2cSEric Biggers 
170*e7f57d2cSEric Biggers 	if (sscanf(*key_string + 1, "%u%c", &ret, &dummy) != 2 || dummy != ':')
171*e7f57d2cSEric Biggers 		return -EINVAL;
172*e7f57d2cSEric Biggers 
173*e7f57d2cSEric Biggers 	/* remaining key string should be :<logon|user>:<key_desc> */
174*e7f57d2cSEric Biggers 	*key_string = colon;
175*e7f57d2cSEric Biggers 
176*e7f57d2cSEric Biggers 	return ret;
177*e7f57d2cSEric Biggers }
178*e7f57d2cSEric Biggers 
179*e7f57d2cSEric Biggers #else
180*e7f57d2cSEric Biggers 
181*e7f57d2cSEric Biggers static int inlinecrypt_get_keyring_key(const char *key_string, u8 *bin_key,
182*e7f57d2cSEric Biggers 					const unsigned int bin_key_size)
183*e7f57d2cSEric Biggers {
184*e7f57d2cSEric Biggers 	return -EINVAL;
185*e7f57d2cSEric Biggers }
186*e7f57d2cSEric Biggers 
187*e7f57d2cSEric Biggers static int get_key_size(char **key_string)
188*e7f57d2cSEric Biggers {
189*e7f57d2cSEric Biggers 	int key_hex_size = strlen(*key_string);
190*e7f57d2cSEric Biggers 
191*e7f57d2cSEric Biggers 	if (*key_string[0] == ':')
192*e7f57d2cSEric Biggers 		return -EINVAL;
193*e7f57d2cSEric Biggers 
194*e7f57d2cSEric Biggers 	if (key_hex_size > 2 * BLK_CRYPTO_MAX_ANY_KEY_SIZE
195*e7f57d2cSEric Biggers 		|| key_hex_size  % 2
196*e7f57d2cSEric Biggers 		|| !key_hex_size) {
197*e7f57d2cSEric Biggers 		DMERR("Invalid keysize");
198*e7f57d2cSEric Biggers 		return -EINVAL;
199*e7f57d2cSEric Biggers 	}
200*e7f57d2cSEric Biggers 
201*e7f57d2cSEric Biggers 	return key_hex_size >> 1;
202*e7f57d2cSEric Biggers }
203*e7f57d2cSEric Biggers 
204*e7f57d2cSEric Biggers #endif /* CONFIG_KEYS */
205*e7f57d2cSEric Biggers 
206*e7f57d2cSEric Biggers static int inlinecrypt_get_key(const char *key_string,
207*e7f57d2cSEric Biggers 				u8 key[BLK_CRYPTO_MAX_ANY_KEY_SIZE],
208*e7f57d2cSEric Biggers 				const unsigned int key_size)
209*e7f57d2cSEric Biggers {
210*e7f57d2cSEric Biggers 	int ret = 0;
211*e7f57d2cSEric Biggers 
212*e7f57d2cSEric Biggers 	if (key_size > BLK_CRYPTO_MAX_ANY_KEY_SIZE) {
213*e7f57d2cSEric Biggers 		DMERR("Invalid keysize");
214*e7f57d2cSEric Biggers 		return -EINVAL;
215*e7f57d2cSEric Biggers 	}
216*e7f57d2cSEric Biggers 
217*e7f57d2cSEric Biggers 	/* ':' means the key is in kernel keyring, short-circuit normal key processing */
218*e7f57d2cSEric Biggers 	if (key_string[0] == ':') {
219*e7f57d2cSEric Biggers 		/* key string should be :<logon|user>:<key_desc> */
220*e7f57d2cSEric Biggers 		ret = inlinecrypt_get_keyring_key(key_string + 1, key, key_size);
221*e7f57d2cSEric Biggers 		goto out;
222*e7f57d2cSEric Biggers 	}
223*e7f57d2cSEric Biggers 
224*e7f57d2cSEric Biggers 	if (hex2bin(key, key_string, key_size) != 0)
225*e7f57d2cSEric Biggers 		ret = -EINVAL;
226*e7f57d2cSEric Biggers 
227*e7f57d2cSEric Biggers out:
228*e7f57d2cSEric Biggers 	return ret;
229*e7f57d2cSEric Biggers }
230*e7f57d2cSEric Biggers 
231*e7f57d2cSEric Biggers static int inlinecrypt_ctr_optional(struct dm_target *ti,
232*e7f57d2cSEric Biggers 				    unsigned int argc, char **argv)
233*e7f57d2cSEric Biggers {
234*e7f57d2cSEric Biggers 	struct inlinecrypt_ctx *ctx = ti->private;
235*e7f57d2cSEric Biggers 	struct dm_arg_set as;
236*e7f57d2cSEric Biggers 	static const struct dm_arg _args[] = {
237*e7f57d2cSEric Biggers 		{0, 3, "Invalid number of feature args"},
238*e7f57d2cSEric Biggers 	};
239*e7f57d2cSEric Biggers 	unsigned int opt_params;
240*e7f57d2cSEric Biggers 	const char *opt_string;
241*e7f57d2cSEric Biggers 	bool iv_large_sectors = false;
242*e7f57d2cSEric Biggers 	char dummy;
243*e7f57d2cSEric Biggers 	int err;
244*e7f57d2cSEric Biggers 
245*e7f57d2cSEric Biggers 	as.argc = argc;
246*e7f57d2cSEric Biggers 	as.argv = argv;
247*e7f57d2cSEric Biggers 
248*e7f57d2cSEric Biggers 	err = dm_read_arg_group(_args, &as, &opt_params, &ti->error);
249*e7f57d2cSEric Biggers 	if (err)
250*e7f57d2cSEric Biggers 		return err;
251*e7f57d2cSEric Biggers 
252*e7f57d2cSEric Biggers 	while (opt_params--) {
253*e7f57d2cSEric Biggers 		opt_string = dm_shift_arg(&as);
254*e7f57d2cSEric Biggers 		if (!opt_string) {
255*e7f57d2cSEric Biggers 			ti->error = "Not enough feature arguments";
256*e7f57d2cSEric Biggers 			return -EINVAL;
257*e7f57d2cSEric Biggers 		}
258*e7f57d2cSEric Biggers 		if (!strcmp(opt_string, "allow_discards")) {
259*e7f57d2cSEric Biggers 			ti->num_discard_bios = 1;
260*e7f57d2cSEric Biggers 		} else if (sscanf(opt_string, "sector_size:%u%c",
261*e7f57d2cSEric Biggers 				  &ctx->sector_size, &dummy) == 1) {
262*e7f57d2cSEric Biggers 			if (ctx->sector_size < SECTOR_SIZE ||
263*e7f57d2cSEric Biggers 			    ctx->sector_size > 4096 ||
264*e7f57d2cSEric Biggers 			    !is_power_of_2(ctx->sector_size)) {
265*e7f57d2cSEric Biggers 				ti->error = "Invalid sector_size";
266*e7f57d2cSEric Biggers 				return -EINVAL;
267*e7f57d2cSEric Biggers 			}
268*e7f57d2cSEric Biggers 		} else if (!strcmp(opt_string, "iv_large_sectors")) {
269*e7f57d2cSEric Biggers 			iv_large_sectors = true;
270*e7f57d2cSEric Biggers 		} else {
271*e7f57d2cSEric Biggers 			ti->error = "Invalid feature arguments";
272*e7f57d2cSEric Biggers 			return -EINVAL;
273*e7f57d2cSEric Biggers 		}
274*e7f57d2cSEric Biggers 	}
275*e7f57d2cSEric Biggers 
276*e7f57d2cSEric Biggers 	/* dm-inlinecrypt doesn't implement iv_large_sectors=false. */
277*e7f57d2cSEric Biggers 	if (ctx->sector_size != SECTOR_SIZE && !iv_large_sectors) {
278*e7f57d2cSEric Biggers 		ti->error = "iv_large_sectors must be specified";
279*e7f57d2cSEric Biggers 		return -EINVAL;
280*e7f57d2cSEric Biggers 	}
281*e7f57d2cSEric Biggers 
282*e7f57d2cSEric Biggers 	return 0;
283*e7f57d2cSEric Biggers }
284*e7f57d2cSEric Biggers 
285*e7f57d2cSEric Biggers /*
286*e7f57d2cSEric Biggers  * Construct an inlinecrypt mapping:
287*e7f57d2cSEric Biggers  * <cipher> [<key>|:<key_size>:<logon>:<key_description>] <iv_offset> <dev_path> <start>
288*e7f57d2cSEric Biggers  *
289*e7f57d2cSEric Biggers  * This syntax matches dm-crypt's, but the set of supported functionality has
290*e7f57d2cSEric Biggers  * been stripped down.
291*e7f57d2cSEric Biggers  */
292*e7f57d2cSEric Biggers static int inlinecrypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
293*e7f57d2cSEric Biggers {
294*e7f57d2cSEric Biggers 	struct inlinecrypt_ctx *ctx;
295*e7f57d2cSEric Biggers 	const struct dm_inlinecrypt_cipher *cipher;
296*e7f57d2cSEric Biggers 	u8 raw_key[BLK_CRYPTO_MAX_ANY_KEY_SIZE];
297*e7f57d2cSEric Biggers 	unsigned int dun_bytes;
298*e7f57d2cSEric Biggers 	unsigned long long tmpll;
299*e7f57d2cSEric Biggers 	char dummy;
300*e7f57d2cSEric Biggers 	int err;
301*e7f57d2cSEric Biggers 
302*e7f57d2cSEric Biggers 	if (argc < 5) {
303*e7f57d2cSEric Biggers 		ti->error = "Not enough arguments";
304*e7f57d2cSEric Biggers 		return -EINVAL;
305*e7f57d2cSEric Biggers 	}
306*e7f57d2cSEric Biggers 
307*e7f57d2cSEric Biggers 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
308*e7f57d2cSEric Biggers 	if (!ctx) {
309*e7f57d2cSEric Biggers 		ti->error = "Out of memory";
310*e7f57d2cSEric Biggers 		return -ENOMEM;
311*e7f57d2cSEric Biggers 	}
312*e7f57d2cSEric Biggers 	ti->private = ctx;
313*e7f57d2cSEric Biggers 
314*e7f57d2cSEric Biggers 	/* <cipher> */
315*e7f57d2cSEric Biggers 	ctx->cipher_string = kstrdup(argv[0], GFP_KERNEL);
316*e7f57d2cSEric Biggers 	if (!ctx->cipher_string) {
317*e7f57d2cSEric Biggers 		ti->error = "Out of memory";
318*e7f57d2cSEric Biggers 		err = -ENOMEM;
319*e7f57d2cSEric Biggers 		goto bad;
320*e7f57d2cSEric Biggers 	}
321*e7f57d2cSEric Biggers 	cipher = lookup_cipher(ctx->cipher_string);
322*e7f57d2cSEric Biggers 	if (!cipher) {
323*e7f57d2cSEric Biggers 		ti->error = "Unsupported cipher";
324*e7f57d2cSEric Biggers 		err = -EINVAL;
325*e7f57d2cSEric Biggers 		goto bad;
326*e7f57d2cSEric Biggers 	}
327*e7f57d2cSEric Biggers 
328*e7f57d2cSEric Biggers 	/* <key> */
329*e7f57d2cSEric Biggers 	err = get_key_size(&argv[1]);
330*e7f57d2cSEric Biggers 	if (err < 0) {
331*e7f57d2cSEric Biggers 		ti->error = "Cannot parse key size";
332*e7f57d2cSEric Biggers 		return -EINVAL;
333*e7f57d2cSEric Biggers 	}
334*e7f57d2cSEric Biggers 	ctx->key_size = err;
335*e7f57d2cSEric Biggers 
336*e7f57d2cSEric Biggers 	err = inlinecrypt_get_key(argv[1], raw_key, ctx->key_size);
337*e7f57d2cSEric Biggers 	if (err) {
338*e7f57d2cSEric Biggers 		ti->error = "Malformed key string";
339*e7f57d2cSEric Biggers 		goto bad;
340*e7f57d2cSEric Biggers 	}
341*e7f57d2cSEric Biggers 
342*e7f57d2cSEric Biggers 	/* <iv_offset> */
343*e7f57d2cSEric Biggers 	if (sscanf(argv[2], "%llu%c", &ctx->iv_offset, &dummy) != 1) {
344*e7f57d2cSEric Biggers 		ti->error = "Invalid iv_offset sector";
345*e7f57d2cSEric Biggers 		err = -EINVAL;
346*e7f57d2cSEric Biggers 		goto bad;
347*e7f57d2cSEric Biggers 	}
348*e7f57d2cSEric Biggers 
349*e7f57d2cSEric Biggers 	/* <dev_path> */
350*e7f57d2cSEric Biggers 	err = dm_get_device(ti, argv[3], dm_table_get_mode(ti->table),
351*e7f57d2cSEric Biggers 			    &ctx->dev);
352*e7f57d2cSEric Biggers 	if (err) {
353*e7f57d2cSEric Biggers 		ti->error = "Device lookup failed";
354*e7f57d2cSEric Biggers 		goto bad;
355*e7f57d2cSEric Biggers 	}
356*e7f57d2cSEric Biggers 
357*e7f57d2cSEric Biggers 	/* <start> */
358*e7f57d2cSEric Biggers 	if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1 ||
359*e7f57d2cSEric Biggers 	    tmpll != (sector_t)tmpll) {
360*e7f57d2cSEric Biggers 		ti->error = "Invalid start sector";
361*e7f57d2cSEric Biggers 		err = -EINVAL;
362*e7f57d2cSEric Biggers 		goto bad;
363*e7f57d2cSEric Biggers 	}
364*e7f57d2cSEric Biggers 	ctx->start = tmpll;
365*e7f57d2cSEric Biggers 
366*e7f57d2cSEric Biggers 	/* optional arguments */
367*e7f57d2cSEric Biggers 	ctx->sector_size = SECTOR_SIZE;
368*e7f57d2cSEric Biggers 	if (argc > 5) {
369*e7f57d2cSEric Biggers 		err = inlinecrypt_ctr_optional(ti, argc - 5, &argv[5]);
370*e7f57d2cSEric Biggers 		if (err)
371*e7f57d2cSEric Biggers 			goto bad;
372*e7f57d2cSEric Biggers 	}
373*e7f57d2cSEric Biggers 	ctx->sector_bits = ilog2(ctx->sector_size);
374*e7f57d2cSEric Biggers 	if (ti->len & ((ctx->sector_size >> SECTOR_SHIFT) - 1)) {
375*e7f57d2cSEric Biggers 		ti->error = "Device size is not a multiple of sector_size";
376*e7f57d2cSEric Biggers 		err = -EINVAL;
377*e7f57d2cSEric Biggers 		goto bad;
378*e7f57d2cSEric Biggers 	}
379*e7f57d2cSEric Biggers 	if (ctx->iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1)) {
380*e7f57d2cSEric Biggers 		ti->error = "Wrong alignment of iv_offset sector";
381*e7f57d2cSEric Biggers 		err = -EINVAL;
382*e7f57d2cSEric Biggers 	}
383*e7f57d2cSEric Biggers 
384*e7f57d2cSEric Biggers 	ctx->max_dun = (ctx->iv_offset + ti->len - 1) >>
385*e7f57d2cSEric Biggers 		       (ctx->sector_bits - SECTOR_SHIFT);
386*e7f57d2cSEric Biggers 	dun_bytes = DIV_ROUND_UP(fls64(ctx->max_dun), 8);
387*e7f57d2cSEric Biggers 
388*e7f57d2cSEric Biggers 	err = blk_crypto_init_key(&ctx->key, raw_key, ctx->key_size,
389*e7f57d2cSEric Biggers 				  BLK_CRYPTO_KEY_TYPE_RAW,
390*e7f57d2cSEric Biggers 				  cipher->mode_num, dun_bytes,
391*e7f57d2cSEric Biggers 				  ctx->sector_size);
392*e7f57d2cSEric Biggers 	if (err) {
393*e7f57d2cSEric Biggers 		ti->error = "Error initializing blk-crypto key";
394*e7f57d2cSEric Biggers 		goto bad;
395*e7f57d2cSEric Biggers 	}
396*e7f57d2cSEric Biggers 
397*e7f57d2cSEric Biggers 	err = blk_crypto_start_using_key(ctx->dev->bdev, &ctx->key);
398*e7f57d2cSEric Biggers 	if (err) {
399*e7f57d2cSEric Biggers 		ti->error = "Error starting to use blk-crypto";
400*e7f57d2cSEric Biggers 		goto bad;
401*e7f57d2cSEric Biggers 	}
402*e7f57d2cSEric Biggers 
403*e7f57d2cSEric Biggers 	ti->num_flush_bios = 1;
404*e7f57d2cSEric Biggers 
405*e7f57d2cSEric Biggers 	err = 0;
406*e7f57d2cSEric Biggers 	goto out;
407*e7f57d2cSEric Biggers 
408*e7f57d2cSEric Biggers bad:
409*e7f57d2cSEric Biggers 	inlinecrypt_dtr(ti);
410*e7f57d2cSEric Biggers out:
411*e7f57d2cSEric Biggers 	memzero_explicit(raw_key, sizeof(raw_key));
412*e7f57d2cSEric Biggers 	return err;
413*e7f57d2cSEric Biggers }
414*e7f57d2cSEric Biggers 
415*e7f57d2cSEric Biggers static int inlinecrypt_map(struct dm_target *ti, struct bio *bio)
416*e7f57d2cSEric Biggers {
417*e7f57d2cSEric Biggers 	const struct inlinecrypt_ctx *ctx = ti->private;
418*e7f57d2cSEric Biggers 	sector_t sector_in_target;
419*e7f57d2cSEric Biggers 	u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE] = {};
420*e7f57d2cSEric Biggers 
421*e7f57d2cSEric Biggers 	bio_set_dev(bio, ctx->dev->bdev);
422*e7f57d2cSEric Biggers 
423*e7f57d2cSEric Biggers 	/*
424*e7f57d2cSEric Biggers 	 * If the bio is a device-level request which doesn't target a specific
425*e7f57d2cSEric Biggers 	 * sector, there's nothing more to do.
426*e7f57d2cSEric Biggers 	 */
427*e7f57d2cSEric Biggers 	if (bio_sectors(bio) == 0)
428*e7f57d2cSEric Biggers 		return DM_MAPIO_REMAPPED;
429*e7f57d2cSEric Biggers 
430*e7f57d2cSEric Biggers 	/*
431*e7f57d2cSEric Biggers 	 * The bio should never have an encryption context already, since
432*e7f57d2cSEric Biggers 	 * dm-inlinecrypt doesn't pass through any inline encryption
433*e7f57d2cSEric Biggers 	 * capabilities to the layer above it.
434*e7f57d2cSEric Biggers 	 */
435*e7f57d2cSEric Biggers 	if (WARN_ON_ONCE(bio_has_crypt_ctx(bio)))
436*e7f57d2cSEric Biggers 		return DM_MAPIO_KILL;
437*e7f57d2cSEric Biggers 
438*e7f57d2cSEric Biggers 	/* Map the bio's sector to the underlying device. (512-byte sectors) */
439*e7f57d2cSEric Biggers 	sector_in_target = dm_target_offset(ti, bio->bi_iter.bi_sector);
440*e7f57d2cSEric Biggers 	bio->bi_iter.bi_sector = ctx->start + sector_in_target;
441*e7f57d2cSEric Biggers 	/*
442*e7f57d2cSEric Biggers 	 * If the bio doesn't have any data (e.g. if it's a DISCARD request),
443*e7f57d2cSEric Biggers 	 * there's nothing more to do.
444*e7f57d2cSEric Biggers 	 */
445*e7f57d2cSEric Biggers 	if (!bio_has_data(bio))
446*e7f57d2cSEric Biggers 		return DM_MAPIO_REMAPPED;
447*e7f57d2cSEric Biggers 
448*e7f57d2cSEric Biggers 	/* Calculate the DUN and enforce data-unit (crypto sector) alignment. */
449*e7f57d2cSEric Biggers 	dun[0] = ctx->iv_offset + sector_in_target; /* 512-byte sectors */
450*e7f57d2cSEric Biggers 	if (dun[0] & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
451*e7f57d2cSEric Biggers 		return DM_MAPIO_KILL;
452*e7f57d2cSEric Biggers 	dun[0] >>= ctx->sector_bits - SECTOR_SHIFT; /* crypto sectors */
453*e7f57d2cSEric Biggers 
454*e7f57d2cSEric Biggers 	/*
455*e7f57d2cSEric Biggers 	 * This check isn't necessary as we should have calculated max_dun
456*e7f57d2cSEric Biggers 	 * correctly, but be safe.
457*e7f57d2cSEric Biggers 	 */
458*e7f57d2cSEric Biggers 	if (WARN_ON_ONCE(dun[0] > ctx->max_dun))
459*e7f57d2cSEric Biggers 		return DM_MAPIO_KILL;
460*e7f57d2cSEric Biggers 
461*e7f57d2cSEric Biggers 	bio_crypt_set_ctx(bio, &ctx->key, dun, GFP_NOIO);
462*e7f57d2cSEric Biggers 
463*e7f57d2cSEric Biggers 	/*
464*e7f57d2cSEric Biggers 	 * Since we've added an encryption context to the bio and
465*e7f57d2cSEric Biggers 	 * blk-crypto-fallback may be needed to process it, it's necessary to
466*e7f57d2cSEric Biggers 	 * use the fallback-aware bio submission code rather than
467*e7f57d2cSEric Biggers 	 * unconditionally returning DM_MAPIO_REMAPPED.
468*e7f57d2cSEric Biggers 	 *
469*e7f57d2cSEric Biggers 	 * To get the correct accounting for a dm target in the case where
470*e7f57d2cSEric Biggers 	 * __blk_crypto_submit_bio() doesn't take ownership of the bio (returns
471*e7f57d2cSEric Biggers 	 * true), call __blk_crypto_submit_bio() directly and return
472*e7f57d2cSEric Biggers 	 * DM_MAPIO_REMAPPED in that case, rather than relying on
473*e7f57d2cSEric Biggers 	 * blk_crypto_submit_bio() which calls submit_bio() in that case.
474*e7f57d2cSEric Biggers 	 *
475*e7f57d2cSEric Biggers 	 * TODO: blk-crypto fallback write slow-path currently double-accounts
476*e7f57d2cSEric Biggers 	 * IO in vmstat, as encrypted bios are submitted via submit_bio().
477*e7f57d2cSEric Biggers 	 * This does not affect data correctness. Consider fixing this if
478*e7f57d2cSEric Biggers 	 * a cleaner accounting model for derived bios is introduced.
479*e7f57d2cSEric Biggers 	 */
480*e7f57d2cSEric Biggers 	if (__blk_crypto_submit_bio(bio))
481*e7f57d2cSEric Biggers 		return DM_MAPIO_REMAPPED;
482*e7f57d2cSEric Biggers 	return DM_MAPIO_SUBMITTED;
483*e7f57d2cSEric Biggers }
484*e7f57d2cSEric Biggers 
485*e7f57d2cSEric Biggers static void inlinecrypt_status(struct dm_target *ti, status_type_t type,
486*e7f57d2cSEric Biggers 			       unsigned int status_flags, char *result,
487*e7f57d2cSEric Biggers 			       unsigned int maxlen)
488*e7f57d2cSEric Biggers {
489*e7f57d2cSEric Biggers 	const struct inlinecrypt_ctx *ctx = ti->private;
490*e7f57d2cSEric Biggers 	unsigned int sz = 0;
491*e7f57d2cSEric Biggers 	int num_feature_args = 0;
492*e7f57d2cSEric Biggers 
493*e7f57d2cSEric Biggers 	switch (type) {
494*e7f57d2cSEric Biggers 	case STATUSTYPE_INFO:
495*e7f57d2cSEric Biggers 	case STATUSTYPE_IMA:
496*e7f57d2cSEric Biggers 		result[0] = '\0';
497*e7f57d2cSEric Biggers 		break;
498*e7f57d2cSEric Biggers 
499*e7f57d2cSEric Biggers 	case STATUSTYPE_TABLE:
500*e7f57d2cSEric Biggers 		/*
501*e7f57d2cSEric Biggers 		 * Warning: like dm-crypt, dm-inlinecrypt includes the key in
502*e7f57d2cSEric Biggers 		 * the returned table.  Userspace is responsible for redacting
503*e7f57d2cSEric Biggers 		 * the key when needed.
504*e7f57d2cSEric Biggers 		 */
505*e7f57d2cSEric Biggers 		DMEMIT("%s %*phN %llu %s %llu", ctx->cipher_string,
506*e7f57d2cSEric Biggers 		       ctx->key.size, ctx->key.bytes, ctx->iv_offset,
507*e7f57d2cSEric Biggers 		       ctx->dev->name, ctx->start);
508*e7f57d2cSEric Biggers 		num_feature_args += !!ti->num_discard_bios;
509*e7f57d2cSEric Biggers 		if (ctx->sector_size != SECTOR_SIZE)
510*e7f57d2cSEric Biggers 			num_feature_args += 2;
511*e7f57d2cSEric Biggers 		if (num_feature_args != 0) {
512*e7f57d2cSEric Biggers 			DMEMIT(" %d", num_feature_args);
513*e7f57d2cSEric Biggers 			if (ti->num_discard_bios)
514*e7f57d2cSEric Biggers 				DMEMIT(" allow_discards");
515*e7f57d2cSEric Biggers 			if (ctx->sector_size != SECTOR_SIZE) {
516*e7f57d2cSEric Biggers 				DMEMIT(" sector_size:%u", ctx->sector_size);
517*e7f57d2cSEric Biggers 				DMEMIT(" iv_large_sectors");
518*e7f57d2cSEric Biggers 			}
519*e7f57d2cSEric Biggers 		}
520*e7f57d2cSEric Biggers 		break;
521*e7f57d2cSEric Biggers 	}
522*e7f57d2cSEric Biggers }
523*e7f57d2cSEric Biggers 
524*e7f57d2cSEric Biggers static int inlinecrypt_prepare_ioctl(struct dm_target *ti,
525*e7f57d2cSEric Biggers 				     struct block_device **bdev, unsigned int cmd,
526*e7f57d2cSEric Biggers 				     unsigned long arg, bool *forward)
527*e7f57d2cSEric Biggers {
528*e7f57d2cSEric Biggers 	const struct inlinecrypt_ctx *ctx = ti->private;
529*e7f57d2cSEric Biggers 	const struct dm_dev *dev = ctx->dev;
530*e7f57d2cSEric Biggers 
531*e7f57d2cSEric Biggers 	*bdev = dev->bdev;
532*e7f57d2cSEric Biggers 
533*e7f57d2cSEric Biggers 	/* Only pass ioctls through if the device sizes match exactly. */
534*e7f57d2cSEric Biggers 	return ctx->start != 0 || ti->len != bdev_nr_sectors(dev->bdev);
535*e7f57d2cSEric Biggers }
536*e7f57d2cSEric Biggers 
537*e7f57d2cSEric Biggers static int inlinecrypt_iterate_devices(struct dm_target *ti,
538*e7f57d2cSEric Biggers 				       iterate_devices_callout_fn fn,
539*e7f57d2cSEric Biggers 				       void *data)
540*e7f57d2cSEric Biggers {
541*e7f57d2cSEric Biggers 	const struct inlinecrypt_ctx *ctx = ti->private;
542*e7f57d2cSEric Biggers 
543*e7f57d2cSEric Biggers 	return fn(ti, ctx->dev, ctx->start, ti->len, data);
544*e7f57d2cSEric Biggers }
545*e7f57d2cSEric Biggers 
546*e7f57d2cSEric Biggers #ifdef CONFIG_BLK_DEV_ZONED
547*e7f57d2cSEric Biggers static int inlinecrypt_report_zones(struct dm_target *ti,
548*e7f57d2cSEric Biggers 				    struct dm_report_zones_args *args,
549*e7f57d2cSEric Biggers 				    unsigned int nr_zones)
550*e7f57d2cSEric Biggers {
551*e7f57d2cSEric Biggers 	const struct inlinecrypt_ctx *ctx = ti->private;
552*e7f57d2cSEric Biggers 
553*e7f57d2cSEric Biggers 	return dm_report_zones(ctx->dev->bdev, ctx->start,
554*e7f57d2cSEric Biggers 			ctx->start + dm_target_offset(ti, args->next_sector),
555*e7f57d2cSEric Biggers 			args, nr_zones);
556*e7f57d2cSEric Biggers }
557*e7f57d2cSEric Biggers #else
558*e7f57d2cSEric Biggers #define inlinecrypt_report_zones NULL
559*e7f57d2cSEric Biggers #endif
560*e7f57d2cSEric Biggers 
561*e7f57d2cSEric Biggers static void inlinecrypt_io_hints(struct dm_target *ti,
562*e7f57d2cSEric Biggers 				 struct queue_limits *limits)
563*e7f57d2cSEric Biggers {
564*e7f57d2cSEric Biggers 	const struct inlinecrypt_ctx *ctx = ti->private;
565*e7f57d2cSEric Biggers 	const unsigned int sector_size = ctx->sector_size;
566*e7f57d2cSEric Biggers 
567*e7f57d2cSEric Biggers 	limits->logical_block_size =
568*e7f57d2cSEric Biggers 		max_t(unsigned int, limits->logical_block_size, sector_size);
569*e7f57d2cSEric Biggers 	limits->physical_block_size =
570*e7f57d2cSEric Biggers 		max_t(unsigned int, limits->physical_block_size, sector_size);
571*e7f57d2cSEric Biggers 	limits->io_min = max_t(unsigned int, limits->io_min, sector_size);
572*e7f57d2cSEric Biggers 	limits->dma_alignment = limits->logical_block_size - 1;
573*e7f57d2cSEric Biggers }
574*e7f57d2cSEric Biggers 
575*e7f57d2cSEric Biggers static struct target_type inlinecrypt_target = {
576*e7f57d2cSEric Biggers 	.name			= "inlinecrypt",
577*e7f57d2cSEric Biggers 	.version		= {1, 0, 0},
578*e7f57d2cSEric Biggers 	/*
579*e7f57d2cSEric Biggers 	 * Do not set DM_TARGET_PASSES_CRYPTO, since dm-inlinecrypt consumes the
580*e7f57d2cSEric Biggers 	 * crypto capability itself.
581*e7f57d2cSEric Biggers 	 */
582*e7f57d2cSEric Biggers 	.features		= DM_TARGET_ZONED_HM,
583*e7f57d2cSEric Biggers 	.module			= THIS_MODULE,
584*e7f57d2cSEric Biggers 	.ctr			= inlinecrypt_ctr,
585*e7f57d2cSEric Biggers 	.dtr			= inlinecrypt_dtr,
586*e7f57d2cSEric Biggers 	.map			= inlinecrypt_map,
587*e7f57d2cSEric Biggers 	.status			= inlinecrypt_status,
588*e7f57d2cSEric Biggers 	.prepare_ioctl		= inlinecrypt_prepare_ioctl,
589*e7f57d2cSEric Biggers 	.iterate_devices	= inlinecrypt_iterate_devices,
590*e7f57d2cSEric Biggers 	.report_zones		= inlinecrypt_report_zones,
591*e7f57d2cSEric Biggers 	.io_hints		= inlinecrypt_io_hints,
592*e7f57d2cSEric Biggers };
593*e7f57d2cSEric Biggers 
594*e7f57d2cSEric Biggers module_dm(inlinecrypt);
595*e7f57d2cSEric Biggers 
596*e7f57d2cSEric Biggers MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>");
597*e7f57d2cSEric Biggers MODULE_AUTHOR("Linlin Zhang <linlin.zhang@oss.qualcomm.com>");
598*e7f57d2cSEric Biggers MODULE_DESCRIPTION(DM_NAME " target for inline encryption");
599*e7f57d2cSEric Biggers MODULE_LICENSE("GPL");
600