Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
0adda907 | 2 | /* |
0b81d077 | 3 | * key management facility for FS encryption support. |
0adda907 JK |
4 | * |
5 | * Copyright (C) 2015, Google, Inc. | |
6 | * | |
0b81d077 | 7 | * This contains encryption key functions. |
0adda907 JK |
8 | * |
9 | * Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015. | |
10 | */ | |
0b81d077 | 11 | |
0adda907 | 12 | #include <keys/user-type.h> |
8094c3ce | 13 | #include <linux/hashtable.h> |
0adda907 | 14 | #include <linux/scatterlist.h> |
b7e7cf7a DW |
15 | #include <linux/ratelimit.h> |
16 | #include <crypto/aes.h> | |
8094c3ce | 17 | #include <crypto/algapi.h> |
b7e7cf7a | 18 | #include <crypto/sha.h> |
a575784c | 19 | #include <crypto/skcipher.h> |
3325bea5 | 20 | #include "fscrypt_private.h" |
0adda907 | 21 | |
b7e7cf7a DW |
22 | static struct crypto_shash *essiv_hash_tfm; |
23 | ||
8094c3ce EB |
24 | /* Table of keys referenced by FS_POLICY_FLAG_DIRECT_KEY policies */ |
25 | static DEFINE_HASHTABLE(fscrypt_master_keys, 6); /* 6 bits = 64 buckets */ | |
26 | static DEFINE_SPINLOCK(fscrypt_master_keys_lock); | |
27 | ||
646b7d4f EB |
28 | /* |
29 | * Key derivation function. This generates the derived key by encrypting the | |
30 | * master key with AES-128-ECB using the inode's nonce as the AES key. | |
0adda907 | 31 | * |
646b7d4f EB |
32 | * The master key must be at least as long as the derived key. If the master |
33 | * key is longer, then only the first 'derived_keysize' bytes are used. | |
0adda907 | 34 | */ |
646b7d4f EB |
35 | static int derive_key_aes(const u8 *master_key, |
36 | const struct fscrypt_context *ctx, | |
37 | u8 *derived_key, unsigned int derived_keysize) | |
0adda907 JK |
38 | { |
39 | int res = 0; | |
d407574e | 40 | struct skcipher_request *req = NULL; |
d0082e1a | 41 | DECLARE_CRYPTO_WAIT(wait); |
0adda907 | 42 | struct scatterlist src_sg, dst_sg; |
d407574e | 43 | struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0); |
0adda907 JK |
44 | |
45 | if (IS_ERR(tfm)) { | |
46 | res = PTR_ERR(tfm); | |
47 | tfm = NULL; | |
48 | goto out; | |
49 | } | |
231baecd | 50 | crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); |
d407574e | 51 | req = skcipher_request_alloc(tfm, GFP_NOFS); |
0adda907 JK |
52 | if (!req) { |
53 | res = -ENOMEM; | |
54 | goto out; | |
55 | } | |
d407574e | 56 | skcipher_request_set_callback(req, |
0adda907 | 57 | CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, |
d0082e1a | 58 | crypto_req_done, &wait); |
646b7d4f | 59 | res = crypto_skcipher_setkey(tfm, ctx->nonce, sizeof(ctx->nonce)); |
0adda907 JK |
60 | if (res < 0) |
61 | goto out; | |
62 | ||
646b7d4f EB |
63 | sg_init_one(&src_sg, master_key, derived_keysize); |
64 | sg_init_one(&dst_sg, derived_key, derived_keysize); | |
65 | skcipher_request_set_crypt(req, &src_sg, &dst_sg, derived_keysize, | |
b7e7cf7a | 66 | NULL); |
d0082e1a | 67 | res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); |
0adda907 | 68 | out: |
d407574e LT |
69 | skcipher_request_free(req); |
70 | crypto_free_skcipher(tfm); | |
0adda907 JK |
71 | return res; |
72 | } | |
73 | ||
590f497d EB |
74 | /* |
75 | * Search the current task's subscribed keyrings for a "logon" key with | |
76 | * description prefix:descriptor, and if found acquire a read lock on it and | |
77 | * return a pointer to its validated payload in *payload_ret. | |
78 | */ | |
79 | static struct key * | |
80 | find_and_lock_process_key(const char *prefix, | |
81 | const u8 descriptor[FS_KEY_DESCRIPTOR_SIZE], | |
82 | unsigned int min_keysize, | |
83 | const struct fscrypt_key **payload_ret) | |
b5a7aef1 | 84 | { |
a5d431ef | 85 | char *description; |
590f497d | 86 | struct key *key; |
b5a7aef1 | 87 | const struct user_key_payload *ukp; |
590f497d | 88 | const struct fscrypt_key *payload; |
b5a7aef1 | 89 | |
a5d431ef | 90 | description = kasprintf(GFP_NOFS, "%s%*phN", prefix, |
590f497d | 91 | FS_KEY_DESCRIPTOR_SIZE, descriptor); |
a5d431ef | 92 | if (!description) |
590f497d | 93 | return ERR_PTR(-ENOMEM); |
b5a7aef1 | 94 | |
590f497d | 95 | key = request_key(&key_type_logon, description, NULL); |
a5d431ef | 96 | kfree(description); |
590f497d EB |
97 | if (IS_ERR(key)) |
98 | return key; | |
99 | ||
100 | down_read(&key->sem); | |
101 | ukp = user_key_payload_locked(key); | |
102 | ||
103 | if (!ukp) /* was the key revoked before we acquired its semaphore? */ | |
104 | goto invalid; | |
105 | ||
106 | payload = (const struct fscrypt_key *)ukp->data; | |
107 | ||
108 | if (ukp->datalen != sizeof(struct fscrypt_key) || | |
109 | payload->size < 1 || payload->size > FS_MAX_KEY_SIZE) { | |
110 | fscrypt_warn(NULL, | |
111 | "key with description '%s' has invalid payload", | |
112 | key->description); | |
113 | goto invalid; | |
d60b5b78 | 114 | } |
590f497d | 115 | |
646b7d4f | 116 | if (payload->size < min_keysize) { |
590f497d | 117 | fscrypt_warn(NULL, |
646b7d4f | 118 | "key with description '%s' is too short (got %u bytes, need %u+ bytes)", |
590f497d EB |
119 | key->description, payload->size, min_keysize); |
120 | goto invalid; | |
b5a7aef1 | 121 | } |
b5a7aef1 | 122 | |
590f497d EB |
123 | *payload_ret = payload; |
124 | return key; | |
125 | ||
126 | invalid: | |
127 | up_read(&key->sem); | |
128 | key_put(key); | |
129 | return ERR_PTR(-ENOKEY); | |
130 | } | |
131 | ||
8094c3ce | 132 | static struct fscrypt_mode available_modes[] = { |
e1cc40e5 EB |
133 | [FS_ENCRYPTION_MODE_AES_256_XTS] = { |
134 | .friendly_name = "AES-256-XTS", | |
135 | .cipher_str = "xts(aes)", | |
136 | .keysize = 64, | |
8094c3ce | 137 | .ivsize = 16, |
e1cc40e5 EB |
138 | }, |
139 | [FS_ENCRYPTION_MODE_AES_256_CTS] = { | |
140 | .friendly_name = "AES-256-CTS-CBC", | |
141 | .cipher_str = "cts(cbc(aes))", | |
142 | .keysize = 32, | |
8094c3ce | 143 | .ivsize = 16, |
e1cc40e5 EB |
144 | }, |
145 | [FS_ENCRYPTION_MODE_AES_128_CBC] = { | |
146 | .friendly_name = "AES-128-CBC", | |
147 | .cipher_str = "cbc(aes)", | |
148 | .keysize = 16, | |
8094c3ce EB |
149 | .ivsize = 16, |
150 | .needs_essiv = true, | |
e1cc40e5 EB |
151 | }, |
152 | [FS_ENCRYPTION_MODE_AES_128_CTS] = { | |
153 | .friendly_name = "AES-128-CTS-CBC", | |
154 | .cipher_str = "cts(cbc(aes))", | |
155 | .keysize = 16, | |
8094c3ce EB |
156 | .ivsize = 16, |
157 | }, | |
158 | [FS_ENCRYPTION_MODE_ADIANTUM] = { | |
159 | .friendly_name = "Adiantum", | |
160 | .cipher_str = "adiantum(xchacha12,aes)", | |
161 | .keysize = 32, | |
162 | .ivsize = 32, | |
e1cc40e5 | 163 | }, |
b7e7cf7a DW |
164 | }; |
165 | ||
e1cc40e5 EB |
166 | static struct fscrypt_mode * |
167 | select_encryption_mode(const struct fscrypt_info *ci, const struct inode *inode) | |
8f39850d | 168 | { |
b7e7cf7a | 169 | if (!fscrypt_valid_enc_modes(ci->ci_data_mode, ci->ci_filename_mode)) { |
544d08fd EB |
170 | fscrypt_warn(inode->i_sb, |
171 | "inode %lu uses unsupported encryption modes (contents mode %d, filenames mode %d)", | |
172 | inode->i_ino, ci->ci_data_mode, | |
173 | ci->ci_filename_mode); | |
e1cc40e5 | 174 | return ERR_PTR(-EINVAL); |
8f39850d EB |
175 | } |
176 | ||
e1cc40e5 EB |
177 | if (S_ISREG(inode->i_mode)) |
178 | return &available_modes[ci->ci_data_mode]; | |
179 | ||
180 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | |
181 | return &available_modes[ci->ci_filename_mode]; | |
8f39850d | 182 | |
e1cc40e5 EB |
183 | WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %lu, which is not encryptable (file type %d)\n", |
184 | inode->i_ino, (inode->i_mode & S_IFMT)); | |
185 | return ERR_PTR(-EINVAL); | |
8f39850d EB |
186 | } |
187 | ||
8094c3ce EB |
188 | /* Find the master key, then derive the inode's actual encryption key */ |
189 | static int find_and_derive_key(const struct inode *inode, | |
190 | const struct fscrypt_context *ctx, | |
191 | u8 *derived_key, const struct fscrypt_mode *mode) | |
0adda907 | 192 | { |
8094c3ce EB |
193 | struct key *key; |
194 | const struct fscrypt_key *payload; | |
195 | int err; | |
196 | ||
197 | key = find_and_lock_process_key(FS_KEY_DESC_PREFIX, | |
198 | ctx->master_key_descriptor, | |
199 | mode->keysize, &payload); | |
200 | if (key == ERR_PTR(-ENOKEY) && inode->i_sb->s_cop->key_prefix) { | |
201 | key = find_and_lock_process_key(inode->i_sb->s_cop->key_prefix, | |
202 | ctx->master_key_descriptor, | |
203 | mode->keysize, &payload); | |
204 | } | |
205 | if (IS_ERR(key)) | |
206 | return PTR_ERR(key); | |
207 | ||
208 | if (ctx->flags & FS_POLICY_FLAG_DIRECT_KEY) { | |
209 | if (mode->ivsize < offsetofend(union fscrypt_iv, nonce)) { | |
210 | fscrypt_warn(inode->i_sb, | |
211 | "direct key mode not allowed with %s", | |
212 | mode->friendly_name); | |
213 | err = -EINVAL; | |
214 | } else if (ctx->contents_encryption_mode != | |
215 | ctx->filenames_encryption_mode) { | |
216 | fscrypt_warn(inode->i_sb, | |
217 | "direct key mode not allowed with different contents and filenames modes"); | |
218 | err = -EINVAL; | |
219 | } else { | |
220 | memcpy(derived_key, payload->raw, mode->keysize); | |
221 | err = 0; | |
222 | } | |
223 | } else { | |
224 | err = derive_key_aes(payload->raw, ctx, derived_key, | |
225 | mode->keysize); | |
226 | } | |
227 | up_read(&key->sem); | |
228 | key_put(key); | |
229 | return err; | |
230 | } | |
231 | ||
232 | /* Allocate and key a symmetric cipher object for the given encryption mode */ | |
233 | static struct crypto_skcipher * | |
234 | allocate_skcipher_for_mode(struct fscrypt_mode *mode, const u8 *raw_key, | |
235 | const struct inode *inode) | |
236 | { | |
237 | struct crypto_skcipher *tfm; | |
238 | int err; | |
239 | ||
240 | tfm = crypto_alloc_skcipher(mode->cipher_str, 0, 0); | |
241 | if (IS_ERR(tfm)) { | |
242 | fscrypt_warn(inode->i_sb, | |
243 | "error allocating '%s' transform for inode %lu: %ld", | |
244 | mode->cipher_str, inode->i_ino, PTR_ERR(tfm)); | |
245 | return tfm; | |
246 | } | |
247 | if (unlikely(!mode->logged_impl_name)) { | |
248 | /* | |
249 | * fscrypt performance can vary greatly depending on which | |
250 | * crypto algorithm implementation is used. Help people debug | |
251 | * performance problems by logging the ->cra_driver_name the | |
252 | * first time a mode is used. Note that multiple threads can | |
253 | * race here, but it doesn't really matter. | |
254 | */ | |
255 | mode->logged_impl_name = true; | |
256 | pr_info("fscrypt: %s using implementation \"%s\"\n", | |
257 | mode->friendly_name, | |
258 | crypto_skcipher_alg(tfm)->base.cra_driver_name); | |
259 | } | |
231baecd | 260 | crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); |
8094c3ce EB |
261 | err = crypto_skcipher_setkey(tfm, raw_key, mode->keysize); |
262 | if (err) | |
263 | goto err_free_tfm; | |
264 | ||
265 | return tfm; | |
266 | ||
267 | err_free_tfm: | |
268 | crypto_free_skcipher(tfm); | |
269 | return ERR_PTR(err); | |
270 | } | |
271 | ||
272 | /* Master key referenced by FS_POLICY_FLAG_DIRECT_KEY policy */ | |
273 | struct fscrypt_master_key { | |
274 | struct hlist_node mk_node; | |
275 | refcount_t mk_refcount; | |
276 | const struct fscrypt_mode *mk_mode; | |
277 | struct crypto_skcipher *mk_ctfm; | |
278 | u8 mk_descriptor[FS_KEY_DESCRIPTOR_SIZE]; | |
279 | u8 mk_raw[FS_MAX_KEY_SIZE]; | |
280 | }; | |
281 | ||
282 | static void free_master_key(struct fscrypt_master_key *mk) | |
283 | { | |
284 | if (mk) { | |
285 | crypto_free_skcipher(mk->mk_ctfm); | |
286 | kzfree(mk); | |
287 | } | |
288 | } | |
289 | ||
290 | static void put_master_key(struct fscrypt_master_key *mk) | |
291 | { | |
292 | if (!refcount_dec_and_lock(&mk->mk_refcount, &fscrypt_master_keys_lock)) | |
0adda907 | 293 | return; |
8094c3ce EB |
294 | hash_del(&mk->mk_node); |
295 | spin_unlock(&fscrypt_master_keys_lock); | |
0adda907 | 296 | |
8094c3ce EB |
297 | free_master_key(mk); |
298 | } | |
299 | ||
300 | /* | |
301 | * Find/insert the given master key into the fscrypt_master_keys table. If | |
302 | * found, it is returned with elevated refcount, and 'to_insert' is freed if | |
303 | * non-NULL. If not found, 'to_insert' is inserted and returned if it's | |
304 | * non-NULL; otherwise NULL is returned. | |
305 | */ | |
306 | static struct fscrypt_master_key * | |
307 | find_or_insert_master_key(struct fscrypt_master_key *to_insert, | |
308 | const u8 *raw_key, const struct fscrypt_mode *mode, | |
309 | const struct fscrypt_info *ci) | |
310 | { | |
311 | unsigned long hash_key; | |
312 | struct fscrypt_master_key *mk; | |
313 | ||
314 | /* | |
315 | * Careful: to avoid potentially leaking secret key bytes via timing | |
316 | * information, we must key the hash table by descriptor rather than by | |
317 | * raw key, and use crypto_memneq() when comparing raw keys. | |
318 | */ | |
319 | ||
320 | BUILD_BUG_ON(sizeof(hash_key) > FS_KEY_DESCRIPTOR_SIZE); | |
321 | memcpy(&hash_key, ci->ci_master_key_descriptor, sizeof(hash_key)); | |
322 | ||
323 | spin_lock(&fscrypt_master_keys_lock); | |
324 | hash_for_each_possible(fscrypt_master_keys, mk, mk_node, hash_key) { | |
325 | if (memcmp(ci->ci_master_key_descriptor, mk->mk_descriptor, | |
326 | FS_KEY_DESCRIPTOR_SIZE) != 0) | |
327 | continue; | |
328 | if (mode != mk->mk_mode) | |
329 | continue; | |
330 | if (crypto_memneq(raw_key, mk->mk_raw, mode->keysize)) | |
331 | continue; | |
332 | /* using existing tfm with same (descriptor, mode, raw_key) */ | |
333 | refcount_inc(&mk->mk_refcount); | |
334 | spin_unlock(&fscrypt_master_keys_lock); | |
335 | free_master_key(to_insert); | |
336 | return mk; | |
337 | } | |
338 | if (to_insert) | |
339 | hash_add(fscrypt_master_keys, &to_insert->mk_node, hash_key); | |
340 | spin_unlock(&fscrypt_master_keys_lock); | |
341 | return to_insert; | |
342 | } | |
343 | ||
344 | /* Prepare to encrypt directly using the master key in the given mode */ | |
345 | static struct fscrypt_master_key * | |
346 | fscrypt_get_master_key(const struct fscrypt_info *ci, struct fscrypt_mode *mode, | |
347 | const u8 *raw_key, const struct inode *inode) | |
348 | { | |
349 | struct fscrypt_master_key *mk; | |
350 | int err; | |
351 | ||
352 | /* Is there already a tfm for this key? */ | |
353 | mk = find_or_insert_master_key(NULL, raw_key, mode, ci); | |
354 | if (mk) | |
355 | return mk; | |
356 | ||
357 | /* Nope, allocate one. */ | |
358 | mk = kzalloc(sizeof(*mk), GFP_NOFS); | |
359 | if (!mk) | |
360 | return ERR_PTR(-ENOMEM); | |
361 | refcount_set(&mk->mk_refcount, 1); | |
362 | mk->mk_mode = mode; | |
363 | mk->mk_ctfm = allocate_skcipher_for_mode(mode, raw_key, inode); | |
364 | if (IS_ERR(mk->mk_ctfm)) { | |
365 | err = PTR_ERR(mk->mk_ctfm); | |
366 | mk->mk_ctfm = NULL; | |
367 | goto err_free_mk; | |
368 | } | |
369 | memcpy(mk->mk_descriptor, ci->ci_master_key_descriptor, | |
370 | FS_KEY_DESCRIPTOR_SIZE); | |
371 | memcpy(mk->mk_raw, raw_key, mode->keysize); | |
372 | ||
373 | return find_or_insert_master_key(mk, raw_key, mode, ci); | |
374 | ||
375 | err_free_mk: | |
376 | free_master_key(mk); | |
377 | return ERR_PTR(err); | |
0adda907 JK |
378 | } |
379 | ||
b7e7cf7a DW |
380 | static int derive_essiv_salt(const u8 *key, int keysize, u8 *salt) |
381 | { | |
382 | struct crypto_shash *tfm = READ_ONCE(essiv_hash_tfm); | |
383 | ||
384 | /* init hash transform on demand */ | |
385 | if (unlikely(!tfm)) { | |
386 | struct crypto_shash *prev_tfm; | |
387 | ||
388 | tfm = crypto_alloc_shash("sha256", 0, 0); | |
389 | if (IS_ERR(tfm)) { | |
544d08fd EB |
390 | fscrypt_warn(NULL, |
391 | "error allocating SHA-256 transform: %ld", | |
392 | PTR_ERR(tfm)); | |
b7e7cf7a DW |
393 | return PTR_ERR(tfm); |
394 | } | |
395 | prev_tfm = cmpxchg(&essiv_hash_tfm, NULL, tfm); | |
396 | if (prev_tfm) { | |
397 | crypto_free_shash(tfm); | |
398 | tfm = prev_tfm; | |
399 | } | |
400 | } | |
401 | ||
402 | { | |
403 | SHASH_DESC_ON_STACK(desc, tfm); | |
404 | desc->tfm = tfm; | |
405 | desc->flags = 0; | |
406 | ||
407 | return crypto_shash_digest(desc, key, keysize, salt); | |
408 | } | |
409 | } | |
410 | ||
411 | static int init_essiv_generator(struct fscrypt_info *ci, const u8 *raw_key, | |
412 | int keysize) | |
413 | { | |
414 | int err; | |
415 | struct crypto_cipher *essiv_tfm; | |
416 | u8 salt[SHA256_DIGEST_SIZE]; | |
417 | ||
418 | essiv_tfm = crypto_alloc_cipher("aes", 0, 0); | |
419 | if (IS_ERR(essiv_tfm)) | |
420 | return PTR_ERR(essiv_tfm); | |
421 | ||
422 | ci->ci_essiv_tfm = essiv_tfm; | |
423 | ||
424 | err = derive_essiv_salt(raw_key, keysize, salt); | |
425 | if (err) | |
426 | goto out; | |
427 | ||
428 | /* | |
429 | * Using SHA256 to derive the salt/key will result in AES-256 being | |
430 | * used for IV generation. File contents encryption will still use the | |
431 | * configured keysize (AES-128) nevertheless. | |
432 | */ | |
433 | err = crypto_cipher_setkey(essiv_tfm, salt, sizeof(salt)); | |
434 | if (err) | |
435 | goto out; | |
436 | ||
437 | out: | |
438 | memzero_explicit(salt, sizeof(salt)); | |
439 | return err; | |
440 | } | |
441 | ||
442 | void __exit fscrypt_essiv_cleanup(void) | |
443 | { | |
444 | crypto_free_shash(essiv_hash_tfm); | |
445 | } | |
446 | ||
8094c3ce EB |
447 | /* |
448 | * Given the encryption mode and key (normally the derived key, but for | |
449 | * FS_POLICY_FLAG_DIRECT_KEY mode it's the master key), set up the inode's | |
450 | * symmetric cipher transform object(s). | |
451 | */ | |
452 | static int setup_crypto_transform(struct fscrypt_info *ci, | |
453 | struct fscrypt_mode *mode, | |
454 | const u8 *raw_key, const struct inode *inode) | |
455 | { | |
456 | struct fscrypt_master_key *mk; | |
457 | struct crypto_skcipher *ctfm; | |
458 | int err; | |
459 | ||
460 | if (ci->ci_flags & FS_POLICY_FLAG_DIRECT_KEY) { | |
461 | mk = fscrypt_get_master_key(ci, mode, raw_key, inode); | |
462 | if (IS_ERR(mk)) | |
463 | return PTR_ERR(mk); | |
464 | ctfm = mk->mk_ctfm; | |
465 | } else { | |
466 | mk = NULL; | |
467 | ctfm = allocate_skcipher_for_mode(mode, raw_key, inode); | |
468 | if (IS_ERR(ctfm)) | |
469 | return PTR_ERR(ctfm); | |
470 | } | |
471 | ci->ci_master_key = mk; | |
472 | ci->ci_ctfm = ctfm; | |
473 | ||
474 | if (mode->needs_essiv) { | |
475 | /* ESSIV implies 16-byte IVs which implies !DIRECT_KEY */ | |
476 | WARN_ON(mode->ivsize != AES_BLOCK_SIZE); | |
477 | WARN_ON(ci->ci_flags & FS_POLICY_FLAG_DIRECT_KEY); | |
478 | ||
479 | err = init_essiv_generator(ci, raw_key, mode->keysize); | |
480 | if (err) { | |
481 | fscrypt_warn(inode->i_sb, | |
482 | "error initializing ESSIV generator for inode %lu: %d", | |
483 | inode->i_ino, err); | |
484 | return err; | |
485 | } | |
486 | } | |
487 | return 0; | |
488 | } | |
489 | ||
490 | static void put_crypt_info(struct fscrypt_info *ci) | |
491 | { | |
492 | if (!ci) | |
493 | return; | |
494 | ||
495 | if (ci->ci_master_key) { | |
496 | put_master_key(ci->ci_master_key); | |
497 | } else { | |
498 | crypto_free_skcipher(ci->ci_ctfm); | |
499 | crypto_free_cipher(ci->ci_essiv_tfm); | |
500 | } | |
501 | kmem_cache_free(fscrypt_info_cachep, ci); | |
502 | } | |
503 | ||
1b53cf98 | 504 | int fscrypt_get_encryption_info(struct inode *inode) |
0adda907 | 505 | { |
0b81d077 | 506 | struct fscrypt_info *crypt_info; |
0b81d077 | 507 | struct fscrypt_context ctx; |
e1cc40e5 | 508 | struct fscrypt_mode *mode; |
a6e08912 | 509 | u8 *raw_key = NULL; |
0adda907 JK |
510 | int res; |
511 | ||
1b53cf98 EB |
512 | if (inode->i_crypt_info) |
513 | return 0; | |
514 | ||
f32d7ac2 | 515 | res = fscrypt_initialize(inode->i_sb->s_cop->flags); |
cfc4d971 JK |
516 | if (res) |
517 | return res; | |
0b81d077 | 518 | |
0b81d077 JK |
519 | res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); |
520 | if (res < 0) { | |
5bbdcbbb | 521 | if (!fscrypt_dummy_context_enabled(inode) || |
e0428a26 | 522 | IS_ENCRYPTED(inode)) |
0b81d077 | 523 | return res; |
5bbdcbbb TT |
524 | /* Fake up a context for an unencrypted directory */ |
525 | memset(&ctx, 0, sizeof(ctx)); | |
8f39850d | 526 | ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; |
0b81d077 JK |
527 | ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS; |
528 | ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS; | |
5bbdcbbb | 529 | memset(ctx.master_key_descriptor, 0x42, FS_KEY_DESCRIPTOR_SIZE); |
0b81d077 | 530 | } else if (res != sizeof(ctx)) { |
0adda907 | 531 | return -EINVAL; |
0b81d077 | 532 | } |
8f39850d EB |
533 | |
534 | if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) | |
535 | return -EINVAL; | |
536 | ||
537 | if (ctx.flags & ~FS_POLICY_FLAGS_VALID) | |
538 | return -EINVAL; | |
0adda907 | 539 | |
8094c3ce | 540 | crypt_info = kmem_cache_zalloc(fscrypt_info_cachep, GFP_NOFS); |
0adda907 JK |
541 | if (!crypt_info) |
542 | return -ENOMEM; | |
543 | ||
544 | crypt_info->ci_flags = ctx.flags; | |
545 | crypt_info->ci_data_mode = ctx.contents_encryption_mode; | |
546 | crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; | |
8094c3ce EB |
547 | memcpy(crypt_info->ci_master_key_descriptor, ctx.master_key_descriptor, |
548 | FS_KEY_DESCRIPTOR_SIZE); | |
549 | memcpy(crypt_info->ci_nonce, ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE); | |
640778fb | 550 | |
e1cc40e5 EB |
551 | mode = select_encryption_mode(crypt_info, inode); |
552 | if (IS_ERR(mode)) { | |
553 | res = PTR_ERR(mode); | |
26bf3dc7 | 554 | goto out; |
e1cc40e5 | 555 | } |
8094c3ce EB |
556 | WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE); |
557 | crypt_info->ci_mode = mode; | |
8f39850d | 558 | |
a6e08912 | 559 | /* |
8094c3ce EB |
560 | * This cannot be a stack buffer because it may be passed to the |
561 | * scatterlist crypto API as part of key derivation. | |
a6e08912 EB |
562 | */ |
563 | res = -ENOMEM; | |
e1cc40e5 | 564 | raw_key = kmalloc(mode->keysize, GFP_NOFS); |
a6e08912 EB |
565 | if (!raw_key) |
566 | goto out; | |
567 | ||
8094c3ce | 568 | res = find_and_derive_key(inode, &ctx, raw_key, mode); |
590f497d | 569 | if (res) |
66aa3e12 | 570 | goto out; |
590f497d | 571 | |
8094c3ce | 572 | res = setup_crypto_transform(crypt_info, mode, raw_key, inode); |
26bf3dc7 JK |
573 | if (res) |
574 | goto out; | |
575 | ||
1b53cf98 EB |
576 | if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL) |
577 | crypt_info = NULL; | |
26bf3dc7 | 578 | out: |
0b81d077 | 579 | if (res == -ENOKEY) |
26bf3dc7 | 580 | res = 0; |
0b81d077 | 581 | put_crypt_info(crypt_info); |
a6e08912 | 582 | kzfree(raw_key); |
0adda907 JK |
583 | return res; |
584 | } | |
1b53cf98 | 585 | EXPORT_SYMBOL(fscrypt_get_encryption_info); |
0adda907 | 586 | |
3d204e24 | 587 | void fscrypt_put_encryption_info(struct inode *inode) |
0adda907 | 588 | { |
3d204e24 EB |
589 | put_crypt_info(inode->i_crypt_info); |
590 | inode->i_crypt_info = NULL; | |
0b81d077 JK |
591 | } |
592 | EXPORT_SYMBOL(fscrypt_put_encryption_info); |