crypto_fname.c 11.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * linux/fs/ext4/crypto_fname.c
 *
 * Copyright (C) 2015, Google, Inc.
 *
 * This contains functions for filename crypto management in ext4
 *
 * Written by Uday Savagaonkar, 2014.
 *
 * This has not yet undergone a rigorous security audit.
 *
 */

H
Herbert Xu 已提交
14
#include <crypto/skcipher.h>
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
#include <keys/encrypted-type.h>
#include <keys/user-type.h>
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/key.h>
#include <linux/list.h>
#include <linux/mempool.h>
#include <linux/random.h>
#include <linux/scatterlist.h>
#include <linux/spinlock_types.h>

#include "ext4.h"
#include "ext4_crypto.h"
#include "xattr.h"

/**
 * ext4_dir_crypt_complete() -
 */
static void ext4_dir_crypt_complete(struct crypto_async_request *req, int res)
{
	struct ext4_completion_result *ecr = req->data;

	if (res == -EINPROGRESS)
		return;
	ecr->res = res;
	complete(&ecr->completion);
}

bool ext4_valid_filenames_enc_mode(uint32_t mode)
{
	return (mode == EXT4_ENCRYPTION_MODE_AES_256_CTS);
}

48 49 50 51 52 53
static unsigned max_name_len(struct inode *inode)
{
	return S_ISLNK(inode->i_mode) ? inode->i_sb->s_blocksize :
		EXT4_NAME_LEN;
}

54 55 56 57 58 59 60
/**
 * ext4_fname_encrypt() -
 *
 * This function encrypts the input filename, and returns the length of the
 * ciphertext. Errors are returned as negative numbers.  We trust the caller to
 * allocate sufficient memory to oname string.
 */
61
static int ext4_fname_encrypt(struct inode *inode,
62 63 64 65
			      const struct qstr *iname,
			      struct ext4_str *oname)
{
	u32 ciphertext_len;
H
Herbert Xu 已提交
66
	struct skcipher_request *req = NULL;
67
	DECLARE_EXT4_COMPLETION_RESULT(ecr);
68
	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
H
Herbert Xu 已提交
69
	struct crypto_skcipher *tfm = ci->ci_ctfm;
70 71
	int res = 0;
	char iv[EXT4_CRYPTO_BLOCK_SIZE];
72
	struct scatterlist src_sg, dst_sg;
73
	int padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
74
	char *workbuf, buf[32], *alloc_buf = NULL;
75
	unsigned lim = max_name_len(inode);
76

77
	if (iname->len <= 0 || iname->len > lim)
78 79 80 81
		return -EIO;

	ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ?
		EXT4_CRYPTO_BLOCK_SIZE : iname->len;
82
	ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
83 84
	ciphertext_len = (ciphertext_len > lim)
			? lim : ciphertext_len;
85

86 87 88 89 90 91 92 93 94
	if (ciphertext_len <= sizeof(buf)) {
		workbuf = buf;
	} else {
		alloc_buf = kmalloc(ciphertext_len, GFP_NOFS);
		if (!alloc_buf)
			return -ENOMEM;
		workbuf = alloc_buf;
	}

95
	/* Allocate request */
H
Herbert Xu 已提交
96
	req = skcipher_request_alloc(tfm, GFP_NOFS);
97 98 99
	if (!req) {
		printk_ratelimited(
		    KERN_ERR "%s: crypto_request_alloc() failed\n", __func__);
100
		kfree(alloc_buf);
101 102
		return -ENOMEM;
	}
H
Herbert Xu 已提交
103
	skcipher_request_set_callback(req,
104 105 106 107 108 109 110 111 112 113 114 115
		CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
		ext4_dir_crypt_complete, &ecr);

	/* Copy the input */
	memcpy(workbuf, iname->name, iname->len);
	if (iname->len < ciphertext_len)
		memset(workbuf + iname->len, 0, ciphertext_len - iname->len);

	/* Initialize IV */
	memset(iv, 0, EXT4_CRYPTO_BLOCK_SIZE);

	/* Create encryption request */
116 117
	sg_init_one(&src_sg, workbuf, ciphertext_len);
	sg_init_one(&dst_sg, oname->name, ciphertext_len);
H
Herbert Xu 已提交
118 119
	skcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv);
	res = crypto_skcipher_encrypt(req);
120 121 122 123
	if (res == -EINPROGRESS || res == -EBUSY) {
		wait_for_completion(&ecr.completion);
		res = ecr.res;
	}
124
	kfree(alloc_buf);
H
Herbert Xu 已提交
125
	skcipher_request_free(req);
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
	if (res < 0) {
		printk_ratelimited(
		    KERN_ERR "%s: Error (error code %d)\n", __func__, res);
	}
	oname->len = ciphertext_len;
	return res;
}

/*
 * ext4_fname_decrypt()
 *	This function decrypts the input filename, and returns
 *	the length of the plaintext.
 *	Errors are returned as negative numbers.
 *	We trust the caller to allocate sufficient memory to oname string.
 */
141
static int ext4_fname_decrypt(struct inode *inode,
142 143 144 145
			      const struct ext4_str *iname,
			      struct ext4_str *oname)
{
	struct ext4_str tmp_in[2], tmp_out[1];
H
Herbert Xu 已提交
146
	struct skcipher_request *req = NULL;
147
	DECLARE_EXT4_COMPLETION_RESULT(ecr);
148
	struct scatterlist src_sg, dst_sg;
149
	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
H
Herbert Xu 已提交
150
	struct crypto_skcipher *tfm = ci->ci_ctfm;
151 152
	int res = 0;
	char iv[EXT4_CRYPTO_BLOCK_SIZE];
153
	unsigned lim = max_name_len(inode);
154

155
	if (iname->len <= 0 || iname->len > lim)
156 157 158 159 160 161 162
		return -EIO;

	tmp_in[0].name = iname->name;
	tmp_in[0].len = iname->len;
	tmp_out[0].name = oname->name;

	/* Allocate request */
H
Herbert Xu 已提交
163
	req = skcipher_request_alloc(tfm, GFP_NOFS);
164 165 166 167 168
	if (!req) {
		printk_ratelimited(
		    KERN_ERR "%s: crypto_request_alloc() failed\n",  __func__);
		return -ENOMEM;
	}
H
Herbert Xu 已提交
169
	skcipher_request_set_callback(req,
170 171 172 173 174 175 176
		CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
		ext4_dir_crypt_complete, &ecr);

	/* Initialize IV */
	memset(iv, 0, EXT4_CRYPTO_BLOCK_SIZE);

	/* Create encryption request */
177 178
	sg_init_one(&src_sg, iname->name, iname->len);
	sg_init_one(&dst_sg, oname->name, oname->len);
H
Herbert Xu 已提交
179 180
	skcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv);
	res = crypto_skcipher_decrypt(req);
181 182 183 184
	if (res == -EINPROGRESS || res == -EBUSY) {
		wait_for_completion(&ecr.completion);
		res = ecr.res;
	}
H
Herbert Xu 已提交
185
	skcipher_request_free(req);
186 187 188 189 190 191 192 193 194 195 196
	if (res < 0) {
		printk_ratelimited(
		    KERN_ERR "%s: Error in ext4_fname_encrypt (error code %d)\n",
		    __func__, res);
		return res;
	}

	oname->len = strnlen(oname->name, iname->len);
	return oname->len;
}

197 198 199
static const char *lookup_table =
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";

200 201 202 203 204 205
/**
 * ext4_fname_encode_digest() -
 *
 * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
 * The encoded string is roughly 4/3 times the size of the input string.
 */
206
static int digest_encode(const char *src, int len, char *dst)
207
{
208 209 210 211 212 213 214 215 216 217 218
	int i = 0, bits = 0, ac = 0;
	char *cp = dst;

	while (i < len) {
		ac += (((unsigned char) src[i]) << bits);
		bits += 8;
		do {
			*cp++ = lookup_table[ac & 0x3f];
			ac >>= 6;
			bits -= 6;
		} while (bits >= 6);
219 220
		i++;
	}
221 222 223
	if (bits)
		*cp++ = lookup_table[ac & 0x3f];
	return cp - dst;
224 225
}

226
static int digest_decode(const char *src, int len, char *dst)
227
{
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
	int i = 0, bits = 0, ac = 0;
	const char *p;
	char *cp = dst;

	while (i < len) {
		p = strchr(lookup_table, src[i]);
		if (p == NULL || src[i] == 0)
			return -2;
		ac += (p - lookup_table) << bits;
		bits += 6;
		if (bits >= 8) {
			*cp++ = ac & 0xff;
			ac >>= 8;
			bits -= 8;
		}
		i++;
244
	}
245 246 247
	if (ac)
		return -1;
	return cp - dst;
248 249 250 251 252 253 254 255 256 257 258 259
}

/**
 * ext4_fname_crypto_round_up() -
 *
 * Return: The next multiple of block size
 */
u32 ext4_fname_crypto_round_up(u32 size, u32 blksize)
{
	return ((size+blksize-1)/blksize)*blksize;
}

260 261 262 263 264 265 266 267 268 269 270 271 272 273
unsigned ext4_fname_encrypted_size(struct inode *inode, u32 ilen)
{
	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
	int padding = 32;

	if (ci)
		padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
	if (ilen < EXT4_CRYPTO_BLOCK_SIZE)
		ilen = EXT4_CRYPTO_BLOCK_SIZE;
	return ext4_fname_crypto_round_up(ilen, padding);
}

/*
 * ext4_fname_crypto_alloc_buffer() -
274 275 276 277
 *
 * Allocates an output buffer that is sufficient for the crypto operation
 * specified by the context and the direction.
 */
278
int ext4_fname_crypto_alloc_buffer(struct inode *inode,
279 280
				   u32 ilen, struct ext4_str *crypto_str)
{
281
	unsigned int olen = ext4_fname_encrypted_size(inode, ilen);
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309

	crypto_str->len = olen;
	if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2)
		olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2;
	/* Allocated buffer can hold one more character to null-terminate the
	 * string */
	crypto_str->name = kmalloc(olen+1, GFP_NOFS);
	if (!(crypto_str->name))
		return -ENOMEM;
	return 0;
}

/**
 * ext4_fname_crypto_free_buffer() -
 *
 * Frees the buffer allocated for crypto operation.
 */
void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str)
{
	if (!crypto_str)
		return;
	kfree(crypto_str->name);
	crypto_str->name = NULL;
}

/**
 * ext4_fname_disk_to_usr() - converts a filename from disk space to user space
 */
310
int _ext4_fname_disk_to_usr(struct inode *inode,
311 312 313
			    struct dx_hash_info *hinfo,
			    const struct ext4_str *iname,
			    struct ext4_str *oname)
314
{
315 316 317
	char buf[24];
	int ret;

318 319 320 321 322 323 324 325 326
	if (iname->len < 3) {
		/*Check for . and .. */
		if (iname->name[0] == '.' && iname->name[iname->len-1] == '.') {
			oname->name[0] = '.';
			oname->name[iname->len-1] = '.';
			oname->len = iname->len;
			return oname->len;
		}
	}
327 328 329 330
	if (iname->len < EXT4_CRYPTO_BLOCK_SIZE) {
		EXT4_ERROR_INODE(inode, "encrypted inode too small");
		return -EUCLEAN;
	}
331 332
	if (EXT4_I(inode)->i_crypt_info)
		return ext4_fname_decrypt(inode, iname, oname);
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348

	if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) {
		ret = digest_encode(iname->name, iname->len, oname->name);
		oname->len = ret;
		return ret;
	}
	if (hinfo) {
		memcpy(buf, &hinfo->hash, 4);
		memcpy(buf+4, &hinfo->minor_hash, 4);
	} else
		memset(buf, 0, 8);
	memcpy(buf + 8, iname->name + iname->len - 16, 16);
	oname->name[0] = '_';
	ret = digest_encode(buf, 24, oname->name+1);
	oname->len = ret + 1;
	return ret + 1;
349 350
}

351
int ext4_fname_disk_to_usr(struct inode *inode,
352
			   struct dx_hash_info *hinfo,
353 354 355 356 357 358
			   const struct ext4_dir_entry_2 *de,
			   struct ext4_str *oname)
{
	struct ext4_str iname = {.name = (unsigned char *) de->name,
				 .len = de->name_len };

359
	return _ext4_fname_disk_to_usr(inode, hinfo, &iname, oname);
360 361 362 363 364 365
}


/**
 * ext4_fname_usr_to_disk() - converts a filename from user space to disk space
 */
366
int ext4_fname_usr_to_disk(struct inode *inode,
367 368 369 370
			   const struct qstr *iname,
			   struct ext4_str *oname)
{
	int res;
371
	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
372 373 374 375 376 377 378 379 380 381 382

	if (iname->len < 3) {
		/*Check for . and .. */
		if (iname->name[0] == '.' &&
				iname->name[iname->len-1] == '.') {
			oname->name[0] = '.';
			oname->name[iname->len-1] = '.';
			oname->len = iname->len;
			return oname->len;
		}
	}
383 384
	if (ci) {
		res = ext4_fname_encrypt(inode, iname, oname);
385 386 387 388 389 390 391 392
		return res;
	}
	/* Without a proper key, a user is not allowed to modify the filenames
	 * in a directory. Consequently, a user space name cannot be mapped to
	 * a disk-space name */
	return -EACCES;
}

393 394
int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
			      int lookup, struct ext4_filename *fname)
395
{
396
	struct ext4_crypt_info *ci;
397 398 399 400
	int ret = 0, bigname = 0;

	memset(fname, 0, sizeof(struct ext4_filename));
	fname->usr_fname = iname;
401

402
	if (!ext4_encrypted_inode(dir) ||
403 404 405
	    ((iname->name[0] == '.') &&
	     ((iname->len == 1) ||
	      ((iname->name[1] == '.') && (iname->len == 2))))) {
406 407
		fname->disk_name.name = (unsigned char *) iname->name;
		fname->disk_name.len = iname->len;
408
		return 0;
409
	}
410
	ret = ext4_get_encryption_info(dir);
411 412 413 414 415
	if (ret)
		return ret;
	ci = EXT4_I(dir)->i_crypt_info;
	if (ci) {
		ret = ext4_fname_crypto_alloc_buffer(dir, iname->len,
416 417
						     &fname->crypto_buf);
		if (ret < 0)
418
			return ret;
419
		ret = ext4_fname_encrypt(dir, iname, &fname->crypto_buf);
420
		if (ret < 0)
421
			goto errout;
422 423
		fname->disk_name.name = fname->crypto_buf.name;
		fname->disk_name.len = fname->crypto_buf.len;
424
		return 0;
425
	}
426 427
	if (!lookup)
		return -EACCES;
428

429 430 431 432 433 434
	/* We don't have the key and we are doing a lookup; decode the
	 * user-supplied name
	 */
	if (iname->name[0] == '_')
		bigname = 1;
	if ((bigname && (iname->len != 33)) ||
435 436 437
	    (!bigname && (iname->len > 43)))
		return -ENOENT;

438
	fname->crypto_buf.name = kmalloc(32, GFP_KERNEL);
439 440
	if (fname->crypto_buf.name == NULL)
		return -ENOMEM;
441 442 443 444
	ret = digest_decode(iname->name + bigname, iname->len - bigname,
			    fname->crypto_buf.name);
	if (ret < 0) {
		ret = -ENOENT;
445
		goto errout;
446 447 448 449 450 451 452 453 454
	}
	fname->crypto_buf.len = ret;
	if (bigname) {
		memcpy(&fname->hinfo.hash, fname->crypto_buf.name, 4);
		memcpy(&fname->hinfo.minor_hash, fname->crypto_buf.name + 4, 4);
	} else {
		fname->disk_name.name = fname->crypto_buf.name;
		fname->disk_name.len = fname->crypto_buf.len;
	}
455 456 457 458
	return 0;
errout:
	kfree(fname->crypto_buf.name);
	fname->crypto_buf.name = NULL;
459 460 461
	return ret;
}

462
void ext4_fname_free_filename(struct ext4_filename *fname)
463
{
464 465 466 467
	kfree(fname->crypto_buf.name);
	fname->crypto_buf.name = NULL;
	fname->usr_fname = NULL;
	fname->disk_name.name = NULL;
468
}