Blame view
fs/crypto/keysetup.c
23 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
0adda907f f2fs crypto: add ... |
2 |
/* |
3ec4f2a62 fscrypt: refactor... |
3 |
* Key setup facility for FS encryption support. |
0adda907f f2fs crypto: add ... |
4 5 6 |
* * Copyright (C) 2015, Google, Inc. * |
3ec4f2a62 fscrypt: refactor... |
7 8 |
* Originally written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar. * Heavily modified since then. |
0adda907f f2fs crypto: add ... |
9 |
*/ |
0b81d0779 fs crypto: move p... |
10 |
|
a575784c6 fscrypt: trim dow... |
11 |
#include <crypto/skcipher.h> |
0109ce76d fscrypt: move v1 ... |
12 |
#include <linux/key.h> |
a992b20cd fscrypt: add fscr... |
13 |
#include <linux/random.h> |
0109ce76d fscrypt: move v1 ... |
14 |
|
3325bea5b fscrypt: rename g... |
15 |
#include "fscrypt_private.h" |
0adda907f f2fs crypto: add ... |
16 |
|
f5f6acfb1 FROMLIST: fscrypt... |
17 |
struct fscrypt_mode fscrypt_modes[] = { |
3b6df59bc fscrypt: use FSCR... |
18 |
[FSCRYPT_MODE_AES_256_XTS] = { |
e1cc40e5d fscrypt: log the ... |
19 20 21 |
.friendly_name = "AES-256-XTS", .cipher_str = "xts(aes)", .keysize = 64, |
8094c3ceb fscrypt: add Adia... |
22 |
.ivsize = 16, |
f5f6acfb1 FROMLIST: fscrypt... |
23 |
.blk_crypto_mode = BLK_ENCRYPTION_MODE_AES_256_XTS, |
e1cc40e5d fscrypt: log the ... |
24 |
}, |
3b6df59bc fscrypt: use FSCR... |
25 |
[FSCRYPT_MODE_AES_256_CTS] = { |
e1cc40e5d fscrypt: log the ... |
26 27 28 |
.friendly_name = "AES-256-CTS-CBC", .cipher_str = "cts(cbc(aes))", .keysize = 32, |
8094c3ceb fscrypt: add Adia... |
29 |
.ivsize = 16, |
e1cc40e5d fscrypt: log the ... |
30 |
}, |
3b6df59bc fscrypt: use FSCR... |
31 |
[FSCRYPT_MODE_AES_128_CBC] = { |
0208947ce FROMLIST: fscrypt... |
32 33 |
.friendly_name = "AES-128-CBC-ESSIV", .cipher_str = "essiv(cbc(aes),sha256)", |
e1cc40e5d fscrypt: log the ... |
34 |
.keysize = 16, |
8094c3ceb fscrypt: add Adia... |
35 |
.ivsize = 16, |
cfd7e6c13 FROMLIST: Update ... |
36 |
.blk_crypto_mode = BLK_ENCRYPTION_MODE_AES_128_CBC_ESSIV, |
e1cc40e5d fscrypt: log the ... |
37 |
}, |
3b6df59bc fscrypt: use FSCR... |
38 |
[FSCRYPT_MODE_AES_128_CTS] = { |
e1cc40e5d fscrypt: log the ... |
39 40 41 |
.friendly_name = "AES-128-CTS-CBC", .cipher_str = "cts(cbc(aes))", .keysize = 16, |
8094c3ceb fscrypt: add Adia... |
42 43 |
.ivsize = 16, }, |
3b6df59bc fscrypt: use FSCR... |
44 |
[FSCRYPT_MODE_ADIANTUM] = { |
8094c3ceb fscrypt: add Adia... |
45 46 47 48 |
.friendly_name = "Adiantum", .cipher_str = "adiantum(xchacha12,aes)", .keysize = 32, .ivsize = 32, |
cfd7e6c13 FROMLIST: Update ... |
49 |
.blk_crypto_mode = BLK_ENCRYPTION_MODE_ADIANTUM, |
e1cc40e5d fscrypt: log the ... |
50 |
}, |
b7e7cf7a6 fscrypt: add supp... |
51 |
}; |
06a813d6d BACKPORT: FROMLIS... |
52 |
static DEFINE_MUTEX(fscrypt_mode_key_setup_mutex); |
e1cc40e5d fscrypt: log the ... |
53 |
static struct fscrypt_mode * |
5dae460c2 fscrypt: v2 encry... |
54 55 |
select_encryption_mode(const union fscrypt_policy *policy, const struct inode *inode) |
8f39850df fscrypto: improve... |
56 |
{ |
3b7c17a81 fscrypt: remove k... |
57 |
BUILD_BUG_ON(ARRAY_SIZE(fscrypt_modes) != FSCRYPT_MODE_MAX + 1); |
e1cc40e5d fscrypt: log the ... |
58 |
if (S_ISREG(inode->i_mode)) |
f5f6acfb1 FROMLIST: fscrypt... |
59 |
return &fscrypt_modes[fscrypt_policy_contents_mode(policy)]; |
e1cc40e5d fscrypt: log the ... |
60 61 |
if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) |
f5f6acfb1 FROMLIST: fscrypt... |
62 |
return &fscrypt_modes[fscrypt_policy_fnames_mode(policy)]; |
8f39850df fscrypto: improve... |
63 |
|
e1cc40e5d fscrypt: log the ... |
64 65 66 67 |
WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %lu, which is not encryptable (file type %d) ", inode->i_ino, (inode->i_mode & S_IFMT)); return ERR_PTR(-EINVAL); |
8f39850df fscrypto: improve... |
68 |
} |
3ec4f2a62 fscrypt: refactor... |
69 |
/* Create a symmetric cipher object for the given encryption mode and key */ |
cfd7e6c13 FROMLIST: Update ... |
70 71 72 |
static struct crypto_skcipher * fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, const struct inode *inode) |
8094c3ceb fscrypt: add Adia... |
73 74 75 76 77 78 |
{ struct crypto_skcipher *tfm; int err; tfm = crypto_alloc_skcipher(mode->cipher_str, 0, 0); if (IS_ERR(tfm)) { |
29a98c1ca fscrypt: use ENOP... |
79 |
if (PTR_ERR(tfm) == -ENOENT) { |
a4d14e915 fscrypt: improve ... |
80 81 82 |
fscrypt_warn(inode, "Missing crypto API support for %s (API name: \"%s\")", mode->friendly_name, mode->cipher_str); |
29a98c1ca fscrypt: use ENOP... |
83 84 85 86 |
return ERR_PTR(-ENOPKG); } fscrypt_err(inode, "Error allocating '%s' transform: %ld", mode->cipher_str, PTR_ERR(tfm)); |
8094c3ceb fscrypt: add Adia... |
87 88 |
return tfm; } |
ff73c2c01 fscrypt: avoid da... |
89 |
if (!xchg(&mode->logged_impl_name, 1)) { |
8094c3ceb fscrypt: add Adia... |
90 91 92 93 |
/* * fscrypt performance can vary greatly depending on which * crypto algorithm implementation is used. Help people debug * performance problems by logging the ->cra_driver_name the |
ff73c2c01 fscrypt: avoid da... |
94 |
* first time a mode is used. |
8094c3ceb fscrypt: add Adia... |
95 |
*/ |
8094c3ceb fscrypt: add Adia... |
96 97 |
pr_info("fscrypt: %s using implementation \"%s\" ", |
6e1adb88d fscrypt: use cryp... |
98 |
mode->friendly_name, crypto_skcipher_driver_name(tfm)); |
8094c3ceb fscrypt: add Adia... |
99 |
} |
c64cfb989 fscrypt: verify t... |
100 101 102 |
if (WARN_ON(crypto_skcipher_ivsize(tfm) != mode->ivsize)) { err = -EINVAL; goto err_free_tfm; |
8094c3ceb fscrypt: add Adia... |
103 |
} |
231baecde crypto: clarify n... |
104 |
crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); |
8094c3ceb fscrypt: add Adia... |
105 106 107 108 109 110 111 112 113 114 |
err = crypto_skcipher_setkey(tfm, raw_key, mode->keysize); if (err) goto err_free_tfm; return tfm; err_free_tfm: crypto_free_skcipher(tfm); return ERR_PTR(err); } |
cfd7e6c13 FROMLIST: Update ... |
115 116 117 118 119 120 |
/* * Prepare the crypto transform object or blk-crypto key in @prep_key, given the * raw key, encryption mode, and flag indicating which encryption implementation * (fs-layer or blk-crypto) will be used. */ int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key, |
155acee85 ANDROID: fscrypt:... |
121 |
const u8 *raw_key, unsigned int raw_key_size, |
f5ecdc54d ANDROID: block: P... |
122 |
bool is_hw_wrapped, const struct fscrypt_info *ci) |
8094c3ceb fscrypt: add Adia... |
123 |
{ |
0208947ce FROMLIST: fscrypt... |
124 |
struct crypto_skcipher *tfm; |
3ec4f2a62 fscrypt: refactor... |
125 |
|
cfd7e6c13 FROMLIST: Update ... |
126 |
if (fscrypt_using_inline_encryption(ci)) |
155acee85 ANDROID: fscrypt:... |
127 |
return fscrypt_prepare_inline_crypt_key(prep_key, |
f5ecdc54d ANDROID: block: P... |
128 |
raw_key, raw_key_size, is_hw_wrapped, ci); |
155acee85 ANDROID: fscrypt:... |
129 |
|
f5ecdc54d ANDROID: block: P... |
130 |
if (WARN_ON(is_hw_wrapped || raw_key_size != ci->ci_mode->keysize)) |
155acee85 ANDROID: fscrypt:... |
131 |
return -EINVAL; |
f5f6acfb1 FROMLIST: fscrypt... |
132 |
|
cfd7e6c13 FROMLIST: Update ... |
133 |
tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode); |
0208947ce FROMLIST: fscrypt... |
134 135 |
if (IS_ERR(tfm)) return PTR_ERR(tfm); |
cfd7e6c13 FROMLIST: Update ... |
136 |
/* |
97c6327f7 fscrypt: use smp_... |
137 138 139 140 |
* Pairs with the smp_load_acquire() in fscrypt_is_key_prepared(). * I.e., here we publish ->tfm with a RELEASE barrier so that * concurrent tasks can ACQUIRE it. Note that this concurrency is only * possible for per-mode keys, not for per-file keys. |
cfd7e6c13 FROMLIST: Update ... |
141 142 143 144 145 146 147 148 149 150 151 |
*/ smp_store_release(&prep_key->tfm, tfm); return 0; } /* Destroy a crypto transform object and/or blk-crypto key. */ void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key) { crypto_free_skcipher(prep_key->tfm); fscrypt_destroy_inline_crypt_key(prep_key); } |
8094c3ceb fscrypt: add Adia... |
152 |
|
5cc45ee59 Merge f0d87441432... |
153 154 |
/* Given a per-file encryption key, set up the file's crypto transform object */ int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key) |
cfd7e6c13 FROMLIST: Update ... |
155 |
{ |
afca03cbb FROMLIST: fscrypt... |
156 |
ci->ci_owns_key = true; |
d628e385c ANDROID: fscrypt:... |
157 158 |
return fscrypt_prepare_key(&ci->ci_enc_key, raw_key, ci->ci_mode->keysize, |
f5ecdc54d ANDROID: block: P... |
159 |
false /*is_hw_wrapped*/, ci); |
8094c3ceb fscrypt: add Adia... |
160 |
} |
f592efe73 fscrypt: clarify ... |
161 162 |
static int setup_per_mode_enc_key(struct fscrypt_info *ci, struct fscrypt_master_key *mk, |
5cc45ee59 Merge f0d87441432... |
163 |
struct fscrypt_prepared_key *keys, |
f592efe73 fscrypt: clarify ... |
164 |
u8 hkdf_context, bool include_fs_uuid) |
5dae460c2 fscrypt: v2 encry... |
165 |
{ |
afca03cbb FROMLIST: fscrypt... |
166 167 |
const struct inode *inode = ci->ci_inode; const struct super_block *sb = inode->i_sb; |
5dae460c2 fscrypt: v2 encry... |
168 |
struct fscrypt_mode *mode = ci->ci_mode; |
f5f6acfb1 FROMLIST: fscrypt... |
169 |
const u8 mode_num = mode - fscrypt_modes; |
cfd7e6c13 FROMLIST: Update ... |
170 |
struct fscrypt_prepared_key *prep_key; |
5dae460c2 fscrypt: v2 encry... |
171 |
u8 mode_key[FSCRYPT_MAX_KEY_SIZE]; |
afca03cbb FROMLIST: fscrypt... |
172 173 |
u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)]; unsigned int hkdf_infolen = 0; |
5dae460c2 fscrypt: v2 encry... |
174 |
int err; |
3b7c17a81 fscrypt: remove k... |
175 |
if (WARN_ON(mode_num > FSCRYPT_MODE_MAX)) |
5dae460c2 fscrypt: v2 encry... |
176 |
return -EINVAL; |
cfd7e6c13 FROMLIST: Update ... |
177 178 |
prep_key = &keys[mode_num]; if (fscrypt_is_key_prepared(prep_key, ci)) { |
c2b86b727 FROMLIST: Update ... |
179 |
ci->ci_enc_key = *prep_key; |
cfd7e6c13 FROMLIST: Update ... |
180 181 |
return 0; } |
06a813d6d BACKPORT: FROMLIS... |
182 |
mutex_lock(&fscrypt_mode_key_setup_mutex); |
cfd7e6c13 FROMLIST: Update ... |
183 184 185 |
if (fscrypt_is_key_prepared(prep_key, ci)) goto done_unlock; |
5dae460c2 fscrypt: v2 encry... |
186 |
|
155acee85 ANDROID: fscrypt:... |
187 188 189 190 191 192 193 194 195 |
if (mk->mk_secret.is_hw_wrapped && S_ISREG(inode->i_mode)) { int i; if (!fscrypt_using_inline_encryption(ci)) { fscrypt_warn(ci->ci_inode, "Hardware-wrapped keys require inline encryption (-o inlinecrypt)"); err = -EINVAL; goto out_unlock; } |
a7c33264f ANDROID: crypto: ... |
196 |
for (i = 0; i <= FSCRYPT_MODE_MAX; i++) { |
155acee85 ANDROID: fscrypt:... |
197 198 199 200 201 202 203 204 |
if (fscrypt_is_key_prepared(&keys[i], ci)) { fscrypt_warn(ci->ci_inode, "Each hardware-wrapped key can only be used with one encryption mode"); err = -EINVAL; goto out_unlock; } } err = fscrypt_prepare_key(prep_key, mk->mk_secret.raw, |
f5ecdc54d ANDROID: block: P... |
205 |
mk->mk_secret.size, true, ci); |
155acee85 ANDROID: fscrypt:... |
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
if (err) goto out_unlock; } else { BUILD_BUG_ON(sizeof(mode_num) != 1); BUILD_BUG_ON(sizeof(sb->s_uuid) != 16); BUILD_BUG_ON(sizeof(hkdf_info) != 17); hkdf_info[hkdf_infolen++] = mode_num; if (include_fs_uuid) { memcpy(&hkdf_info[hkdf_infolen], &sb->s_uuid, sizeof(sb->s_uuid)); hkdf_infolen += sizeof(sb->s_uuid); } err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, hkdf_context, hkdf_info, hkdf_infolen, mode_key, mode->keysize); if (err) goto out_unlock; err = fscrypt_prepare_key(prep_key, mode_key, mode->keysize, |
f5ecdc54d ANDROID: block: P... |
224 |
false /*is_hw_wrapped*/, ci); |
155acee85 ANDROID: fscrypt:... |
225 226 227 |
memzero_explicit(mode_key, mode->keysize); if (err) goto out_unlock; |
afca03cbb FROMLIST: fscrypt... |
228 |
} |
cfd7e6c13 FROMLIST: Update ... |
229 |
done_unlock: |
c2b86b727 FROMLIST: Update ... |
230 |
ci->ci_enc_key = *prep_key; |
cfd7e6c13 FROMLIST: Update ... |
231 232 |
err = 0; out_unlock: |
06a813d6d BACKPORT: FROMLIS... |
233 |
mutex_unlock(&fscrypt_mode_key_setup_mutex); |
cfd7e6c13 FROMLIST: Update ... |
234 |
return err; |
5dae460c2 fscrypt: v2 encry... |
235 |
} |
aa408f835 fscrypt: derive d... |
236 237 238 239 240 241 |
int fscrypt_derive_dirhash_key(struct fscrypt_info *ci, const struct fscrypt_master_key *mk) { int err; err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, HKDF_CONTEXT_DIRHASH_KEY, |
1d6217a4f fscrypt: rename F... |
242 |
ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE, |
aa408f835 fscrypt: derive d... |
243 244 245 246 247 248 249 |
(u8 *)&ci->ci_dirhash_key, sizeof(ci->ci_dirhash_key)); if (err) return err; ci->ci_dirhash_key_initialized = true; return 0; } |
a992b20cd fscrypt: add fscr... |
250 251 252 253 254 255 256 257 258 |
void fscrypt_hash_inode_number(struct fscrypt_info *ci, const struct fscrypt_master_key *mk) { WARN_ON(ci->ci_inode->i_ino == 0); WARN_ON(!mk->mk_ino_hash_key_initialized); ci->ci_hashed_ino = (u32)siphash_1u64(ci->ci_inode->i_ino, &mk->mk_ino_hash_key); } |
06a813d6d BACKPORT: FROMLIS... |
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
static int fscrypt_setup_iv_ino_lblk_32_key(struct fscrypt_info *ci, struct fscrypt_master_key *mk) { int err; err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_32_keys, HKDF_CONTEXT_IV_INO_LBLK_32_KEY, true); if (err) return err; /* pairs with smp_store_release() below */ if (!smp_load_acquire(&mk->mk_ino_hash_key_initialized)) { mutex_lock(&fscrypt_mode_key_setup_mutex); if (mk->mk_ino_hash_key_initialized) goto unlock; err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, HKDF_CONTEXT_INODE_HASH_KEY, NULL, 0, (u8 *)&mk->mk_ino_hash_key, sizeof(mk->mk_ino_hash_key)); if (err) goto unlock; /* pairs with smp_load_acquire() above */ smp_store_release(&mk->mk_ino_hash_key_initialized, true); unlock: mutex_unlock(&fscrypt_mode_key_setup_mutex); if (err) return err; } |
a992b20cd fscrypt: add fscr... |
290 291 292 293 |
/* * New inodes may not have an inode number assigned yet. * Hashing their inode number is delayed until later. */ |
92cfcd030 fscrypt: remove r... |
294 |
if (ci->ci_inode->i_ino) |
a992b20cd fscrypt: add fscr... |
295 |
fscrypt_hash_inode_number(ci, mk); |
06a813d6d BACKPORT: FROMLIS... |
296 297 |
return 0; } |
5dae460c2 fscrypt: v2 encry... |
298 |
static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, |
a992b20cd fscrypt: add fscr... |
299 300 |
struct fscrypt_master_key *mk, bool need_dirhash_key) |
5dae460c2 fscrypt: v2 encry... |
301 |
{ |
5dae460c2 fscrypt: v2 encry... |
302 |
int err; |
155acee85 ANDROID: fscrypt:... |
303 |
if (mk->mk_secret.is_hw_wrapped && |
06a813d6d BACKPORT: FROMLIS... |
304 305 |
!(ci->ci_policy.v2.flags & (FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 | FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))) { |
155acee85 ANDROID: fscrypt:... |
306 |
fscrypt_warn(ci->ci_inode, |
06a813d6d BACKPORT: FROMLIS... |
307 |
"Hardware-wrapped keys are only supported with IV_INO_LBLK policies"); |
155acee85 ANDROID: fscrypt:... |
308 309 |
return -EINVAL; } |
5dae460c2 fscrypt: v2 encry... |
310 311 |
if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { /* |
f592efe73 fscrypt: clarify ... |
312 313 314 315 316 317 |
* DIRECT_KEY: instead of deriving per-file encryption keys, the * per-file nonce will be included in all the IVs. But unlike * v1 policies, for v2 policies in this case we don't encrypt * with the master key directly but rather derive a per-mode * encryption key. This ensures that the master key is * consistently used only for HKDF, avoiding key reuse issues. |
5dae460c2 fscrypt: v2 encry... |
318 |
*/ |
5cc45ee59 Merge f0d87441432... |
319 |
err = setup_per_mode_enc_key(ci, mk, mk->mk_direct_keys, |
f592efe73 fscrypt: clarify ... |
320 |
HKDF_CONTEXT_DIRECT_KEY, false); |
afca03cbb FROMLIST: fscrypt... |
321 322 323 324 325 326 |
} else if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) { /* * IV_INO_LBLK_64: encryption keys are derived from (master_key, * mode_num, filesystem_uuid), and inode number is included in * the IVs. This format is optimized for use with inline |
06a813d6d BACKPORT: FROMLIS... |
327 |
* encryption hardware compliant with the UFS standard. |
afca03cbb FROMLIST: fscrypt... |
328 |
*/ |
5cc45ee59 Merge f0d87441432... |
329 |
err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_64_keys, |
f592efe73 fscrypt: clarify ... |
330 331 |
HKDF_CONTEXT_IV_INO_LBLK_64_KEY, true); |
06a813d6d BACKPORT: FROMLIS... |
332 333 334 |
} else if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) { err = fscrypt_setup_iv_ino_lblk_32_key(ci, mk); |
aa408f835 fscrypt: derive d... |
335 336 |
} else { u8 derived_key[FSCRYPT_MAX_KEY_SIZE]; |
5dae460c2 fscrypt: v2 encry... |
337 |
|
aa408f835 fscrypt: derive d... |
338 |
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, |
f592efe73 fscrypt: clarify ... |
339 |
HKDF_CONTEXT_PER_FILE_ENC_KEY, |
1d6217a4f fscrypt: rename F... |
340 |
ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE, |
aa408f835 fscrypt: derive d... |
341 342 343 |
derived_key, ci->ci_mode->keysize); if (err) return err; |
f592efe73 fscrypt: clarify ... |
344 |
err = fscrypt_set_per_file_enc_key(ci, derived_key); |
aa408f835 fscrypt: derive d... |
345 346 |
memzero_explicit(derived_key, ci->ci_mode->keysize); } |
5dae460c2 fscrypt: v2 encry... |
347 348 |
if (err) return err; |
aa408f835 fscrypt: derive d... |
349 |
/* Derive a secret dirhash key for directories that need it. */ |
a992b20cd fscrypt: add fscr... |
350 |
if (need_dirhash_key) { |
aa408f835 fscrypt: derive d... |
351 352 353 354 355 356 |
err = fscrypt_derive_dirhash_key(ci, mk); if (err) return err; } return 0; |
5dae460c2 fscrypt: v2 encry... |
357 |
} |
3ec4f2a62 fscrypt: refactor... |
358 359 |
/* * Find the master key, then set up the inode's actual encryption key. |
b1c0ec359 fscrypt: add FS_I... |
360 361 |
* * If the master key is found in the filesystem-level keyring, then the |
3b743b006 fscrypt: simplify... |
362 363 364 365 366 |
* corresponding 'struct key' is returned in *master_key_ret with its semaphore * read-locked. This is needed to ensure that only one task links the * fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race to create * an fscrypt_info for the same inode), and to synchronize the master key being * removed with a new inode starting to use it. |
3ec4f2a62 fscrypt: refactor... |
367 |
*/ |
b1c0ec359 fscrypt: add FS_I... |
368 |
static int setup_file_encryption_key(struct fscrypt_info *ci, |
a992b20cd fscrypt: add fscr... |
369 |
bool need_dirhash_key, |
b1c0ec359 fscrypt: add FS_I... |
370 |
struct key **master_key_ret) |
3ec4f2a62 fscrypt: refactor... |
371 |
{ |
22d94f493 fscrypt: add FS_I... |
372 373 374 375 |
struct key *key; struct fscrypt_master_key *mk = NULL; struct fscrypt_key_specifier mk_spec; int err; |
5dae460c2 fscrypt: v2 encry... |
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 |
switch (ci->ci_policy.version) { case FSCRYPT_POLICY_V1: mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; memcpy(mk_spec.u.descriptor, ci->ci_policy.v1.master_key_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE); break; case FSCRYPT_POLICY_V2: mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER; memcpy(mk_spec.u.identifier, ci->ci_policy.v2.master_key_identifier, FSCRYPT_KEY_IDENTIFIER_SIZE); break; default: WARN_ON(1); return -EINVAL; } |
22d94f493 fscrypt: add FS_I... |
393 394 395 |
key = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec); if (IS_ERR(key)) { |
5dae460c2 fscrypt: v2 encry... |
396 397 |
if (key != ERR_PTR(-ENOKEY) || ci->ci_policy.version != FSCRYPT_POLICY_V1) |
22d94f493 fscrypt: add FS_I... |
398 |
return PTR_ERR(key); |
3ddb60ffd ANDROID: fscrypt:... |
399 400 401 |
err = fscrypt_select_encryption_impl(ci, false); if (err) return err; |
5dae460c2 fscrypt: v2 encry... |
402 403 404 405 406 407 |
/* * As a legacy fallback for v1 policies, search for the key in * the current task's subscribed keyrings too. Don't move this * to before the search of ->s_master_keys, since users * shouldn't be able to override filesystem-level keys. */ |
22d94f493 fscrypt: add FS_I... |
408 409 410 411 |
return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci); } mk = key->payload.data[0]; |
3b743b006 fscrypt: simplify... |
412 |
down_read(&key->sem); |
b1c0ec359 fscrypt: add FS_I... |
413 414 415 416 417 418 |
/* Has the secret been removed (via FS_IOC_REMOVE_ENCRYPTION_KEY)? */ if (!is_master_key_secret_present(&mk->mk_secret)) { err = -ENOKEY; goto out_release_key; } |
22d94f493 fscrypt: add FS_I... |
419 |
|
5dae460c2 fscrypt: v2 encry... |
420 421 422 423 424 425 |
/* * Require that the master key be at least as long as the derived key. * Otherwise, the derived key cannot possibly contain as much entropy as * that required by the encryption mode it will be used for. For v1 * policies it's also required for the KDF to work at all. */ |
22d94f493 fscrypt: add FS_I... |
426 427 428 429 430 431 432 433 434 |
if (mk->mk_secret.size < ci->ci_mode->keysize) { fscrypt_warn(NULL, "key with %s %*phN is too short (got %u bytes, need %u+ bytes)", master_key_spec_type(&mk_spec), master_key_spec_len(&mk_spec), (u8 *)&mk_spec.u, mk->mk_secret.size, ci->ci_mode->keysize); err = -ENOKEY; goto out_release_key; } |
3ddb60ffd ANDROID: fscrypt:... |
435 436 437 |
err = fscrypt_select_encryption_impl(ci, mk->mk_secret.is_hw_wrapped); if (err) goto out_release_key; |
5dae460c2 fscrypt: v2 encry... |
438 439 440 441 442 |
switch (ci->ci_policy.version) { case FSCRYPT_POLICY_V1: err = fscrypt_setup_v1_file_key(ci, mk->mk_secret.raw); break; case FSCRYPT_POLICY_V2: |
a992b20cd fscrypt: add fscr... |
443 |
err = fscrypt_setup_v2_file_key(ci, mk, need_dirhash_key); |
5dae460c2 fscrypt: v2 encry... |
444 445 446 447 448 449 |
break; default: WARN_ON(1); err = -EINVAL; break; } |
b1c0ec359 fscrypt: add FS_I... |
450 451 452 453 454 |
if (err) goto out_release_key; *master_key_ret = key; return 0; |
22d94f493 fscrypt: add FS_I... |
455 456 |
out_release_key: |
3b743b006 fscrypt: simplify... |
457 |
up_read(&key->sem); |
22d94f493 fscrypt: add FS_I... |
458 459 |
key_put(key); return err; |
3ec4f2a62 fscrypt: refactor... |
460 |
} |
8094c3ceb fscrypt: add Adia... |
461 462 |
static void put_crypt_info(struct fscrypt_info *ci) { |
b1c0ec359 fscrypt: add FS_I... |
463 |
struct key *key; |
8094c3ceb fscrypt: add Adia... |
464 465 |
if (!ci) return; |
0208947ce FROMLIST: fscrypt... |
466 |
if (ci->ci_direct_key) |
0109ce76d fscrypt: move v1 ... |
467 |
fscrypt_put_direct_key(ci->ci_direct_key); |
cfd7e6c13 FROMLIST: Update ... |
468 |
else if (ci->ci_owns_key) |
c2b86b727 FROMLIST: Update ... |
469 |
fscrypt_destroy_prepared_key(&ci->ci_enc_key); |
b1c0ec359 fscrypt: add FS_I... |
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 |
key = ci->ci_master_key; if (key) { struct fscrypt_master_key *mk = key->payload.data[0]; /* * Remove this inode from the list of inodes that were unlocked * with the master key. * * In addition, if we're removing the last inode from a key that * already had its secret removed, invalidate the key so that it * gets removed from ->s_master_keys. */ spin_lock(&mk->mk_decrypted_inodes_lock); list_del(&ci->ci_master_key_link); spin_unlock(&mk->mk_decrypted_inodes_lock); if (refcount_dec_and_test(&mk->mk_refcount)) key_invalidate(key); key_put(key); } |
7ab69374a FROMLIST: fscrypt... |
490 |
memzero_explicit(ci, sizeof(*ci)); |
8094c3ceb fscrypt: add Adia... |
491 492 |
kmem_cache_free(fscrypt_info_cachep, ci); } |
a992b20cd fscrypt: add fscr... |
493 494 495 496 497 |
static int fscrypt_setup_encryption_info(struct inode *inode, const union fscrypt_policy *policy, const u8 nonce[FSCRYPT_FILE_NONCE_SIZE], bool need_dirhash_key) |
0adda907f f2fs crypto: add ... |
498 |
{ |
0b81d0779 fs crypto: move p... |
499 |
struct fscrypt_info *crypt_info; |
e1cc40e5d fscrypt: log the ... |
500 |
struct fscrypt_mode *mode; |
b1c0ec359 fscrypt: add FS_I... |
501 |
struct key *master_key = NULL; |
0adda907f f2fs crypto: add ... |
502 |
int res; |
f32d7ac20 fscrypt: Delay bo... |
503 |
res = fscrypt_initialize(inode->i_sb->s_cop->flags); |
cfc4d971d f2fs crypto: spli... |
504 505 |
if (res) return res; |
0b81d0779 fs crypto: move p... |
506 |
|
9dad5feb4 fscrypt: stop pre... |
507 |
crypt_info = kmem_cache_zalloc(fscrypt_info_cachep, GFP_KERNEL); |
0adda907f f2fs crypto: add ... |
508 509 |
if (!crypt_info) return -ENOMEM; |
59dc6a8e1 fscrypt: add ->ci... |
510 |
crypt_info->ci_inode = inode; |
a992b20cd fscrypt: add fscr... |
511 512 |
crypt_info->ci_policy = *policy; memcpy(crypt_info->ci_nonce, nonce, FSCRYPT_FILE_NONCE_SIZE); |
640778fbc f2fs crypto: get ... |
513 |
|
5dae460c2 fscrypt: v2 encry... |
514 |
mode = select_encryption_mode(&crypt_info->ci_policy, inode); |
e1cc40e5d fscrypt: log the ... |
515 516 |
if (IS_ERR(mode)) { res = PTR_ERR(mode); |
26bf3dc7e f2fs crypto: use ... |
517 |
goto out; |
e1cc40e5d fscrypt: log the ... |
518 |
} |
8094c3ceb fscrypt: add Adia... |
519 520 |
WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE); crypt_info->ci_mode = mode; |
8f39850df fscrypto: improve... |
521 |
|
a992b20cd fscrypt: add fscr... |
522 523 |
res = setup_file_encryption_key(crypt_info, need_dirhash_key, &master_key); |
26bf3dc7e f2fs crypto: use ... |
524 525 |
if (res) goto out; |
ab673b987 fscrypt: use smp_... |
526 |
/* |
a992b20cd fscrypt: add fscr... |
527 528 |
* For existing inodes, multiple tasks may race to set ->i_crypt_info. * So use cmpxchg_release(). This pairs with the smp_load_acquire() in |
ab673b987 fscrypt: use smp_... |
529 530 531 |
* fscrypt_get_info(). I.e., here we publish ->i_crypt_info with a * RELEASE barrier so that other tasks can ACQUIRE it. */ |
b1c0ec359 fscrypt: add FS_I... |
532 |
if (cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info) == NULL) { |
ab673b987 fscrypt: use smp_... |
533 534 535 536 |
/* * We won the race and set ->i_crypt_info to our crypt_info. * Now link it into the master key's inode list. */ |
b1c0ec359 fscrypt: add FS_I... |
537 538 539 540 541 542 543 544 545 546 547 |
if (master_key) { struct fscrypt_master_key *mk = master_key->payload.data[0]; refcount_inc(&mk->mk_refcount); crypt_info->ci_master_key = key_get(master_key); spin_lock(&mk->mk_decrypted_inodes_lock); list_add(&crypt_info->ci_master_key_link, &mk->mk_decrypted_inodes); spin_unlock(&mk->mk_decrypted_inodes_lock); } |
1b53cf981 fscrypt: remove b... |
548 |
crypt_info = NULL; |
b1c0ec359 fscrypt: add FS_I... |
549 550 |
} res = 0; |
26bf3dc7e f2fs crypto: use ... |
551 |
out: |
b1c0ec359 fscrypt: add FS_I... |
552 |
if (master_key) { |
3b743b006 fscrypt: simplify... |
553 |
up_read(&master_key->sem); |
b1c0ec359 fscrypt: add FS_I... |
554 555 |
key_put(master_key); } |
a992b20cd fscrypt: add fscr... |
556 557 558 559 560 561 |
put_crypt_info(crypt_info); return res; } /** * fscrypt_get_encryption_info() - set up an inode's encryption key |
ac4acb1f4 fscrypt: handle t... |
562 |
* @inode: the inode to set up the key for. Must be encrypted. |
a7359960b fscrypt: allow de... |
563 564 565 566 567 |
* @allow_unsupported: if %true, treat an unsupported encryption policy (or * unrecognized encryption context) the same way as the key * being unavailable, instead of returning an error. Use * %false unless the operation being performed is needed in * order for files (or directories) to be deleted. |
a992b20cd fscrypt: add fscr... |
568 569 570 571 572 573 574 575 576 577 |
* * Set up ->i_crypt_info, if it hasn't already been done. * * Note: unless ->i_crypt_info is already set, this isn't %GFP_NOFS-safe. So * generally this shouldn't be called from within a filesystem transaction. * * Return: 0 if ->i_crypt_info was set or was already set, *or* if the * encryption key is unavailable. (Use fscrypt_has_encryption_key() to * distinguish these cases.) Also can return another -errno code. */ |
a7359960b fscrypt: allow de... |
578 |
int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported) |
a992b20cd fscrypt: add fscr... |
579 580 581 582 583 584 585 586 587 588 |
{ int res; union fscrypt_context ctx; union fscrypt_policy policy; if (fscrypt_has_encryption_key(inode)) return 0; res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); if (res < 0) { |
a7359960b fscrypt: allow de... |
589 590 |
if (res == -ERANGE && allow_unsupported) return 0; |
ac4acb1f4 fscrypt: handle t... |
591 592 |
fscrypt_warn(inode, "Error %d getting encryption context", res); return res; |
a992b20cd fscrypt: add fscr... |
593 594 595 596 |
} res = fscrypt_policy_from_context(&policy, &ctx, res); if (res) { |
a7359960b fscrypt: allow de... |
597 598 |
if (allow_unsupported) return 0; |
a992b20cd fscrypt: add fscr... |
599 600 601 602 |
fscrypt_warn(inode, "Unrecognized or corrupt encryption context"); return res; } |
a7359960b fscrypt: allow de... |
603 604 605 |
if (!fscrypt_supported_policy(&policy, inode)) { if (allow_unsupported) return 0; |
a992b20cd fscrypt: add fscr... |
606 |
return -EINVAL; |
a7359960b fscrypt: allow de... |
607 |
} |
a992b20cd fscrypt: add fscr... |
608 609 610 611 612 |
res = fscrypt_setup_encryption_info(inode, &policy, fscrypt_context_nonce(&ctx), IS_CASEFOLDED(inode) && S_ISDIR(inode->i_mode)); |
a7359960b fscrypt: allow de... |
613 614 615 |
if (res == -ENOPKG && allow_unsupported) /* Algorithm unavailable? */ res = 0; |
0b81d0779 fs crypto: move p... |
616 |
if (res == -ENOKEY) |
26bf3dc7e f2fs crypto: use ... |
617 |
res = 0; |
0adda907f f2fs crypto: add ... |
618 619 |
return res; } |
2c58d548f fscrypt: cache de... |
620 |
/** |
a992b20cd fscrypt: add fscr... |
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 |
* fscrypt_prepare_new_inode() - prepare to create a new inode in a directory * @dir: a possibly-encrypted directory * @inode: the new inode. ->i_mode must be set already. * ->i_ino doesn't need to be set yet. * @encrypt_ret: (output) set to %true if the new inode will be encrypted * * If the directory is encrypted, set up its ->i_crypt_info in preparation for * encrypting the name of the new file. Also, if the new inode will be * encrypted, set up its ->i_crypt_info and set *encrypt_ret=true. * * This isn't %GFP_NOFS-safe, and therefore it should be called before starting * any filesystem transaction to create the inode. For this reason, ->i_ino * isn't required to be set yet, as the filesystem may not have set it yet. * * This doesn't persist the new inode's encryption context. That still needs to * be done later by calling fscrypt_set_context(). * * Return: 0 on success, -ENOKEY if the encryption key is missing, or another * -errno code */ int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode, bool *encrypt_ret) { |
ac4acb1f4 fscrypt: handle t... |
644 |
const union fscrypt_policy *policy; |
a992b20cd fscrypt: add fscr... |
645 |
u8 nonce[FSCRYPT_FILE_NONCE_SIZE]; |
ac4acb1f4 fscrypt: handle t... |
646 647 |
policy = fscrypt_policy_to_inherit(dir); if (policy == NULL) |
a992b20cd fscrypt: add fscr... |
648 |
return 0; |
ac4acb1f4 fscrypt: handle t... |
649 650 |
if (IS_ERR(policy)) return PTR_ERR(policy); |
a992b20cd fscrypt: add fscr... |
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 |
if (WARN_ON_ONCE(inode->i_mode == 0)) return -EINVAL; /* * Only regular files, directories, and symlinks are encrypted. * Special files like device nodes and named pipes aren't. */ if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) && !S_ISLNK(inode->i_mode)) return 0; *encrypt_ret = true; get_random_bytes(nonce, FSCRYPT_FILE_NONCE_SIZE); |
ac4acb1f4 fscrypt: handle t... |
667 |
return fscrypt_setup_encryption_info(inode, policy, nonce, |
a992b20cd fscrypt: add fscr... |
668 669 670 671 672 673 |
IS_CASEFOLDED(dir) && S_ISDIR(inode->i_mode)); } EXPORT_SYMBOL_GPL(fscrypt_prepare_new_inode); /** |
d2fe97545 fscrypt: fix all ... |
674 675 |
* fscrypt_put_encryption_info() - free most of an inode's fscrypt data * @inode: an inode being evicted |
2c58d548f fscrypt: cache de... |
676 677 678 679 |
* * Free the inode's fscrypt_info. Filesystems must call this when the inode is * being evicted. An RCU grace period need not have elapsed yet. */ |
3d204e24d fscrypt: remove '... |
680 |
void fscrypt_put_encryption_info(struct inode *inode) |
0adda907f f2fs crypto: add ... |
681 |
{ |
3d204e24d fscrypt: remove '... |
682 683 |
put_crypt_info(inode->i_crypt_info); inode->i_crypt_info = NULL; |
0b81d0779 fs crypto: move p... |
684 685 |
} EXPORT_SYMBOL(fscrypt_put_encryption_info); |
2c58d548f fscrypt: cache de... |
686 687 |
/** |
d2fe97545 fscrypt: fix all ... |
688 689 |
* fscrypt_free_inode() - free an inode's fscrypt data requiring RCU delay * @inode: an inode being freed |
2c58d548f fscrypt: cache de... |
690 691 692 693 694 695 696 697 698 699 700 701 |
* * Free the inode's cached decrypted symlink target, if any. Filesystems must * call this after an RCU grace period, just before they free the inode. */ void fscrypt_free_inode(struct inode *inode) { if (IS_ENCRYPTED(inode) && S_ISLNK(inode->i_mode)) { kfree(inode->i_link); inode->i_link = NULL; } } EXPORT_SYMBOL(fscrypt_free_inode); |
b1c0ec359 fscrypt: add FS_I... |
702 703 |
/** |
d2fe97545 fscrypt: fix all ... |
704 705 |
* fscrypt_drop_inode() - check whether the inode's master key has been removed * @inode: an inode being considered for eviction |
b1c0ec359 fscrypt: add FS_I... |
706 707 708 709 710 711 712 713 714 |
* * Filesystems supporting fscrypt must call this from their ->drop_inode() * method so that encrypted inodes are evicted as soon as they're no longer in * use and their master key has been removed. * * Return: 1 if fscrypt wants the inode to be evicted now, otherwise 0 */ int fscrypt_drop_inode(struct inode *inode) { |
ab673b987 fscrypt: use smp_... |
715 |
const struct fscrypt_info *ci = fscrypt_get_info(inode); |
b1c0ec359 fscrypt: add FS_I... |
716 717 718 719 720 721 722 723 724 725 726 727 728 |
const struct fscrypt_master_key *mk; /* * If ci is NULL, then the inode doesn't have an encryption key set up * so it's irrelevant. If ci_master_key is NULL, then the master key * was provided via the legacy mechanism of the process-subscribed * keyrings, so we don't know whether it's been removed or not. */ if (!ci || !ci->ci_master_key) return 0; mk = ci->ci_master_key->payload.data[0]; /* |
2b4eae95c fscrypt: don't ev... |
729 730 731 732 733 734 735 736 737 |
* With proper, non-racy use of FS_IOC_REMOVE_ENCRYPTION_KEY, all inodes * protected by the key were cleaned by sync_filesystem(). But if * userspace is still using the files, inodes can be dirtied between * then and now. We mustn't lose any writes, so skip dirty inodes here. */ if (inode->i_state & I_DIRTY_ALL) return 0; /* |
3b743b006 fscrypt: simplify... |
738 |
* Note: since we aren't holding the key semaphore, the result here can |
b1c0ec359 fscrypt: add FS_I... |
739 740 741 742 743 744 745 746 747 |
* immediately become outdated. But there's no correctness problem with * unnecessarily evicting. Nor is there a correctness problem with not * evicting while iput() is racing with the key being removed, since * then the thread removing the key will either evict the inode itself * or will correctly detect that it wasn't evicted due to the race. */ return !is_master_key_secret_present(&mk->mk_secret); } EXPORT_SYMBOL_GPL(fscrypt_drop_inode); |