Merge remote-tracking branch 'asoc/fix/tpa6130a2' into asoc-linus
[linux/fpc-iii.git] / fs / crypto / keyinfo.c
blob1ac263eddc4ebc2fe3dacf746f370fbb1c158087
1 /*
2 * key management facility for FS encryption support.
4 * Copyright (C) 2015, Google, Inc.
6 * This contains encryption key functions.
8 * Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015.
9 */
11 #include <keys/encrypted-type.h>
12 #include <keys/user-type.h>
13 #include <linux/random.h>
14 #include <linux/scatterlist.h>
15 #include <uapi/linux/keyctl.h>
16 #include <linux/fscrypto.h>
18 static void derive_crypt_complete(struct crypto_async_request *req, int rc)
20 struct fscrypt_completion_result *ecr = req->data;
22 if (rc == -EINPROGRESS)
23 return;
25 ecr->res = rc;
26 complete(&ecr->completion);
29 /**
30 * derive_key_aes() - Derive a key using AES-128-ECB
31 * @deriving_key: Encryption key used for derivation.
32 * @source_key: Source key to which to apply derivation.
33 * @derived_key: Derived key.
35 * Return: Zero on success; non-zero otherwise.
37 static int derive_key_aes(u8 deriving_key[FS_AES_128_ECB_KEY_SIZE],
38 u8 source_key[FS_AES_256_XTS_KEY_SIZE],
39 u8 derived_key[FS_AES_256_XTS_KEY_SIZE])
41 int res = 0;
42 struct skcipher_request *req = NULL;
43 DECLARE_FS_COMPLETION_RESULT(ecr);
44 struct scatterlist src_sg, dst_sg;
45 struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0);
47 if (IS_ERR(tfm)) {
48 res = PTR_ERR(tfm);
49 tfm = NULL;
50 goto out;
52 crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
53 req = skcipher_request_alloc(tfm, GFP_NOFS);
54 if (!req) {
55 res = -ENOMEM;
56 goto out;
58 skcipher_request_set_callback(req,
59 CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
60 derive_crypt_complete, &ecr);
61 res = crypto_skcipher_setkey(tfm, deriving_key,
62 FS_AES_128_ECB_KEY_SIZE);
63 if (res < 0)
64 goto out;
66 sg_init_one(&src_sg, source_key, FS_AES_256_XTS_KEY_SIZE);
67 sg_init_one(&dst_sg, derived_key, FS_AES_256_XTS_KEY_SIZE);
68 skcipher_request_set_crypt(req, &src_sg, &dst_sg,
69 FS_AES_256_XTS_KEY_SIZE, NULL);
70 res = crypto_skcipher_encrypt(req);
71 if (res == -EINPROGRESS || res == -EBUSY) {
72 wait_for_completion(&ecr.completion);
73 res = ecr.res;
75 out:
76 skcipher_request_free(req);
77 crypto_free_skcipher(tfm);
78 return res;
81 static int validate_user_key(struct fscrypt_info *crypt_info,
82 struct fscrypt_context *ctx, u8 *raw_key,
83 u8 *prefix, int prefix_size)
85 u8 *full_key_descriptor;
86 struct key *keyring_key;
87 struct fscrypt_key *master_key;
88 const struct user_key_payload *ukp;
89 int full_key_len = prefix_size + (FS_KEY_DESCRIPTOR_SIZE * 2) + 1;
90 int res;
92 full_key_descriptor = kmalloc(full_key_len, GFP_NOFS);
93 if (!full_key_descriptor)
94 return -ENOMEM;
96 memcpy(full_key_descriptor, prefix, prefix_size);
97 sprintf(full_key_descriptor + prefix_size,
98 "%*phN", FS_KEY_DESCRIPTOR_SIZE,
99 ctx->master_key_descriptor);
100 full_key_descriptor[full_key_len - 1] = '\0';
101 keyring_key = request_key(&key_type_logon, full_key_descriptor, NULL);
102 kfree(full_key_descriptor);
103 if (IS_ERR(keyring_key))
104 return PTR_ERR(keyring_key);
106 if (keyring_key->type != &key_type_logon) {
107 printk_once(KERN_WARNING
108 "%s: key type must be logon\n", __func__);
109 res = -ENOKEY;
110 goto out;
112 down_read(&keyring_key->sem);
113 ukp = user_key_payload(keyring_key);
114 if (ukp->datalen != sizeof(struct fscrypt_key)) {
115 res = -EINVAL;
116 up_read(&keyring_key->sem);
117 goto out;
119 master_key = (struct fscrypt_key *)ukp->data;
120 BUILD_BUG_ON(FS_AES_128_ECB_KEY_SIZE != FS_KEY_DERIVATION_NONCE_SIZE);
122 if (master_key->size != FS_AES_256_XTS_KEY_SIZE) {
123 printk_once(KERN_WARNING
124 "%s: key size incorrect: %d\n",
125 __func__, master_key->size);
126 res = -ENOKEY;
127 up_read(&keyring_key->sem);
128 goto out;
130 res = derive_key_aes(ctx->nonce, master_key->raw, raw_key);
131 up_read(&keyring_key->sem);
132 if (res)
133 goto out;
135 crypt_info->ci_keyring_key = keyring_key;
136 return 0;
137 out:
138 key_put(keyring_key);
139 return res;
142 static void put_crypt_info(struct fscrypt_info *ci)
144 if (!ci)
145 return;
147 key_put(ci->ci_keyring_key);
148 crypto_free_skcipher(ci->ci_ctfm);
149 kmem_cache_free(fscrypt_info_cachep, ci);
152 int get_crypt_info(struct inode *inode)
154 struct fscrypt_info *crypt_info;
155 struct fscrypt_context ctx;
156 struct crypto_skcipher *ctfm;
157 const char *cipher_str;
158 u8 raw_key[FS_MAX_KEY_SIZE];
159 u8 mode;
160 int res;
162 res = fscrypt_initialize();
163 if (res)
164 return res;
166 if (!inode->i_sb->s_cop->get_context)
167 return -EOPNOTSUPP;
168 retry:
169 crypt_info = ACCESS_ONCE(inode->i_crypt_info);
170 if (crypt_info) {
171 if (!crypt_info->ci_keyring_key ||
172 key_validate(crypt_info->ci_keyring_key) == 0)
173 return 0;
174 fscrypt_put_encryption_info(inode, crypt_info);
175 goto retry;
178 res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
179 if (res < 0) {
180 if (!fscrypt_dummy_context_enabled(inode))
181 return res;
182 ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS;
183 ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS;
184 ctx.flags = 0;
185 } else if (res != sizeof(ctx)) {
186 return -EINVAL;
188 res = 0;
190 crypt_info = kmem_cache_alloc(fscrypt_info_cachep, GFP_NOFS);
191 if (!crypt_info)
192 return -ENOMEM;
194 crypt_info->ci_flags = ctx.flags;
195 crypt_info->ci_data_mode = ctx.contents_encryption_mode;
196 crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
197 crypt_info->ci_ctfm = NULL;
198 crypt_info->ci_keyring_key = NULL;
199 memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
200 sizeof(crypt_info->ci_master_key));
201 if (S_ISREG(inode->i_mode))
202 mode = crypt_info->ci_data_mode;
203 else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
204 mode = crypt_info->ci_filename_mode;
205 else
206 BUG();
208 switch (mode) {
209 case FS_ENCRYPTION_MODE_AES_256_XTS:
210 cipher_str = "xts(aes)";
211 break;
212 case FS_ENCRYPTION_MODE_AES_256_CTS:
213 cipher_str = "cts(cbc(aes))";
214 break;
215 default:
216 printk_once(KERN_WARNING
217 "%s: unsupported key mode %d (ino %u)\n",
218 __func__, mode, (unsigned) inode->i_ino);
219 res = -ENOKEY;
220 goto out;
222 if (fscrypt_dummy_context_enabled(inode)) {
223 memset(raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE);
224 goto got_key;
227 res = validate_user_key(crypt_info, &ctx, raw_key,
228 FS_KEY_DESC_PREFIX, FS_KEY_DESC_PREFIX_SIZE);
229 if (res && inode->i_sb->s_cop->key_prefix) {
230 u8 *prefix = NULL;
231 int prefix_size, res2;
233 prefix_size = inode->i_sb->s_cop->key_prefix(inode, &prefix);
234 res2 = validate_user_key(crypt_info, &ctx, raw_key,
235 prefix, prefix_size);
236 if (res2) {
237 if (res2 == -ENOKEY)
238 res = -ENOKEY;
239 goto out;
241 } else if (res) {
242 goto out;
244 got_key:
245 ctfm = crypto_alloc_skcipher(cipher_str, 0, 0);
246 if (!ctfm || IS_ERR(ctfm)) {
247 res = ctfm ? PTR_ERR(ctfm) : -ENOMEM;
248 printk(KERN_DEBUG
249 "%s: error %d (inode %u) allocating crypto tfm\n",
250 __func__, res, (unsigned) inode->i_ino);
251 goto out;
253 crypt_info->ci_ctfm = ctfm;
254 crypto_skcipher_clear_flags(ctfm, ~0);
255 crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY);
256 res = crypto_skcipher_setkey(ctfm, raw_key, fscrypt_key_size(mode));
257 if (res)
258 goto out;
260 memzero_explicit(raw_key, sizeof(raw_key));
261 if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) {
262 put_crypt_info(crypt_info);
263 goto retry;
265 return 0;
267 out:
268 if (res == -ENOKEY)
269 res = 0;
270 put_crypt_info(crypt_info);
271 memzero_explicit(raw_key, sizeof(raw_key));
272 return res;
275 void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci)
277 struct fscrypt_info *prev;
279 if (ci == NULL)
280 ci = ACCESS_ONCE(inode->i_crypt_info);
281 if (ci == NULL)
282 return;
284 prev = cmpxchg(&inode->i_crypt_info, ci, NULL);
285 if (prev != ci)
286 return;
288 put_crypt_info(ci);
290 EXPORT_SYMBOL(fscrypt_put_encryption_info);
292 int fscrypt_get_encryption_info(struct inode *inode)
294 struct fscrypt_info *ci = inode->i_crypt_info;
296 if (!ci ||
297 (ci->ci_keyring_key &&
298 (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
299 (1 << KEY_FLAG_REVOKED) |
300 (1 << KEY_FLAG_DEAD)))))
301 return get_crypt_info(inode);
302 return 0;
304 EXPORT_SYMBOL(fscrypt_get_encryption_info);