9e443fccad4cfde54deb9710feb4eee4bdadae17
[cascardo/linux.git] / security / keys / big_key.c
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);