1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Key setup for v1 encryption policies |
4 | * |
5 | * Copyright 2015, 2019 Google LLC |
6 | */ |
7 | |
8 | /* |
9 | * This file implements compatibility functions for the original encryption |
10 | * policy version ("v1"), including: |
11 | * |
12 | * - Deriving per-file encryption keys using the AES-128-ECB based KDF |
13 | * (rather than the new method of using HKDF-SHA512) |
14 | * |
15 | * - Retrieving fscrypt master keys from process-subscribed keyrings |
16 | * (rather than the new method of using a filesystem-level keyring) |
17 | * |
18 | * - Handling policies with the DIRECT_KEY flag set using a master key table |
19 | * (rather than the new method of implementing DIRECT_KEY with per-mode keys |
20 | * managed alongside the master keys in the filesystem-level keyring) |
21 | */ |
22 | |
23 | #include <crypto/skcipher.h> |
24 | #include <crypto/utils.h> |
25 | #include <keys/user-type.h> |
26 | #include <linux/hashtable.h> |
27 | #include <linux/scatterlist.h> |
28 | |
29 | #include "fscrypt_private.h" |
30 | |
31 | /* Table of keys referenced by DIRECT_KEY policies */ |
32 | static DEFINE_HASHTABLE(fscrypt_direct_keys, 6); /* 6 bits = 64 buckets */ |
33 | static DEFINE_SPINLOCK(fscrypt_direct_keys_lock); |
34 | |
35 | /* |
36 | * v1 key derivation function. This generates the derived key by encrypting the |
37 | * master key with AES-128-ECB using the nonce as the AES key. This provides a |
38 | * unique derived key with sufficient entropy for each inode. However, it's |
39 | * nonstandard, non-extensible, doesn't evenly distribute the entropy from the |
40 | * master key, and is trivially reversible: an attacker who compromises a |
41 | * derived key can "decrypt" it to get back to the master key, then derive any |
42 | * other key. For all new code, use HKDF instead. |
43 | * |
44 | * The master key must be at least as long as the derived key. If the master |
45 | * key is longer, then only the first 'derived_keysize' bytes are used. |
46 | */ |
47 | static int derive_key_aes(const u8 *master_key, |
48 | const u8 nonce[FSCRYPT_FILE_NONCE_SIZE], |
49 | u8 *derived_key, unsigned int derived_keysize) |
50 | { |
51 | int res = 0; |
52 | struct skcipher_request *req = NULL; |
53 | DECLARE_CRYPTO_WAIT(wait); |
54 | struct scatterlist src_sg, dst_sg; |
55 | struct crypto_skcipher *tfm = crypto_alloc_skcipher(alg_name: "ecb(aes)" , type: 0, mask: 0); |
56 | |
57 | if (IS_ERR(ptr: tfm)) { |
58 | res = PTR_ERR(ptr: tfm); |
59 | tfm = NULL; |
60 | goto out; |
61 | } |
62 | crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); |
63 | req = skcipher_request_alloc(tfm, GFP_KERNEL); |
64 | if (!req) { |
65 | res = -ENOMEM; |
66 | goto out; |
67 | } |
68 | skcipher_request_set_callback(req, |
69 | CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, |
70 | compl: crypto_req_done, data: &wait); |
71 | res = crypto_skcipher_setkey(tfm, key: nonce, FSCRYPT_FILE_NONCE_SIZE); |
72 | if (res < 0) |
73 | goto out; |
74 | |
75 | sg_init_one(&src_sg, master_key, derived_keysize); |
76 | sg_init_one(&dst_sg, derived_key, derived_keysize); |
77 | skcipher_request_set_crypt(req, src: &src_sg, dst: &dst_sg, cryptlen: derived_keysize, |
78 | NULL); |
79 | res = crypto_wait_req(err: crypto_skcipher_encrypt(req), wait: &wait); |
80 | out: |
81 | skcipher_request_free(req); |
82 | crypto_free_skcipher(tfm); |
83 | return res; |
84 | } |
85 | |
86 | /* |
87 | * Search the current task's subscribed keyrings for a "logon" key with |
88 | * description prefix:descriptor, and if found acquire a read lock on it and |
89 | * return a pointer to its validated payload in *payload_ret. |
90 | */ |
91 | static struct key * |
92 | find_and_lock_process_key(const char *prefix, |
93 | const u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE], |
94 | unsigned int min_keysize, |
95 | const struct fscrypt_key **payload_ret) |
96 | { |
97 | char *description; |
98 | struct key *key; |
99 | const struct user_key_payload *ukp; |
100 | const struct fscrypt_key *payload; |
101 | |
102 | description = kasprintf(GFP_KERNEL, fmt: "%s%*phN" , prefix, |
103 | FSCRYPT_KEY_DESCRIPTOR_SIZE, descriptor); |
104 | if (!description) |
105 | return ERR_PTR(error: -ENOMEM); |
106 | |
107 | key = request_key(type: &key_type_logon, description, NULL); |
108 | kfree(objp: description); |
109 | if (IS_ERR(ptr: key)) |
110 | return key; |
111 | |
112 | down_read(sem: &key->sem); |
113 | ukp = user_key_payload_locked(key); |
114 | |
115 | if (!ukp) /* was the key revoked before we acquired its semaphore? */ |
116 | goto invalid; |
117 | |
118 | payload = (const struct fscrypt_key *)ukp->data; |
119 | |
120 | if (ukp->datalen != sizeof(struct fscrypt_key) || |
121 | payload->size < 1 || payload->size > FSCRYPT_MAX_KEY_SIZE) { |
122 | fscrypt_warn(NULL, |
123 | "key with description '%s' has invalid payload" , |
124 | key->description); |
125 | goto invalid; |
126 | } |
127 | |
128 | if (payload->size < min_keysize) { |
129 | fscrypt_warn(NULL, |
130 | "key with description '%s' is too short (got %u bytes, need %u+ bytes)" , |
131 | key->description, payload->size, min_keysize); |
132 | goto invalid; |
133 | } |
134 | |
135 | *payload_ret = payload; |
136 | return key; |
137 | |
138 | invalid: |
139 | up_read(sem: &key->sem); |
140 | key_put(key); |
141 | return ERR_PTR(error: -ENOKEY); |
142 | } |
143 | |
144 | /* Master key referenced by DIRECT_KEY policy */ |
145 | struct fscrypt_direct_key { |
146 | struct super_block *dk_sb; |
147 | struct hlist_node dk_node; |
148 | refcount_t dk_refcount; |
149 | const struct fscrypt_mode *dk_mode; |
150 | struct fscrypt_prepared_key dk_key; |
151 | u8 dk_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; |
152 | u8 dk_raw[FSCRYPT_MAX_KEY_SIZE]; |
153 | }; |
154 | |
155 | static void free_direct_key(struct fscrypt_direct_key *dk) |
156 | { |
157 | if (dk) { |
158 | fscrypt_destroy_prepared_key(sb: dk->dk_sb, prep_key: &dk->dk_key); |
159 | kfree_sensitive(objp: dk); |
160 | } |
161 | } |
162 | |
163 | void fscrypt_put_direct_key(struct fscrypt_direct_key *dk) |
164 | { |
165 | if (!refcount_dec_and_lock(r: &dk->dk_refcount, lock: &fscrypt_direct_keys_lock)) |
166 | return; |
167 | hash_del(node: &dk->dk_node); |
168 | spin_unlock(lock: &fscrypt_direct_keys_lock); |
169 | |
170 | free_direct_key(dk); |
171 | } |
172 | |
173 | /* |
174 | * Find/insert the given key into the fscrypt_direct_keys table. If found, it |
175 | * is returned with elevated refcount, and 'to_insert' is freed if non-NULL. If |
176 | * not found, 'to_insert' is inserted and returned if it's non-NULL; otherwise |
177 | * NULL is returned. |
178 | */ |
179 | static struct fscrypt_direct_key * |
180 | find_or_insert_direct_key(struct fscrypt_direct_key *to_insert, |
181 | const u8 *raw_key, |
182 | const struct fscrypt_inode_info *ci) |
183 | { |
184 | unsigned long hash_key; |
185 | struct fscrypt_direct_key *dk; |
186 | |
187 | /* |
188 | * Careful: to avoid potentially leaking secret key bytes via timing |
189 | * information, we must key the hash table by descriptor rather than by |
190 | * raw key, and use crypto_memneq() when comparing raw keys. |
191 | */ |
192 | |
193 | BUILD_BUG_ON(sizeof(hash_key) > FSCRYPT_KEY_DESCRIPTOR_SIZE); |
194 | memcpy(&hash_key, ci->ci_policy.v1.master_key_descriptor, |
195 | sizeof(hash_key)); |
196 | |
197 | spin_lock(lock: &fscrypt_direct_keys_lock); |
198 | hash_for_each_possible(fscrypt_direct_keys, dk, dk_node, hash_key) { |
199 | if (memcmp(p: ci->ci_policy.v1.master_key_descriptor, |
200 | q: dk->dk_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0) |
201 | continue; |
202 | if (ci->ci_mode != dk->dk_mode) |
203 | continue; |
204 | if (!fscrypt_is_key_prepared(prep_key: &dk->dk_key, ci)) |
205 | continue; |
206 | if (crypto_memneq(a: raw_key, b: dk->dk_raw, size: ci->ci_mode->keysize)) |
207 | continue; |
208 | /* using existing tfm with same (descriptor, mode, raw_key) */ |
209 | refcount_inc(r: &dk->dk_refcount); |
210 | spin_unlock(lock: &fscrypt_direct_keys_lock); |
211 | free_direct_key(dk: to_insert); |
212 | return dk; |
213 | } |
214 | if (to_insert) |
215 | hash_add(fscrypt_direct_keys, &to_insert->dk_node, hash_key); |
216 | spin_unlock(lock: &fscrypt_direct_keys_lock); |
217 | return to_insert; |
218 | } |
219 | |
220 | /* Prepare to encrypt directly using the master key in the given mode */ |
221 | static struct fscrypt_direct_key * |
222 | fscrypt_get_direct_key(const struct fscrypt_inode_info *ci, const u8 *raw_key) |
223 | { |
224 | struct fscrypt_direct_key *dk; |
225 | int err; |
226 | |
227 | /* Is there already a tfm for this key? */ |
228 | dk = find_or_insert_direct_key(NULL, raw_key, ci); |
229 | if (dk) |
230 | return dk; |
231 | |
232 | /* Nope, allocate one. */ |
233 | dk = kzalloc(size: sizeof(*dk), GFP_KERNEL); |
234 | if (!dk) |
235 | return ERR_PTR(error: -ENOMEM); |
236 | dk->dk_sb = ci->ci_inode->i_sb; |
237 | refcount_set(r: &dk->dk_refcount, n: 1); |
238 | dk->dk_mode = ci->ci_mode; |
239 | err = fscrypt_prepare_key(prep_key: &dk->dk_key, raw_key, ci); |
240 | if (err) |
241 | goto err_free_dk; |
242 | memcpy(dk->dk_descriptor, ci->ci_policy.v1.master_key_descriptor, |
243 | FSCRYPT_KEY_DESCRIPTOR_SIZE); |
244 | memcpy(dk->dk_raw, raw_key, ci->ci_mode->keysize); |
245 | |
246 | return find_or_insert_direct_key(to_insert: dk, raw_key, ci); |
247 | |
248 | err_free_dk: |
249 | free_direct_key(dk); |
250 | return ERR_PTR(error: err); |
251 | } |
252 | |
253 | /* v1 policy, DIRECT_KEY: use the master key directly */ |
254 | static int setup_v1_file_key_direct(struct fscrypt_inode_info *ci, |
255 | const u8 *raw_master_key) |
256 | { |
257 | struct fscrypt_direct_key *dk; |
258 | |
259 | dk = fscrypt_get_direct_key(ci, raw_key: raw_master_key); |
260 | if (IS_ERR(ptr: dk)) |
261 | return PTR_ERR(ptr: dk); |
262 | ci->ci_direct_key = dk; |
263 | ci->ci_enc_key = dk->dk_key; |
264 | return 0; |
265 | } |
266 | |
267 | /* v1 policy, !DIRECT_KEY: derive the file's encryption key */ |
268 | static int setup_v1_file_key_derived(struct fscrypt_inode_info *ci, |
269 | const u8 *raw_master_key) |
270 | { |
271 | u8 *derived_key; |
272 | int err; |
273 | |
274 | /* |
275 | * This cannot be a stack buffer because it will be passed to the |
276 | * scatterlist crypto API during derive_key_aes(). |
277 | */ |
278 | derived_key = kmalloc(size: ci->ci_mode->keysize, GFP_KERNEL); |
279 | if (!derived_key) |
280 | return -ENOMEM; |
281 | |
282 | err = derive_key_aes(master_key: raw_master_key, nonce: ci->ci_nonce, |
283 | derived_key, derived_keysize: ci->ci_mode->keysize); |
284 | if (err) |
285 | goto out; |
286 | |
287 | err = fscrypt_set_per_file_enc_key(ci, raw_key: derived_key); |
288 | out: |
289 | kfree_sensitive(objp: derived_key); |
290 | return err; |
291 | } |
292 | |
293 | int fscrypt_setup_v1_file_key(struct fscrypt_inode_info *ci, |
294 | const u8 *raw_master_key) |
295 | { |
296 | if (ci->ci_policy.v1.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) |
297 | return setup_v1_file_key_direct(ci, raw_master_key); |
298 | else |
299 | return setup_v1_file_key_derived(ci, raw_master_key); |
300 | } |
301 | |
302 | int |
303 | fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_inode_info *ci) |
304 | { |
305 | const struct super_block *sb = ci->ci_inode->i_sb; |
306 | struct key *key; |
307 | const struct fscrypt_key *payload; |
308 | int err; |
309 | |
310 | key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX, |
311 | descriptor: ci->ci_policy.v1.master_key_descriptor, |
312 | min_keysize: ci->ci_mode->keysize, payload_ret: &payload); |
313 | if (key == ERR_PTR(error: -ENOKEY) && sb->s_cop->legacy_key_prefix) { |
314 | key = find_and_lock_process_key(prefix: sb->s_cop->legacy_key_prefix, |
315 | descriptor: ci->ci_policy.v1.master_key_descriptor, |
316 | min_keysize: ci->ci_mode->keysize, payload_ret: &payload); |
317 | } |
318 | if (IS_ERR(ptr: key)) |
319 | return PTR_ERR(ptr: key); |
320 | |
321 | err = fscrypt_setup_v1_file_key(ci, raw_master_key: payload->raw); |
322 | up_read(sem: &key->sem); |
323 | key_put(key); |
324 | return err; |
325 | } |
326 | |