Blame view
fs/crypto/fname.c
12.2 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
6b3bd08f9 f2fs crypto: file... |
2 |
/* |
0b81d0779 fs crypto: move p... |
3 |
* This contains functions for filename crypto management |
6b3bd08f9 f2fs crypto: file... |
4 5 6 7 |
* * Copyright (C) 2015, Google, Inc. * Copyright (C) 2015, Motorola Mobility * |
6b3bd08f9 f2fs crypto: file... |
8 |
* Written by Uday Savagaonkar, 2014. |
0b81d0779 fs crypto: move p... |
9 |
* Modified by Jaegeuk Kim, 2015. |
6b3bd08f9 f2fs crypto: file... |
10 11 12 |
* * This has not yet undergone a rigorous security audit. */ |
0b81d0779 fs crypto: move p... |
13 |
|
6b3bd08f9 f2fs crypto: file... |
14 |
#include <linux/scatterlist.h> |
6b3bd08f9 f2fs crypto: file... |
15 |
#include <linux/ratelimit.h> |
3325bea5b fscrypt: rename g... |
16 |
#include "fscrypt_private.h" |
6b3bd08f9 f2fs crypto: file... |
17 |
|
6b3bd08f9 f2fs crypto: file... |
18 |
/** |
53fd7550e fscrypto: rename ... |
19 20 21 |
* fname_crypt_complete() - completion callback for filename crypto * @req: The asynchronous cipher request context * @res: The result of the cipher operation |
6b3bd08f9 f2fs crypto: file... |
22 |
*/ |
53fd7550e fscrypto: rename ... |
23 |
static void fname_crypt_complete(struct crypto_async_request *req, int res) |
6b3bd08f9 f2fs crypto: file... |
24 |
{ |
0b81d0779 fs crypto: move p... |
25 |
struct fscrypt_completion_result *ecr = req->data; |
6b3bd08f9 f2fs crypto: file... |
26 27 28 29 30 31 |
if (res == -EINPROGRESS) return; ecr->res = res; complete(&ecr->completion); } |
6b3bd08f9 f2fs crypto: file... |
32 |
/** |
ef1eb3aa5 fscrypto: make fi... |
33 |
* fname_encrypt() - encrypt a filename |
6b3bd08f9 f2fs crypto: file... |
34 |
* |
ef1eb3aa5 fscrypto: make fi... |
35 36 37 |
* The caller must have allocated sufficient memory for the @oname string. * * Return: 0 on success, -errno on failure |
6b3bd08f9 f2fs crypto: file... |
38 |
*/ |
0b81d0779 fs crypto: move p... |
39 40 |
static int fname_encrypt(struct inode *inode, const struct qstr *iname, struct fscrypt_str *oname) |
6b3bd08f9 f2fs crypto: file... |
41 |
{ |
2731a944f f2fs: Use skcipher |
42 |
struct skcipher_request *req = NULL; |
0b81d0779 fs crypto: move p... |
43 44 |
DECLARE_FS_COMPLETION_RESULT(ecr); struct fscrypt_info *ci = inode->i_crypt_info; |
2731a944f f2fs: Use skcipher |
45 |
struct crypto_skcipher *tfm = ci->ci_ctfm; |
6b3bd08f9 f2fs crypto: file... |
46 |
int res = 0; |
0b81d0779 fs crypto: move p... |
47 |
char iv[FS_CRYPTO_BLOCK_SIZE]; |
08ae877f4 fscrypto: don't u... |
48 |
struct scatterlist sg; |
0b81d0779 fs crypto: move p... |
49 |
int padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK); |
08ae877f4 fscrypto: don't u... |
50 51 |
unsigned int lim; unsigned int cryptlen; |
6b3bd08f9 f2fs crypto: file... |
52 |
|
0b81d0779 fs crypto: move p... |
53 |
lim = inode->i_sb->s_cop->max_namelen(inode); |
6b3bd08f9 f2fs crypto: file... |
54 55 |
if (iname->len <= 0 || iname->len > lim) return -EIO; |
08ae877f4 fscrypto: don't u... |
56 57 58 59 60 61 62 63 64 |
/* * Copy the filename to the output buffer for encrypting in-place and * pad it with the needed number of NUL bytes. */ cryptlen = max_t(unsigned int, iname->len, FS_CRYPTO_BLOCK_SIZE); cryptlen = round_up(cryptlen, padding); cryptlen = min(cryptlen, lim); memcpy(oname->name, iname->name, iname->len); memset(oname->name + iname->len, 0, cryptlen - iname->len); |
6b3bd08f9 f2fs crypto: file... |
65 |
|
08ae877f4 fscrypto: don't u... |
66 67 |
/* Initialize the IV */ memset(iv, 0, FS_CRYPTO_BLOCK_SIZE); |
6b3bd08f9 f2fs crypto: file... |
68 |
|
08ae877f4 fscrypto: don't u... |
69 |
/* Set up the encryption request */ |
2731a944f f2fs: Use skcipher |
70 |
req = skcipher_request_alloc(tfm, GFP_NOFS); |
6b3bd08f9 f2fs crypto: file... |
71 72 |
if (!req) { printk_ratelimited(KERN_ERR |
08ae877f4 fscrypto: don't u... |
73 74 |
"%s: skcipher_request_alloc() failed ", __func__); |
6b3bd08f9 f2fs crypto: file... |
75 76 |
return -ENOMEM; } |
2731a944f f2fs: Use skcipher |
77 |
skcipher_request_set_callback(req, |
6b3bd08f9 f2fs crypto: file... |
78 |
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, |
53fd7550e fscrypto: rename ... |
79 |
fname_crypt_complete, &ecr); |
08ae877f4 fscrypto: don't u... |
80 81 |
sg_init_one(&sg, oname->name, cryptlen); skcipher_request_set_crypt(req, &sg, &sg, cryptlen, iv); |
6b3bd08f9 f2fs crypto: file... |
82 |
|
08ae877f4 fscrypto: don't u... |
83 |
/* Do the encryption */ |
2731a944f f2fs: Use skcipher |
84 |
res = crypto_skcipher_encrypt(req); |
6b3bd08f9 f2fs crypto: file... |
85 |
if (res == -EINPROGRESS || res == -EBUSY) { |
08ae877f4 fscrypto: don't u... |
86 |
/* Request is being completed asynchronously; wait for it */ |
6b3bd08f9 f2fs crypto: file... |
87 88 89 |
wait_for_completion(&ecr.completion); res = ecr.res; } |
2731a944f f2fs: Use skcipher |
90 |
skcipher_request_free(req); |
ef1eb3aa5 fscrypto: make fi... |
91 |
if (res < 0) { |
6b3bd08f9 f2fs crypto: file... |
92 93 94 |
printk_ratelimited(KERN_ERR "%s: Error (error code %d) ", __func__, res); |
ef1eb3aa5 fscrypto: make fi... |
95 96 |
return res; } |
0b81d0779 fs crypto: move p... |
97 |
|
08ae877f4 fscrypto: don't u... |
98 |
oname->len = cryptlen; |
ef1eb3aa5 fscrypto: make fi... |
99 |
return 0; |
6b3bd08f9 f2fs crypto: file... |
100 |
} |
ef1eb3aa5 fscrypto: make fi... |
101 102 103 104 105 106 |
/** * fname_decrypt() - decrypt a filename * * The caller must have allocated sufficient memory for the @oname string. * * Return: 0 on success, -errno on failure |
6b3bd08f9 f2fs crypto: file... |
107 |
*/ |
0b81d0779 fs crypto: move p... |
108 109 110 |
static int fname_decrypt(struct inode *inode, const struct fscrypt_str *iname, struct fscrypt_str *oname) |
6b3bd08f9 f2fs crypto: file... |
111 |
{ |
2731a944f f2fs: Use skcipher |
112 |
struct skcipher_request *req = NULL; |
0b81d0779 fs crypto: move p... |
113 |
DECLARE_FS_COMPLETION_RESULT(ecr); |
6b3bd08f9 f2fs crypto: file... |
114 |
struct scatterlist src_sg, dst_sg; |
0b81d0779 fs crypto: move p... |
115 |
struct fscrypt_info *ci = inode->i_crypt_info; |
2731a944f f2fs: Use skcipher |
116 |
struct crypto_skcipher *tfm = ci->ci_ctfm; |
6b3bd08f9 f2fs crypto: file... |
117 |
int res = 0; |
0b81d0779 fs crypto: move p... |
118 119 |
char iv[FS_CRYPTO_BLOCK_SIZE]; unsigned lim; |
6b3bd08f9 f2fs crypto: file... |
120 |
|
0b81d0779 fs crypto: move p... |
121 |
lim = inode->i_sb->s_cop->max_namelen(inode); |
6b3bd08f9 f2fs crypto: file... |
122 123 124 125 |
if (iname->len <= 0 || iname->len > lim) return -EIO; /* Allocate request */ |
2731a944f f2fs: Use skcipher |
126 |
req = skcipher_request_alloc(tfm, GFP_NOFS); |
6b3bd08f9 f2fs crypto: file... |
127 128 129 130 131 132 |
if (!req) { printk_ratelimited(KERN_ERR "%s: crypto_request_alloc() failed ", __func__); return -ENOMEM; } |
2731a944f f2fs: Use skcipher |
133 |
skcipher_request_set_callback(req, |
6b3bd08f9 f2fs crypto: file... |
134 |
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, |
53fd7550e fscrypto: rename ... |
135 |
fname_crypt_complete, &ecr); |
6b3bd08f9 f2fs crypto: file... |
136 137 |
/* Initialize IV */ |
0b81d0779 fs crypto: move p... |
138 |
memset(iv, 0, FS_CRYPTO_BLOCK_SIZE); |
6b3bd08f9 f2fs crypto: file... |
139 140 141 142 |
/* Create decryption request */ sg_init_one(&src_sg, iname->name, iname->len); sg_init_one(&dst_sg, oname->name, oname->len); |
2731a944f f2fs: Use skcipher |
143 144 |
skcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv); res = crypto_skcipher_decrypt(req); |
6b3bd08f9 f2fs crypto: file... |
145 |
if (res == -EINPROGRESS || res == -EBUSY) { |
6b3bd08f9 f2fs crypto: file... |
146 147 148 |
wait_for_completion(&ecr.completion); res = ecr.res; } |
2731a944f f2fs: Use skcipher |
149 |
skcipher_request_free(req); |
6b3bd08f9 f2fs crypto: file... |
150 151 |
if (res < 0) { printk_ratelimited(KERN_ERR |
0b81d0779 fs crypto: move p... |
152 153 |
"%s: Error (error code %d) ", __func__, res); |
6b3bd08f9 f2fs crypto: file... |
154 155 156 157 |
return res; } oname->len = strnlen(oname->name, iname->len); |
ef1eb3aa5 fscrypto: make fi... |
158 |
return 0; |
6b3bd08f9 f2fs crypto: file... |
159 160 161 162 |
} static const char *lookup_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; |
17159420a fscrypt: introduc... |
163 |
#define BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3) |
6b3bd08f9 f2fs crypto: file... |
164 |
/** |
0b81d0779 fs crypto: move p... |
165 |
* digest_encode() - |
6b3bd08f9 f2fs crypto: file... |
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
* * Encodes the input digest using characters from the set [a-zA-Z0-9_+]. * The encoded string is roughly 4/3 times the size of the input string. */ static int digest_encode(const char *src, int len, char *dst) { int i = 0, bits = 0, ac = 0; char *cp = dst; while (i < len) { ac += (((unsigned char) src[i]) << bits); bits += 8; do { *cp++ = lookup_table[ac & 0x3f]; ac >>= 6; bits -= 6; } while (bits >= 6); i++; } if (bits) *cp++ = lookup_table[ac & 0x3f]; return cp - dst; } static int digest_decode(const char *src, int len, char *dst) { int i = 0, bits = 0, ac = 0; const char *p; char *cp = dst; while (i < len) { p = strchr(lookup_table, src[i]); if (p == NULL || src[i] == 0) return -2; ac += (p - lookup_table) << bits; bits += 6; if (bits >= 8) { *cp++ = ac & 0xff; ac >>= 8; bits -= 8; } i++; } if (ac) return -1; return cp - dst; } |
0b93e1b94 fscrypt: Constify... |
213 |
u32 fscrypt_fname_encrypted_size(const struct inode *inode, u32 ilen) |
6b3bd08f9 f2fs crypto: file... |
214 |
{ |
922ec355f f2fs crypto: avoi... |
215 |
int padding = 32; |
0b81d0779 fs crypto: move p... |
216 |
struct fscrypt_info *ci = inode->i_crypt_info; |
922ec355f f2fs crypto: avoi... |
217 218 |
if (ci) |
0b81d0779 fs crypto: move p... |
219 |
padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK); |
55be3145d fscrypto: use sta... |
220 221 |
ilen = max(ilen, (u32)FS_CRYPTO_BLOCK_SIZE); return round_up(ilen, padding); |
6b3bd08f9 f2fs crypto: file... |
222 |
} |
0b81d0779 fs crypto: move p... |
223 |
EXPORT_SYMBOL(fscrypt_fname_encrypted_size); |
6b3bd08f9 f2fs crypto: file... |
224 225 |
/** |
0b81d0779 fs crypto: move p... |
226 |
* fscrypt_fname_crypto_alloc_obuff() - |
6b3bd08f9 f2fs crypto: file... |
227 228 229 230 |
* * Allocates an output buffer that is sufficient for the crypto operation * specified by the context and the direction. */ |
0b93e1b94 fscrypt: Constify... |
231 |
int fscrypt_fname_alloc_buffer(const struct inode *inode, |
0b81d0779 fs crypto: move p... |
232 |
u32 ilen, struct fscrypt_str *crypto_str) |
6b3bd08f9 f2fs crypto: file... |
233 |
{ |
17159420a fscrypt: introduc... |
234 235 236 237 |
u32 olen = fscrypt_fname_encrypted_size(inode, ilen); const u32 max_encoded_len = max_t(u32, BASE64_CHARS(FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE), 1 + BASE64_CHARS(sizeof(struct fscrypt_digested_name))); |
6b3bd08f9 f2fs crypto: file... |
238 |
|
6b3bd08f9 f2fs crypto: file... |
239 |
crypto_str->len = olen; |
17159420a fscrypt: introduc... |
240 |
olen = max(olen, max_encoded_len); |
0b81d0779 fs crypto: move p... |
241 242 243 244 |
/* * Allocated buffer can hold one more character to null-terminate the * string */ |
6b3bd08f9 f2fs crypto: file... |
245 246 247 248 249 |
crypto_str->name = kmalloc(olen + 1, GFP_NOFS); if (!(crypto_str->name)) return -ENOMEM; return 0; } |
0b81d0779 fs crypto: move p... |
250 |
EXPORT_SYMBOL(fscrypt_fname_alloc_buffer); |
6b3bd08f9 f2fs crypto: file... |
251 252 |
/** |
0b81d0779 fs crypto: move p... |
253 |
* fscrypt_fname_crypto_free_buffer() - |
6b3bd08f9 f2fs crypto: file... |
254 255 256 |
* * Frees the buffer allocated for crypto operation. */ |
0b81d0779 fs crypto: move p... |
257 |
void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str) |
6b3bd08f9 f2fs crypto: file... |
258 259 260 261 262 263 |
{ if (!crypto_str) return; kfree(crypto_str->name); crypto_str->name = NULL; } |
0b81d0779 fs crypto: move p... |
264 |
EXPORT_SYMBOL(fscrypt_fname_free_buffer); |
6b3bd08f9 f2fs crypto: file... |
265 266 |
/** |
0b81d0779 fs crypto: move p... |
267 268 |
* fscrypt_fname_disk_to_usr() - converts a filename from disk space to user * space |
ef1eb3aa5 fscrypto: make fi... |
269 270 271 |
* * The caller must have allocated sufficient memory for the @oname string. * |
17159420a fscrypt: introduc... |
272 273 274 275 |
* If the key is available, we'll decrypt the disk name; otherwise, we'll encode * it for presentation. Short names are directly base64-encoded, while long * names are encoded in fscrypt_digested_name format. * |
ef1eb3aa5 fscrypto: make fi... |
276 |
* Return: 0 on success, -errno on failure |
6b3bd08f9 f2fs crypto: file... |
277 |
*/ |
0b81d0779 fs crypto: move p... |
278 279 280 281 |
int fscrypt_fname_disk_to_usr(struct inode *inode, u32 hash, u32 minor_hash, const struct fscrypt_str *iname, struct fscrypt_str *oname) |
6b3bd08f9 f2fs crypto: file... |
282 283 |
{ const struct qstr qname = FSTR_TO_QSTR(iname); |
17159420a fscrypt: introduc... |
284 |
struct fscrypt_digested_name digested_name; |
6b3bd08f9 f2fs crypto: file... |
285 |
|
0b81d0779 fs crypto: move p... |
286 |
if (fscrypt_is_dot_dotdot(&qname)) { |
6b3bd08f9 f2fs crypto: file... |
287 288 289 |
oname->name[0] = '.'; oname->name[iname->len - 1] = '.'; oname->len = iname->len; |
ef1eb3aa5 fscrypto: make fi... |
290 |
return 0; |
6b3bd08f9 f2fs crypto: file... |
291 |
} |
0b81d0779 fs crypto: move p... |
292 |
if (iname->len < FS_CRYPTO_BLOCK_SIZE) |
1dafa51d4 f2fs crypto: chec... |
293 |
return -EUCLEAN; |
6b3bd08f9 f2fs crypto: file... |
294 |
|
0b81d0779 fs crypto: move p... |
295 296 |
if (inode->i_crypt_info) return fname_decrypt(inode, iname, oname); |
17159420a fscrypt: introduc... |
297 |
if (iname->len <= FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE) { |
ef1eb3aa5 fscrypto: make fi... |
298 299 300 |
oname->len = digest_encode(iname->name, iname->len, oname->name); return 0; |
6b3bd08f9 f2fs crypto: file... |
301 302 |
} if (hash) { |
17159420a fscrypt: introduc... |
303 304 |
digested_name.hash = hash; digested_name.minor_hash = minor_hash; |
0b81d0779 fs crypto: move p... |
305 |
} else { |
17159420a fscrypt: introduc... |
306 307 |
digested_name.hash = 0; digested_name.minor_hash = 0; |
0b81d0779 fs crypto: move p... |
308 |
} |
17159420a fscrypt: introduc... |
309 310 311 |
memcpy(digested_name.digest, FSCRYPT_FNAME_DIGEST(iname->name, iname->len), FSCRYPT_FNAME_DIGEST_SIZE); |
6b3bd08f9 f2fs crypto: file... |
312 |
oname->name[0] = '_'; |
17159420a fscrypt: introduc... |
313 314 |
oname->len = 1 + digest_encode((const char *)&digested_name, sizeof(digested_name), oname->name + 1); |
ef1eb3aa5 fscrypto: make fi... |
315 |
return 0; |
6b3bd08f9 f2fs crypto: file... |
316 |
} |
0b81d0779 fs crypto: move p... |
317 |
EXPORT_SYMBOL(fscrypt_fname_disk_to_usr); |
6b3bd08f9 f2fs crypto: file... |
318 319 |
/** |
0b81d0779 fs crypto: move p... |
320 321 |
* fscrypt_fname_usr_to_disk() - converts a filename from user space to disk * space |
ef1eb3aa5 fscrypto: make fi... |
322 323 324 325 |
* * The caller must have allocated sufficient memory for the @oname string. * * Return: 0 on success, -errno on failure |
6b3bd08f9 f2fs crypto: file... |
326 |
*/ |
0b81d0779 fs crypto: move p... |
327 |
int fscrypt_fname_usr_to_disk(struct inode *inode, |
6b3bd08f9 f2fs crypto: file... |
328 |
const struct qstr *iname, |
0b81d0779 fs crypto: move p... |
329 |
struct fscrypt_str *oname) |
6b3bd08f9 f2fs crypto: file... |
330 |
{ |
0b81d0779 fs crypto: move p... |
331 |
if (fscrypt_is_dot_dotdot(iname)) { |
6b3bd08f9 f2fs crypto: file... |
332 333 334 |
oname->name[0] = '.'; oname->name[iname->len - 1] = '.'; oname->len = iname->len; |
ef1eb3aa5 fscrypto: make fi... |
335 |
return 0; |
6b3bd08f9 f2fs crypto: file... |
336 |
} |
0b81d0779 fs crypto: move p... |
337 338 339 340 |
if (inode->i_crypt_info) return fname_encrypt(inode, iname, oname); /* * Without a proper key, a user is not allowed to modify the filenames |
6b3bd08f9 f2fs crypto: file... |
341 |
* in a directory. Consequently, a user space name cannot be mapped to |
0b81d0779 fs crypto: move p... |
342 343 |
* a disk-space name */ |
54475f531 fscrypt: use ENOK... |
344 |
return -ENOKEY; |
6b3bd08f9 f2fs crypto: file... |
345 |
} |
0b81d0779 fs crypto: move p... |
346 |
EXPORT_SYMBOL(fscrypt_fname_usr_to_disk); |
6b3bd08f9 f2fs crypto: file... |
347 |
|
17159420a fscrypt: introduc... |
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
/** * fscrypt_setup_filename() - prepare to search a possibly encrypted directory * @dir: the directory that will be searched * @iname: the user-provided filename being searched for * @lookup: 1 if we're allowed to proceed without the key because it's * ->lookup() or we're finding the dir_entry for deletion; 0 if we cannot * proceed without the key because we're going to create the dir_entry. * @fname: the filename information to be filled in * * Given a user-provided filename @iname, this function sets @fname->disk_name * to the name that would be stored in the on-disk directory entry, if possible. * If the directory is unencrypted this is simply @iname. Else, if we have the * directory's encryption key, then @iname is the plaintext, so we encrypt it to * get the disk_name. * * Else, for keyless @lookup operations, @iname is the presented ciphertext, so * we decode it to get either the ciphertext disk_name (for short names) or the * fscrypt_digested_name (for long names). Non-@lookup operations will be * impossible in this case, so we fail them with ENOKEY. * * If successful, fscrypt_free_filename() must be called later to clean up. * * Return: 0 on success, -errno on failure */ |
0b81d0779 fs crypto: move p... |
372 373 |
int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, int lookup, struct fscrypt_name *fname) |
6b3bd08f9 f2fs crypto: file... |
374 |
{ |
17159420a fscrypt: introduc... |
375 376 |
int ret; int digested; |
6b3bd08f9 f2fs crypto: file... |
377 |
|
0b81d0779 fs crypto: move p... |
378 |
memset(fname, 0, sizeof(struct fscrypt_name)); |
6b3bd08f9 f2fs crypto: file... |
379 |
fname->usr_fname = iname; |
0b81d0779 fs crypto: move p... |
380 381 |
if (!dir->i_sb->s_cop->is_encrypted(dir) || fscrypt_is_dot_dotdot(iname)) { |
6b3bd08f9 f2fs crypto: file... |
382 383 |
fname->disk_name.name = (unsigned char *)iname->name; fname->disk_name.len = iname->len; |
7bf4b5576 f2fs crypto: fix ... |
384 |
return 0; |
6b3bd08f9 f2fs crypto: file... |
385 |
} |
1b53cf981 fscrypt: remove b... |
386 |
ret = fscrypt_get_encryption_info(dir); |
0b81d0779 fs crypto: move p... |
387 |
if (ret && ret != -EOPNOTSUPP) |
6b3bd08f9 f2fs crypto: file... |
388 |
return ret; |
0b81d0779 fs crypto: move p... |
389 390 391 392 |
if (dir->i_crypt_info) { ret = fscrypt_fname_alloc_buffer(dir, iname->len, &fname->crypto_buf); |
ef1eb3aa5 fscrypto: make fi... |
393 |
if (ret) |
7bf4b5576 f2fs crypto: fix ... |
394 |
return ret; |
0b81d0779 fs crypto: move p... |
395 |
ret = fname_encrypt(dir, iname, &fname->crypto_buf); |
ef1eb3aa5 fscrypto: make fi... |
396 |
if (ret) |
e5e0906b6 f2fs crypto: clea... |
397 |
goto errout; |
6b3bd08f9 f2fs crypto: file... |
398 399 |
fname->disk_name.name = fname->crypto_buf.name; fname->disk_name.len = fname->crypto_buf.len; |
7bf4b5576 f2fs crypto: fix ... |
400 |
return 0; |
6b3bd08f9 f2fs crypto: file... |
401 |
} |
e5e0906b6 f2fs crypto: clea... |
402 |
if (!lookup) |
54475f531 fscrypt: use ENOK... |
403 |
return -ENOKEY; |
6b3bd08f9 f2fs crypto: file... |
404 |
|
0b81d0779 fs crypto: move p... |
405 406 |
/* * We don't have the key and we are doing a lookup; decode the |
6b3bd08f9 f2fs crypto: file... |
407 408 |
* user-supplied name */ |
17159420a fscrypt: introduc... |
409 410 411 412 413 414 415 416 417 418 419 |
if (iname->name[0] == '_') { if (iname->len != 1 + BASE64_CHARS(sizeof(struct fscrypt_digested_name))) return -ENOENT; digested = 1; } else { if (iname->len > BASE64_CHARS(FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE)) return -ENOENT; digested = 0; } |
e5e0906b6 f2fs crypto: clea... |
420 |
|
17159420a fscrypt: introduc... |
421 422 423 424 |
fname->crypto_buf.name = kmalloc(max_t(size_t, FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE, sizeof(struct fscrypt_digested_name)), GFP_KERNEL); |
e5e0906b6 f2fs crypto: clea... |
425 426 |
if (fname->crypto_buf.name == NULL) return -ENOMEM; |
0b81d0779 fs crypto: move p... |
427 |
|
17159420a fscrypt: introduc... |
428 |
ret = digest_decode(iname->name + digested, iname->len - digested, |
6b3bd08f9 f2fs crypto: file... |
429 430 431 |
fname->crypto_buf.name); if (ret < 0) { ret = -ENOENT; |
e5e0906b6 f2fs crypto: clea... |
432 |
goto errout; |
6b3bd08f9 f2fs crypto: file... |
433 434 |
} fname->crypto_buf.len = ret; |
17159420a fscrypt: introduc... |
435 436 437 438 439 |
if (digested) { const struct fscrypt_digested_name *n = (const void *)fname->crypto_buf.name; fname->hash = n->hash; fname->minor_hash = n->minor_hash; |
6b3bd08f9 f2fs crypto: file... |
440 441 442 443 |
} else { fname->disk_name.name = fname->crypto_buf.name; fname->disk_name.len = fname->crypto_buf.len; } |
7bf4b5576 f2fs crypto: fix ... |
444 |
return 0; |
0b81d0779 fs crypto: move p... |
445 |
|
e5e0906b6 f2fs crypto: clea... |
446 |
errout: |
0b81d0779 fs crypto: move p... |
447 |
fscrypt_fname_free_buffer(&fname->crypto_buf); |
6b3bd08f9 f2fs crypto: file... |
448 449 |
return ret; } |
0b81d0779 fs crypto: move p... |
450 |
EXPORT_SYMBOL(fscrypt_setup_filename); |