14
14
#include <linux/file.h>
15
15
#include <linux/shmem_fs.h>
16
16
#include <linux/err.h>
17
+ #include <linux/scatterlist.h>
17
18
#include <keys/user-type.h>
18
19
#include <keys/big_key-type.h>
20
+ #include <crypto/rng.h>
19
21
20
22
/*
21
23
* Layout of key payload words.
@@ -27,13 +29,26 @@ enum {
27
29
big_key_len ,
28
30
};
29
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
+
30
40
/*
31
41
* If the data is under this limit, there's no point creating a shm file to
32
42
* hold it as the permanently resident metadata for the shmem fs will be at
33
43
* least as large as the data.
34
44
*/
35
45
#define BIG_KEY_FILE_THRESHOLD (sizeof(struct inode) + sizeof(struct dentry))
36
46
47
+ /*
48
+ * Key size for big_key data encryption
49
+ */
50
+ #define ENC_KEY_SIZE 16
51
+
37
52
/*
38
53
* big_key defined keys take an arbitrary string as the description and an
39
54
* arbitrary blob of data as the payload
@@ -49,13 +64,63 @@ struct key_type key_type_big_key = {
49
64
.read = big_key_read ,
50
65
};
51
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
+
52
115
/*
53
116
* Preparse a big key
54
117
*/
55
118
int big_key_preparse (struct key_preparsed_payload * prep )
56
119
{
57
120
struct path * path = (struct path * )& prep -> payload .data [big_key_path ];
58
121
struct file * file ;
122
+ u8 * enckey ;
123
+ u8 * data = NULL ;
59
124
ssize_t written ;
60
125
size_t datalen = prep -> datalen ;
61
126
int ret ;
@@ -73,16 +138,43 @@ int big_key_preparse(struct key_preparsed_payload *prep)
73
138
/* Create a shmem file to store the data in. This will permit the data
74
139
* to be swapped out if needed.
75
140
*
76
- * TODO: Encrypt the stored data with a temporary key.
141
+ * File content is stored encrypted with randomly generated key.
77
142
*/
78
- file = shmem_kernel_file_setup ("" , datalen , 0 );
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 );
79
171
if (IS_ERR (file )) {
80
172
ret = PTR_ERR (file );
81
- goto error ;
173
+ goto err_enckey ;
82
174
}
83
175
84
- written = kernel_write (file , prep -> data , prep -> datalen , 0 );
85
- if (written != datalen ) {
176
+ written = kernel_write (file , data , enclen , 0 );
177
+ if (written != enclen ) {
86
178
ret = written ;
87
179
if (written >= 0 )
88
180
ret = - ENOMEM ;
@@ -92,12 +184,15 @@ int big_key_preparse(struct key_preparsed_payload *prep)
92
184
/* Pin the mount and dentry to the key so that we can open it again
93
185
* later
94
186
*/
187
+ prep -> payload .data [big_key_data ] = enckey ;
95
188
* path = file -> f_path ;
96
189
path_get (path );
97
190
fput (file );
191
+ kfree (data );
98
192
} else {
99
193
/* Just store the data in a buffer */
100
194
void * data = kmalloc (datalen , GFP_KERNEL );
195
+
101
196
if (!data )
102
197
return - ENOMEM ;
103
198
@@ -108,7 +203,10 @@ int big_key_preparse(struct key_preparsed_payload *prep)
108
203
109
204
err_fput :
110
205
fput (file );
206
+ err_enckey :
207
+ kfree (enckey );
111
208
error :
209
+ kfree (data );
112
210
return ret ;
113
211
}
114
212
@@ -119,10 +217,10 @@ void big_key_free_preparse(struct key_preparsed_payload *prep)
119
217
{
120
218
if (prep -> datalen > BIG_KEY_FILE_THRESHOLD ) {
121
219
struct path * path = (struct path * )& prep -> payload .data [big_key_path ];
220
+
122
221
path_put (path );
123
- } else {
124
- kfree (prep -> payload .data [big_key_data ]);
125
222
}
223
+ kfree (prep -> payload .data [big_key_data ]);
126
224
}
127
225
128
226
/*
@@ -147,15 +245,15 @@ void big_key_destroy(struct key *key)
147
245
{
148
246
size_t datalen = (size_t )key -> payload .data [big_key_len ];
149
247
150
- if (datalen ) {
248
+ if (datalen > BIG_KEY_FILE_THRESHOLD ) {
151
249
struct path * path = (struct path * )& key -> payload .data [big_key_path ];
250
+
152
251
path_put (path );
153
252
path -> mnt = NULL ;
154
253
path -> dentry = NULL ;
155
- } else {
156
- kfree (key -> payload .data [big_key_data ]);
157
- key -> payload .data [big_key_data ] = NULL ;
158
254
}
255
+ kfree (key -> payload .data [big_key_data ]);
256
+ key -> payload .data [big_key_data ] = NULL ;
159
257
}
160
258
161
259
/*
@@ -188,17 +286,41 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
188
286
if (datalen > BIG_KEY_FILE_THRESHOLD ) {
189
287
struct path * path = (struct path * )& key -> payload .data [big_key_path ];
190
288
struct file * file ;
191
- loff_t pos ;
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 ;
192
296
193
297
file = dentry_open (path , O_RDONLY , current_cred ());
194
- if (IS_ERR (file ))
195
- return PTR_ERR (file );
298
+ if (IS_ERR (file )) {
299
+ ret = PTR_ERR (file );
300
+ goto error ;
301
+ }
196
302
197
- pos = 0 ;
198
- ret = vfs_read (file , buffer , datalen , & pos );
199
- fput (file );
200
- if (ret >= 0 && ret != datalen )
303
+ /* read file to kernel and decrypt */
304
+ ret = kernel_read (file , 0 , data , enclen );
305
+ if (ret >= 0 && ret != enclen ) {
201
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 );
202
324
} else {
203
325
ret = datalen ;
204
326
if (copy_to_user (buffer , key -> payload .data [big_key_data ],
@@ -209,8 +331,48 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
209
331
return ret ;
210
332
}
211
333
334
+ /*
335
+ * Register key type
336
+ */
212
337
static int __init big_key_init (void )
213
338
{
214
339
return register_key_type (& key_type_big_key );
215
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
+
216
377
device_initcall (big_key_init );
378
+ late_initcall (big_key_crypto_init );
0 commit comments