“1de84979dfc527c422abf63f27beabe43892989b”上不存在“README.md”
big_key.c 10.0 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2 3
/* Large capacity key type
 *
4
 * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
5 6 7 8
 * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 */

9
#define pr_fmt(fmt) "big_key: "fmt
10 11 12 13 14
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/file.h>
#include <linux/shmem_fs.h>
#include <linux/err.h>
15
#include <linux/scatterlist.h>
16
#include <linux/random.h>
17
#include <linux/vmalloc.h>
18 19
#include <keys/user-type.h>
#include <keys/big_key-type.h>
20
#include <crypto/aead.h>
21
#include <crypto/gcm.h>
22

23 24 25 26 27 28 29
struct big_key_buf {
	unsigned int		nr_pages;
	void			*virt;
	struct scatterlist	*sg;
	struct page		*pages[];
};

30 31 32 33 34 35 36 37 38 39
/*
 * Layout of key payload words.
 */
enum {
	big_key_data,
	big_key_path,
	big_key_path_2nd_part,
	big_key_len,
};

40 41 42 43 44 45 46 47
/*
 * Crypto operation with big_key data
 */
enum big_key_op {
	BIG_KEY_ENC,
	BIG_KEY_DEC,
};

48 49 50 51 52 53 54
/*
 * If the data is under this limit, there's no point creating a shm file to
 * hold it as the permanently resident metadata for the shmem fs will be at
 * least as large as the data.
 */
#define BIG_KEY_FILE_THRESHOLD (sizeof(struct inode) + sizeof(struct dentry))

55 56 57
/*
 * Key size for big_key data encryption
 */
58 59 60 61 62 63
#define ENC_KEY_SIZE 32

/*
 * Authentication tag length
 */
#define ENC_AUTHTAG_SIZE 16
64

65 66 67 68 69 70
/*
 * big_key defined keys take an arbitrary string as the description and an
 * arbitrary blob of data as the payload
 */
struct key_type key_type_big_key = {
	.name			= "big_key",
71 72 73
	.preparse		= big_key_preparse,
	.free_preparse		= big_key_free_preparse,
	.instantiate		= generic_key_instantiate,
74 75 76 77
	.revoke			= big_key_revoke,
	.destroy		= big_key_destroy,
	.describe		= big_key_describe,
	.read			= big_key_read,
78
	/* no ->update(); don't add it without changing big_key_crypt() nonce */
79 80
};

81
/*
82
 * Crypto names for big_key data authenticated encryption
83
 */
84
static const char big_key_alg_name[] = "gcm(aes)";
85
#define BIG_KEY_IV_SIZE		GCM_AES_IV_SIZE
86 87

/*
88
 * Crypto algorithms for big_key data authenticated encryption
89
 */
90
static struct crypto_aead *big_key_aead;
91 92

/*
93
 * Since changing the key affects the entire object, we need a mutex.
94
 */
95
static DEFINE_MUTEX(big_key_aead_lock);
96 97 98 99

/*
 * Encrypt/decrypt big_key data
 */
100
static int big_key_crypt(enum big_key_op op, struct big_key_buf *buf, size_t datalen, u8 *key)
101
{
102 103 104 105 106 107 108 109
	int ret;
	struct aead_request *aead_req;
	/* We always use a zero nonce. The reason we can get away with this is
	 * because we're using a different randomly generated key for every
	 * different encryption. Notably, too, key_type_big_key doesn't define
	 * an .update function, so there's no chance we'll wind up reusing the
	 * key to encrypt updated data. Simply put: one key, one encryption.
	 */
110
	u8 zero_nonce[BIG_KEY_IV_SIZE];
111 112 113 114 115 116

	aead_req = aead_request_alloc(big_key_aead, GFP_KERNEL);
	if (!aead_req)
		return -ENOMEM;

	memset(zero_nonce, 0, sizeof(zero_nonce));
117
	aead_request_set_crypt(aead_req, buf->sg, buf->sg, datalen, zero_nonce);
118 119 120 121 122
	aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
	aead_request_set_ad(aead_req, 0);

	mutex_lock(&big_key_aead_lock);
	if (crypto_aead_setkey(big_key_aead, key, ENC_KEY_SIZE)) {
123 124 125 126
		ret = -EAGAIN;
		goto error;
	}
	if (op == BIG_KEY_ENC)
127
		ret = crypto_aead_encrypt(aead_req);
128
	else
129
		ret = crypto_aead_decrypt(aead_req);
130
error:
131 132
	mutex_unlock(&big_key_aead_lock);
	aead_request_free(aead_req);
133 134 135
	return ret;
}

136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
/*
 * Free up the buffer.
 */
static void big_key_free_buffer(struct big_key_buf *buf)
{
	unsigned int i;

	if (buf->virt) {
		memset(buf->virt, 0, buf->nr_pages * PAGE_SIZE);
		vunmap(buf->virt);
	}

	for (i = 0; i < buf->nr_pages; i++)
		if (buf->pages[i])
			__free_page(buf->pages[i]);

	kfree(buf);
}

/*
 * Allocate a buffer consisting of a set of pages with a virtual mapping
 * applied over them.
 */
static void *big_key_alloc_buffer(size_t len)
{
	struct big_key_buf *buf;
	unsigned int npg = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
	unsigned int i, l;

	buf = kzalloc(sizeof(struct big_key_buf) +
		      sizeof(struct page) * npg +
		      sizeof(struct scatterlist) * npg,
		      GFP_KERNEL);
	if (!buf)
		return NULL;

	buf->nr_pages = npg;
	buf->sg = (void *)(buf->pages + npg);
	sg_init_table(buf->sg, npg);

	for (i = 0; i < buf->nr_pages; i++) {
		buf->pages[i] = alloc_page(GFP_KERNEL);
		if (!buf->pages[i])
			goto nomem;

		l = min_t(size_t, len, PAGE_SIZE);
		sg_set_page(&buf->sg[i], buf->pages[i], l, 0);
		len -= l;
	}

	buf->virt = vmap(buf->pages, buf->nr_pages, VM_MAP, PAGE_KERNEL);
	if (!buf->virt)
		goto nomem;

	return buf;

nomem:
	big_key_free_buffer(buf);
	return NULL;
}

197
/*
198
 * Preparse a big key
199
 */
200
int big_key_preparse(struct key_preparsed_payload *prep)
201
{
202
	struct big_key_buf *buf;
203
	struct path *path = (struct path *)&prep->payload.data[big_key_path];
204
	struct file *file;
205
	u8 *enckey;
206
	ssize_t written;
207
	size_t datalen = prep->datalen, enclen = datalen + ENC_AUTHTAG_SIZE;
208 209 210
	int ret;

	if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data)
211
		return -EINVAL;
212 213

	/* Set an arbitrary quota */
214
	prep->quotalen = 16;
215

216
	prep->payload.data[big_key_len] = (void *)(unsigned long)datalen;
217 218 219 220 221

	if (datalen > BIG_KEY_FILE_THRESHOLD) {
		/* Create a shmem file to store the data in.  This will permit the data
		 * to be swapped out if needed.
		 *
222
		 * File content is stored encrypted with randomly generated key.
223
		 */
224
		loff_t pos = 0;
225

226 227
		buf = big_key_alloc_buffer(enclen);
		if (!buf)
228
			return -ENOMEM;
229
		memcpy(buf->virt, prep->data, datalen);
230 231 232 233 234 235 236

		/* generate random key */
		enckey = kmalloc(ENC_KEY_SIZE, GFP_KERNEL);
		if (!enckey) {
			ret = -ENOMEM;
			goto error;
		}
237 238
		ret = get_random_bytes_wait(enckey, ENC_KEY_SIZE);
		if (unlikely(ret))
239 240 241
			goto err_enckey;

		/* encrypt aligned data */
242
		ret = big_key_crypt(BIG_KEY_ENC, buf, datalen, enckey);
243 244 245 246 247
		if (ret)
			goto err_enckey;

		/* save aligned data to file */
		file = shmem_kernel_file_setup("", enclen, 0);
248 249
		if (IS_ERR(file)) {
			ret = PTR_ERR(file);
250
			goto err_enckey;
251
		}
252

253
		written = kernel_write(file, buf->virt, enclen, &pos);
254
		if (written != enclen) {
255
			ret = written;
256 257 258 259 260 261 262 263
			if (written >= 0)
				ret = -ENOMEM;
			goto err_fput;
		}

		/* Pin the mount and dentry to the key so that we can open it again
		 * later
		 */
264
		prep->payload.data[big_key_data] = enckey;
265 266 267
		*path = file->f_path;
		path_get(path);
		fput(file);
268
		big_key_free_buffer(buf);
269 270 271
	} else {
		/* Just store the data in a buffer */
		void *data = kmalloc(datalen, GFP_KERNEL);
272

273 274
		if (!data)
			return -ENOMEM;
275

276 277
		prep->payload.data[big_key_data] = data;
		memcpy(data, prep->data, prep->datalen);
278 279 280 281 282
	}
	return 0;

err_fput:
	fput(file);
283
err_enckey:
284
	kzfree(enckey);
285
error:
286
	big_key_free_buffer(buf);
287 288 289
	return ret;
}

290 291 292 293 294 295
/*
 * Clear preparsement.
 */
void big_key_free_preparse(struct key_preparsed_payload *prep)
{
	if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
296
		struct path *path = (struct path *)&prep->payload.data[big_key_path];
297

298 299
		path_put(path);
	}
300
	kzfree(prep->payload.data[big_key_data]);
301 302
}

303 304 305 306 307 308
/*
 * dispose of the links from a revoked keyring
 * - called with the key sem write-locked
 */
void big_key_revoke(struct key *key)
{
309
	struct path *path = (struct path *)&key->payload.data[big_key_path];
310 311 312

	/* clear the quota */
	key_payload_reserve(key, 0);
313
	if (key_is_positive(key) &&
314
	    (size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD)
315 316 317 318 319 320 321 322
		vfs_truncate(path, 0);
}

/*
 * dispose of the data dangling from the corpse of a big_key key
 */
void big_key_destroy(struct key *key)
{
323 324
	size_t datalen = (size_t)key->payload.data[big_key_len];

325
	if (datalen > BIG_KEY_FILE_THRESHOLD) {
326
		struct path *path = (struct path *)&key->payload.data[big_key_path];
327

328 329 330 331
		path_put(path);
		path->mnt = NULL;
		path->dentry = NULL;
	}
332
	kzfree(key->payload.data[big_key_data]);
333
	key->payload.data[big_key_data] = NULL;
334 335 336 337 338 339 340
}

/*
 * describe the big_key key
 */
void big_key_describe(const struct key *key, struct seq_file *m)
{
341
	size_t datalen = (size_t)key->payload.data[big_key_len];
342 343 344

	seq_puts(m, key->description);

345
	if (key_is_positive(key))
346
		seq_printf(m, ": %zu [%s]",
347 348 349 350 351 352 353 354
			   datalen,
			   datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff");
}

/*
 * read the key data
 * - the key's semaphore is read-locked
 */
355
long big_key_read(const struct key *key, char *buffer, size_t buflen)
356
{
357
	size_t datalen = (size_t)key->payload.data[big_key_len];
358 359 360 361 362 363
	long ret;

	if (!buffer || buflen < datalen)
		return datalen;

	if (datalen > BIG_KEY_FILE_THRESHOLD) {
364
		struct big_key_buf *buf;
365
		struct path *path = (struct path *)&key->payload.data[big_key_path];
366
		struct file *file;
367
		u8 *enckey = (u8 *)key->payload.data[big_key_data];
368
		size_t enclen = datalen + ENC_AUTHTAG_SIZE;
369
		loff_t pos = 0;
370

371 372
		buf = big_key_alloc_buffer(enclen);
		if (!buf)
373
			return -ENOMEM;
374 375

		file = dentry_open(path, O_RDONLY, current_cred());
376 377 378 379
		if (IS_ERR(file)) {
			ret = PTR_ERR(file);
			goto error;
		}
380

381
		/* read file to kernel and decrypt */
382
		ret = kernel_read(file, buf->virt, enclen, &pos);
383
		if (ret >= 0 && ret != enclen) {
384
			ret = -EIO;
385 386 387
			goto err_fput;
		}

388
		ret = big_key_crypt(BIG_KEY_DEC, buf, enclen, enckey);
389 390 391 392 393
		if (ret)
			goto err_fput;

		ret = datalen;

394 395
		/* copy out decrypted data */
		memcpy(buffer, buf->virt, datalen);
396 397 398 399

err_fput:
		fput(file);
error:
400
		big_key_free_buffer(buf);
401 402
	} else {
		ret = datalen;
403
		memcpy(buffer, key->payload.data[big_key_data], datalen);
404 405 406 407 408
	}

	return ret;
}

409 410 411
/*
 * Register key type
 */
412 413
static int __init big_key_init(void)
{
414
	int ret;
415 416

	/* init block cipher */
417 418 419
	big_key_aead = crypto_alloc_aead(big_key_alg_name, 0, CRYPTO_ALG_ASYNC);
	if (IS_ERR(big_key_aead)) {
		ret = PTR_ERR(big_key_aead);
420
		pr_err("Can't alloc crypto: %d\n", ret);
421 422
		return ret;
	}
423 424 425 426 427 428 429

	if (unlikely(crypto_aead_ivsize(big_key_aead) != BIG_KEY_IV_SIZE)) {
		WARN(1, "big key algorithm changed?");
		ret = -EINVAL;
		goto free_aead;
	}

430 431 432 433
	ret = crypto_aead_setauthsize(big_key_aead, ENC_AUTHTAG_SIZE);
	if (ret < 0) {
		pr_err("Can't set crypto auth tag len: %d\n", ret);
		goto free_aead;
434 435 436 437 438
	}

	ret = register_key_type(&key_type_big_key);
	if (ret < 0) {
		pr_err("Can't register type: %d\n", ret);
439
		goto free_aead;
440 441 442 443
	}

	return 0;

444 445
free_aead:
	crypto_free_aead(big_key_aead);
446 447 448
	return ret;
}

449
late_initcall(big_key_init);
新手
引导
客服 返回
顶部