22
22
#include <keys/big_key-type.h>
23
23
#include <crypto/aead.h>
24
24
25
+ struct big_key_buf {
26
+ unsigned int nr_pages ;
27
+ void * virt ;
28
+ struct scatterlist * sg ;
29
+ struct page * pages [];
30
+ };
31
+
25
32
/*
26
33
* Layout of key payload words.
27
34
*/
@@ -91,10 +98,9 @@ static DEFINE_MUTEX(big_key_aead_lock);
91
98
/*
92
99
* Encrypt/decrypt big_key data
93
100
*/
94
- static int big_key_crypt (enum big_key_op op , u8 * data , size_t datalen , u8 * key )
101
+ static int big_key_crypt (enum big_key_op op , struct big_key_buf * buf , size_t datalen , u8 * key )
95
102
{
96
103
int ret ;
97
- struct scatterlist sgio ;
98
104
struct aead_request * aead_req ;
99
105
/* We always use a zero nonce. The reason we can get away with this is
100
106
* because we're using a different randomly generated key for every
@@ -109,8 +115,7 @@ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key)
109
115
return - ENOMEM ;
110
116
111
117
memset (zero_nonce , 0 , sizeof (zero_nonce ));
112
- sg_init_one (& sgio , data , datalen + (op == BIG_KEY_ENC ? ENC_AUTHTAG_SIZE : 0 ));
113
- aead_request_set_crypt (aead_req , & sgio , & sgio , datalen , zero_nonce );
118
+ aead_request_set_crypt (aead_req , buf -> sg , buf -> sg , datalen , zero_nonce );
114
119
aead_request_set_callback (aead_req , CRYPTO_TFM_REQ_MAY_SLEEP , NULL , NULL );
115
120
aead_request_set_ad (aead_req , 0 );
116
121
@@ -129,22 +134,82 @@ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key)
129
134
return ret ;
130
135
}
131
136
137
+ /*
138
+ * Free up the buffer.
139
+ */
140
+ static void big_key_free_buffer (struct big_key_buf * buf )
141
+ {
142
+ unsigned int i ;
143
+
144
+ if (buf -> virt ) {
145
+ memset (buf -> virt , 0 , buf -> nr_pages * PAGE_SIZE );
146
+ vunmap (buf -> virt );
147
+ }
148
+
149
+ for (i = 0 ; i < buf -> nr_pages ; i ++ )
150
+ if (buf -> pages [i ])
151
+ __free_page (buf -> pages [i ]);
152
+
153
+ kfree (buf );
154
+ }
155
+
156
+ /*
157
+ * Allocate a buffer consisting of a set of pages with a virtual mapping
158
+ * applied over them.
159
+ */
160
+ static void * big_key_alloc_buffer (size_t len )
161
+ {
162
+ struct big_key_buf * buf ;
163
+ unsigned int npg = (len + PAGE_SIZE - 1 ) >> PAGE_SHIFT ;
164
+ unsigned int i , l ;
165
+
166
+ buf = kzalloc (sizeof (struct big_key_buf ) +
167
+ sizeof (struct page ) * npg +
168
+ sizeof (struct scatterlist ) * npg ,
169
+ GFP_KERNEL );
170
+ if (!buf )
171
+ return NULL ;
172
+
173
+ buf -> nr_pages = npg ;
174
+ buf -> sg = (void * )(buf -> pages + npg );
175
+ sg_init_table (buf -> sg , npg );
176
+
177
+ for (i = 0 ; i < buf -> nr_pages ; i ++ ) {
178
+ buf -> pages [i ] = alloc_page (GFP_KERNEL );
179
+ if (!buf -> pages [i ])
180
+ goto nomem ;
181
+
182
+ l = min_t (size_t , len , PAGE_SIZE );
183
+ sg_set_page (& buf -> sg [i ], buf -> pages [i ], l , 0 );
184
+ len -= l ;
185
+ }
186
+
187
+ buf -> virt = vmap (buf -> pages , buf -> nr_pages , VM_MAP , PAGE_KERNEL );
188
+ if (!buf -> virt )
189
+ goto nomem ;
190
+
191
+ return buf ;
192
+
193
+ nomem :
194
+ big_key_free_buffer (buf );
195
+ return NULL ;
196
+ }
197
+
132
198
/*
133
199
* Preparse a big key
134
200
*/
135
201
int big_key_preparse (struct key_preparsed_payload * prep )
136
202
{
203
+ struct big_key_buf * buf ;
137
204
struct path * path = (struct path * )& prep -> payload .data [big_key_path ];
138
205
struct file * file ;
139
206
u8 * enckey ;
140
- u8 * data = NULL ;
141
207
ssize_t written ;
142
- size_t datalen = prep -> datalen ;
208
+ size_t datalen = prep -> datalen , enclen = datalen + ENC_AUTHTAG_SIZE ;
143
209
int ret ;
144
210
145
- ret = - EINVAL ;
146
211
if (datalen <= 0 || datalen > 1024 * 1024 || !prep -> data )
147
- goto error ;
212
+ return - EINVAL ;
148
213
149
214
/* Set an arbitrary quota */
150
215
prep -> quotalen = 16 ;
@@ -157,13 +222,12 @@ int big_key_preparse(struct key_preparsed_payload *prep)
157
222
*
158
223
* File content is stored encrypted with randomly generated key.
159
224
*/
160
- size_t enclen = datalen + ENC_AUTHTAG_SIZE ;
161
225
loff_t pos = 0 ;
162
226
163
- data = kmalloc (enclen , GFP_KERNEL );
164
- if (!data )
227
+ buf = big_key_alloc_buffer (enclen );
228
+ if (!buf )
165
229
return - ENOMEM ;
166
- memcpy (data , prep -> data , datalen );
230
+ memcpy (buf -> virt , prep -> data , datalen );
167
231
168
232
/* generate random key */
169
233
enckey = kmalloc (ENC_KEY_SIZE , GFP_KERNEL );
@@ -176,7 +240,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
176
240
goto err_enckey ;
177
241
178
242
/* encrypt aligned data */
179
- ret = big_key_crypt (BIG_KEY_ENC , data , datalen , enckey );
243
+ ret = big_key_crypt (BIG_KEY_ENC , buf , datalen , enckey );
180
244
if (ret )
181
245
goto err_enckey ;
182
246
@@ -187,7 +251,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
187
251
goto err_enckey ;
188
252
}
189
253
190
- written = kernel_write (file , data , enclen , & pos );
254
+ written = kernel_write (file , buf -> virt , enclen , & pos );
191
255
if (written != enclen ) {
192
256
ret = written ;
193
257
if (written >= 0 )
@@ -202,7 +266,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
202
266
* path = file -> f_path ;
203
267
path_get (path );
204
268
fput (file );
205
- kzfree ( data );
269
+ big_key_free_buffer ( buf );
206
270
} else {
207
271
/* Just store the data in a buffer */
208
272
void * data = kmalloc (datalen , GFP_KERNEL );
@@ -220,7 +284,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
220
284
err_enckey :
221
285
kzfree (enckey );
222
286
error :
223
- kzfree ( data );
287
+ big_key_free_buffer ( buf );
224
288
return ret ;
225
289
}
226
290
@@ -298,15 +362,15 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
298
362
return datalen ;
299
363
300
364
if (datalen > BIG_KEY_FILE_THRESHOLD ) {
365
+ struct big_key_buf * buf ;
301
366
struct path * path = (struct path * )& key -> payload .data [big_key_path ];
302
367
struct file * file ;
303
- u8 * data ;
304
368
u8 * enckey = (u8 * )key -> payload .data [big_key_data ];
305
369
size_t enclen = datalen + ENC_AUTHTAG_SIZE ;
306
370
loff_t pos = 0 ;
307
371
308
- data = kmalloc (enclen , GFP_KERNEL );
309
- if (!data )
372
+ buf = big_key_alloc_buffer (enclen );
373
+ if (!buf )
310
374
return - ENOMEM ;
311
375
312
376
file = dentry_open (path , O_RDONLY , current_cred ());
@@ -316,26 +380,26 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
316
380
}
317
381
318
382
/* read file to kernel and decrypt */
319
- ret = kernel_read (file , data , enclen , & pos );
383
+ ret = kernel_read (file , buf -> virt , enclen , & pos );
320
384
if (ret >= 0 && ret != enclen ) {
321
385
ret = - EIO ;
322
386
goto err_fput ;
323
387
}
324
388
325
- ret = big_key_crypt (BIG_KEY_DEC , data , enclen , enckey );
389
+ ret = big_key_crypt (BIG_KEY_DEC , buf , enclen , enckey );
326
390
if (ret )
327
391
goto err_fput ;
328
392
329
393
ret = datalen ;
330
394
331
395
/* copy decrypted data to user */
332
- if (copy_to_user (buffer , data , datalen ) != 0 )
396
+ if (copy_to_user (buffer , buf -> virt , datalen ) != 0 )
333
397
ret = - EFAULT ;
334
398
335
399
err_fput :
336
400
fput (file );
337
401
error :
338
- kzfree ( data );
402
+ big_key_free_buffer ( buf );
339
403
} else {
340
404
ret = datalen ;
341
405
if (copy_to_user (buffer , key -> payload .data [big_key_data ],
0 commit comments