xref: /openbmc/linux/security/keys/big_key.c (revision bdd91001)
1 /* Large capacity key type
2  *
3  * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public Licence
8  * as published by the Free Software Foundation; either version
9  * 2 of the Licence, or (at your option) any later version.
10  */
11 
12 #include <linux/init.h>
13 #include <linux/seq_file.h>
14 #include <linux/file.h>
15 #include <linux/shmem_fs.h>
16 #include <linux/err.h>
17 #include <linux/scatterlist.h>
18 #include <keys/user-type.h>
19 #include <keys/big_key-type.h>
20 #include <crypto/rng.h>
21 
22 /*
23  * Layout of key payload words.
24  */
25 enum {
26 	big_key_data,
27 	big_key_path,
28 	big_key_path_2nd_part,
29 	big_key_len,
30 };
31 
32 /*
33  * Crypto operation with big_key data
34  */
35 enum big_key_op {
36 	BIG_KEY_ENC,
37 	BIG_KEY_DEC,
38 };
39 
40 /*
41  * If the data is under this limit, there's no point creating a shm file to
42  * hold it as the permanently resident metadata for the shmem fs will be at
43  * least as large as the data.
44  */
45 #define BIG_KEY_FILE_THRESHOLD (sizeof(struct inode) + sizeof(struct dentry))
46 
47 /*
48  * Key size for big_key data encryption
49  */
50 #define ENC_KEY_SIZE	16
51 
52 /*
53  * big_key defined keys take an arbitrary string as the description and an
54  * arbitrary blob of data as the payload
55  */
56 struct key_type key_type_big_key = {
57 	.name			= "big_key",
58 	.preparse		= big_key_preparse,
59 	.free_preparse		= big_key_free_preparse,
60 	.instantiate		= generic_key_instantiate,
61 	.revoke			= big_key_revoke,
62 	.destroy		= big_key_destroy,
63 	.describe		= big_key_describe,
64 	.read			= big_key_read,
65 };
66 
67 /*
68  * Crypto names for big_key data encryption
69  */
70 static const char big_key_rng_name[] = "stdrng";
71 static const char big_key_alg_name[] = "ecb(aes)";
72 
73 /*
74  * Crypto algorithms for big_key data encryption
75  */
76 static struct crypto_rng *big_key_rng;
77 static struct crypto_blkcipher *big_key_blkcipher;
78 
79 /*
80  * Generate random key to encrypt big_key data
81  */
82 static inline int big_key_gen_enckey(u8 *key)
83 {
84 	return crypto_rng_get_bytes(big_key_rng, key, ENC_KEY_SIZE);
85 }
86 
87 /*
88  * Encrypt/decrypt big_key data
89  */
90 static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key)
91 {
92 	int ret = -EINVAL;
93 	struct scatterlist sgio;
94 	struct blkcipher_desc desc;
95 
96 	if (crypto_blkcipher_setkey(big_key_blkcipher, key, ENC_KEY_SIZE)) {
97 		ret = -EAGAIN;
98 		goto error;
99 	}
100 
101 	desc.flags = 0;
102 	desc.tfm = big_key_blkcipher;
103 
104 	sg_init_one(&sgio, data, datalen);
105 
106 	if (op == BIG_KEY_ENC)
107 		ret = crypto_blkcipher_encrypt(&desc, &sgio, &sgio, datalen);
108 	else
109 		ret = crypto_blkcipher_decrypt(&desc, &sgio, &sgio, datalen);
110 
111 error:
112 	return ret;
113 }
114 
115 /*
116  * Preparse a big key
117  */
118 int big_key_preparse(struct key_preparsed_payload *prep)
119 {
120 	struct path *path = (struct path *)&prep->payload.data[big_key_path];
121 	struct file *file;
122 	u8 *enckey;
123 	u8 *data = NULL;
124 	ssize_t written;
125 	size_t datalen = prep->datalen;
126 	int ret;
127 
128 	ret = -EINVAL;
129 	if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data)
130 		goto error;
131 
132 	/* Set an arbitrary quota */
133 	prep->quotalen = 16;
134 
135 	prep->payload.data[big_key_len] = (void *)(unsigned long)datalen;
136 
137 	if (datalen > BIG_KEY_FILE_THRESHOLD) {
138 		/* Create a shmem file to store the data in.  This will permit the data
139 		 * to be swapped out if needed.
140 		 *
141 		 * File content is stored encrypted with randomly generated key.
142 		 */
143 		size_t enclen = ALIGN(datalen, crypto_blkcipher_blocksize(big_key_blkcipher));
144 
145 		/* prepare aligned data to encrypt */
146 		data = kmalloc(enclen, GFP_KERNEL);
147 		if (!data)
148 			return -ENOMEM;
149 
150 		memcpy(data, prep->data, datalen);
151 		memset(data + datalen, 0x00, enclen - datalen);
152 
153 		/* generate random key */
154 		enckey = kmalloc(ENC_KEY_SIZE, GFP_KERNEL);
155 		if (!enckey) {
156 			ret = -ENOMEM;
157 			goto error;
158 		}
159 
160 		ret = big_key_gen_enckey(enckey);
161 		if (ret)
162 			goto err_enckey;
163 
164 		/* encrypt aligned data */
165 		ret = big_key_crypt(BIG_KEY_ENC, data, enclen, enckey);
166 		if (ret)
167 			goto err_enckey;
168 
169 		/* save aligned data to file */
170 		file = shmem_kernel_file_setup("", enclen, 0);
171 		if (IS_ERR(file)) {
172 			ret = PTR_ERR(file);
173 			goto err_enckey;
174 		}
175 
176 		written = kernel_write(file, data, enclen, 0);
177 		if (written != enclen) {
178 			ret = written;
179 			if (written >= 0)
180 				ret = -ENOMEM;
181 			goto err_fput;
182 		}
183 
184 		/* Pin the mount and dentry to the key so that we can open it again
185 		 * later
186 		 */
187 		prep->payload.data[big_key_data] = enckey;
188 		*path = file->f_path;
189 		path_get(path);
190 		fput(file);
191 		kfree(data);
192 	} else {
193 		/* Just store the data in a buffer */
194 		void *data = kmalloc(datalen, GFP_KERNEL);
195 
196 		if (!data)
197 			return -ENOMEM;
198 
199 		prep->payload.data[big_key_data] = data;
200 		memcpy(data, prep->data, prep->datalen);
201 	}
202 	return 0;
203 
204 err_fput:
205 	fput(file);
206 err_enckey:
207 	kfree(enckey);
208 error:
209 	kfree(data);
210 	return ret;
211 }
212 
213 /*
214  * Clear preparsement.
215  */
216 void big_key_free_preparse(struct key_preparsed_payload *prep)
217 {
218 	if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
219 		struct path *path = (struct path *)&prep->payload.data[big_key_path];
220 
221 		path_put(path);
222 	}
223 	kfree(prep->payload.data[big_key_data]);
224 }
225 
226 /*
227  * dispose of the links from a revoked keyring
228  * - called with the key sem write-locked
229  */
230 void big_key_revoke(struct key *key)
231 {
232 	struct path *path = (struct path *)&key->payload.data[big_key_path];
233 
234 	/* clear the quota */
235 	key_payload_reserve(key, 0);
236 	if (key_is_instantiated(key) &&
237 	    (size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD)
238 		vfs_truncate(path, 0);
239 }
240 
241 /*
242  * dispose of the data dangling from the corpse of a big_key key
243  */
244 void big_key_destroy(struct key *key)
245 {
246 	size_t datalen = (size_t)key->payload.data[big_key_len];
247 
248 	if (datalen > BIG_KEY_FILE_THRESHOLD) {
249 		struct path *path = (struct path *)&key->payload.data[big_key_path];
250 
251 		path_put(path);
252 		path->mnt = NULL;
253 		path->dentry = NULL;
254 	}
255 	kfree(key->payload.data[big_key_data]);
256 	key->payload.data[big_key_data] = NULL;
257 }
258 
259 /*
260  * describe the big_key key
261  */
262 void big_key_describe(const struct key *key, struct seq_file *m)
263 {
264 	size_t datalen = (size_t)key->payload.data[big_key_len];
265 
266 	seq_puts(m, key->description);
267 
268 	if (key_is_instantiated(key))
269 		seq_printf(m, ": %zu [%s]",
270 			   datalen,
271 			   datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff");
272 }
273 
274 /*
275  * read the key data
276  * - the key's semaphore is read-locked
277  */
278 long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
279 {
280 	size_t datalen = (size_t)key->payload.data[big_key_len];
281 	long ret;
282 
283 	if (!buffer || buflen < datalen)
284 		return datalen;
285 
286 	if (datalen > BIG_KEY_FILE_THRESHOLD) {
287 		struct path *path = (struct path *)&key->payload.data[big_key_path];
288 		struct file *file;
289 		u8 *data;
290 		u8 *enckey = (u8 *)key->payload.data[big_key_data];
291 		size_t enclen = ALIGN(datalen, crypto_blkcipher_blocksize(big_key_blkcipher));
292 
293 		data = kmalloc(enclen, GFP_KERNEL);
294 		if (!data)
295 			return -ENOMEM;
296 
297 		file = dentry_open(path, O_RDONLY, current_cred());
298 		if (IS_ERR(file)) {
299 			ret = PTR_ERR(file);
300 			goto error;
301 		}
302 
303 		/* read file to kernel and decrypt */
304 		ret = kernel_read(file, 0, data, enclen);
305 		if (ret >= 0 && ret != enclen) {
306 			ret = -EIO;
307 			goto err_fput;
308 		}
309 
310 		ret = big_key_crypt(BIG_KEY_DEC, data, enclen, enckey);
311 		if (ret)
312 			goto err_fput;
313 
314 		ret = datalen;
315 
316 		/* copy decrypted data to user */
317 		if (copy_to_user(buffer, data, datalen) != 0)
318 			ret = -EFAULT;
319 
320 err_fput:
321 		fput(file);
322 error:
323 		kfree(data);
324 	} else {
325 		ret = datalen;
326 		if (copy_to_user(buffer, key->payload.data[big_key_data],
327 				 datalen) != 0)
328 			ret = -EFAULT;
329 	}
330 
331 	return ret;
332 }
333 
334 /*
335  * Register key type
336  */
337 static int __init big_key_init(void)
338 {
339 	return register_key_type(&key_type_big_key);
340 }
341 
342 /*
343  * Initialize big_key crypto and RNG algorithms
344  */
345 static int __init big_key_crypto_init(void)
346 {
347 	int ret = -EINVAL;
348 
349 	/* init RNG */
350 	big_key_rng = crypto_alloc_rng(big_key_rng_name, 0, 0);
351 	if (IS_ERR(big_key_rng)) {
352 		big_key_rng = NULL;
353 		return -EFAULT;
354 	}
355 
356 	/* seed RNG */
357 	ret = crypto_rng_reset(big_key_rng, NULL, crypto_rng_seedsize(big_key_rng));
358 	if (ret)
359 		goto error;
360 
361 	/* init block cipher */
362 	big_key_blkcipher = crypto_alloc_blkcipher(big_key_alg_name, 0, 0);
363 	if (IS_ERR(big_key_blkcipher)) {
364 		big_key_blkcipher = NULL;
365 		ret = -EFAULT;
366 		goto error;
367 	}
368 
369 	return 0;
370 
371 error:
372 	crypto_free_rng(big_key_rng);
373 	big_key_rng = NULL;
374 	return ret;
375 }
376 
377 device_initcall(big_key_init);
378 late_initcall(big_key_crypto_init);
379