blob: d9f08ddbfda2570d4acddb81dac6774bb9a97741 [file] [log] [blame]
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -04001/*
2 * linux/fs/ext4/crypto_fname.c
3 *
4 * Copyright (C) 2015, Google, Inc.
5 *
6 * This contains functions for filename crypto management in ext4
7 *
8 * Written by Uday Savagaonkar, 2014.
9 *
10 * This has not yet undergone a rigorous security audit.
11 *
12 */
13
14#include <crypto/hash.h>
15#include <crypto/sha.h>
16#include <keys/encrypted-type.h>
17#include <keys/user-type.h>
18#include <linux/crypto.h>
19#include <linux/gfp.h>
20#include <linux/kernel.h>
21#include <linux/key.h>
22#include <linux/key.h>
23#include <linux/list.h>
24#include <linux/mempool.h>
25#include <linux/random.h>
26#include <linux/scatterlist.h>
27#include <linux/spinlock_types.h>
28
29#include "ext4.h"
30#include "ext4_crypto.h"
31#include "xattr.h"
32
33/**
34 * ext4_dir_crypt_complete() -
35 */
36static void ext4_dir_crypt_complete(struct crypto_async_request *req, int res)
37{
38 struct ext4_completion_result *ecr = req->data;
39
40 if (res == -EINPROGRESS)
41 return;
42 ecr->res = res;
43 complete(&ecr->completion);
44}
45
46bool ext4_valid_filenames_enc_mode(uint32_t mode)
47{
48 return (mode == EXT4_ENCRYPTION_MODE_AES_256_CTS);
49}
50
51/**
52 * ext4_fname_encrypt() -
53 *
54 * This function encrypts the input filename, and returns the length of the
55 * ciphertext. Errors are returned as negative numbers. We trust the caller to
56 * allocate sufficient memory to oname string.
57 */
58static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
59 const struct qstr *iname,
60 struct ext4_str *oname)
61{
62 u32 ciphertext_len;
63 struct ablkcipher_request *req = NULL;
64 DECLARE_EXT4_COMPLETION_RESULT(ecr);
65 struct crypto_ablkcipher *tfm = ctx->ctfm;
66 int res = 0;
67 char iv[EXT4_CRYPTO_BLOCK_SIZE];
Theodore Ts'od2299592015-05-18 13:15:47 -040068 struct scatterlist src_sg, dst_sg;
Theodore Ts'oa44cd7a2015-05-01 16:56:50 -040069 int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
Theodore Ts'od2299592015-05-18 13:15:47 -040070 char *workbuf, buf[32], *alloc_buf = NULL;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -040071
72 if (iname->len <= 0 || iname->len > ctx->lim)
73 return -EIO;
74
75 ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ?
76 EXT4_CRYPTO_BLOCK_SIZE : iname->len;
Theodore Ts'oa44cd7a2015-05-01 16:56:50 -040077 ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -040078 ciphertext_len = (ciphertext_len > ctx->lim)
79 ? ctx->lim : ciphertext_len;
80
Theodore Ts'od2299592015-05-18 13:15:47 -040081 if (ciphertext_len <= sizeof(buf)) {
82 workbuf = buf;
83 } else {
84 alloc_buf = kmalloc(ciphertext_len, GFP_NOFS);
85 if (!alloc_buf)
86 return -ENOMEM;
87 workbuf = alloc_buf;
88 }
89
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -040090 /* Allocate request */
91 req = ablkcipher_request_alloc(tfm, GFP_NOFS);
92 if (!req) {
93 printk_ratelimited(
94 KERN_ERR "%s: crypto_request_alloc() failed\n", __func__);
Theodore Ts'od2299592015-05-18 13:15:47 -040095 kfree(alloc_buf);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -040096 return -ENOMEM;
97 }
98 ablkcipher_request_set_callback(req,
99 CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
100 ext4_dir_crypt_complete, &ecr);
101
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400102 /* Copy the input */
103 memcpy(workbuf, iname->name, iname->len);
104 if (iname->len < ciphertext_len)
105 memset(workbuf + iname->len, 0, ciphertext_len - iname->len);
106
107 /* Initialize IV */
108 memset(iv, 0, EXT4_CRYPTO_BLOCK_SIZE);
109
110 /* Create encryption request */
Theodore Ts'od2299592015-05-18 13:15:47 -0400111 sg_init_one(&src_sg, workbuf, ciphertext_len);
112 sg_init_one(&dst_sg, oname->name, ciphertext_len);
113 ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400114 res = crypto_ablkcipher_encrypt(req);
115 if (res == -EINPROGRESS || res == -EBUSY) {
116 BUG_ON(req->base.data != &ecr);
117 wait_for_completion(&ecr.completion);
118 res = ecr.res;
119 }
Theodore Ts'od2299592015-05-18 13:15:47 -0400120 kfree(alloc_buf);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400121 ablkcipher_request_free(req);
122 if (res < 0) {
123 printk_ratelimited(
124 KERN_ERR "%s: Error (error code %d)\n", __func__, res);
125 }
126 oname->len = ciphertext_len;
127 return res;
128}
129
130/*
131 * ext4_fname_decrypt()
132 * This function decrypts the input filename, and returns
133 * the length of the plaintext.
134 * Errors are returned as negative numbers.
135 * We trust the caller to allocate sufficient memory to oname string.
136 */
137static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx,
138 const struct ext4_str *iname,
139 struct ext4_str *oname)
140{
141 struct ext4_str tmp_in[2], tmp_out[1];
142 struct ablkcipher_request *req = NULL;
143 DECLARE_EXT4_COMPLETION_RESULT(ecr);
Theodore Ts'od2299592015-05-18 13:15:47 -0400144 struct scatterlist src_sg, dst_sg;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400145 struct crypto_ablkcipher *tfm = ctx->ctfm;
146 int res = 0;
147 char iv[EXT4_CRYPTO_BLOCK_SIZE];
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400148
149 if (iname->len <= 0 || iname->len > ctx->lim)
150 return -EIO;
151
152 tmp_in[0].name = iname->name;
153 tmp_in[0].len = iname->len;
154 tmp_out[0].name = oname->name;
155
156 /* Allocate request */
157 req = ablkcipher_request_alloc(tfm, GFP_NOFS);
158 if (!req) {
159 printk_ratelimited(
160 KERN_ERR "%s: crypto_request_alloc() failed\n", __func__);
161 return -ENOMEM;
162 }
163 ablkcipher_request_set_callback(req,
164 CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
165 ext4_dir_crypt_complete, &ecr);
166
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400167 /* Initialize IV */
168 memset(iv, 0, EXT4_CRYPTO_BLOCK_SIZE);
169
170 /* Create encryption request */
Theodore Ts'od2299592015-05-18 13:15:47 -0400171 sg_init_one(&src_sg, iname->name, iname->len);
172 sg_init_one(&dst_sg, oname->name, oname->len);
173 ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400174 res = crypto_ablkcipher_decrypt(req);
175 if (res == -EINPROGRESS || res == -EBUSY) {
176 BUG_ON(req->base.data != &ecr);
177 wait_for_completion(&ecr.completion);
178 res = ecr.res;
179 }
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400180 ablkcipher_request_free(req);
181 if (res < 0) {
182 printk_ratelimited(
183 KERN_ERR "%s: Error in ext4_fname_encrypt (error code %d)\n",
184 __func__, res);
185 return res;
186 }
187
188 oname->len = strnlen(oname->name, iname->len);
189 return oname->len;
190}
191
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400192static const char *lookup_table =
193 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
194
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400195/**
196 * ext4_fname_encode_digest() -
197 *
198 * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
199 * The encoded string is roughly 4/3 times the size of the input string.
200 */
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400201static int digest_encode(const char *src, int len, char *dst)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400202{
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400203 int i = 0, bits = 0, ac = 0;
204 char *cp = dst;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400205
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400206 while (i < len) {
207 ac += (((unsigned char) src[i]) << bits);
208 bits += 8;
209 do {
210 *cp++ = lookup_table[ac & 0x3f];
211 ac >>= 6;
212 bits -= 6;
213 } while (bits >= 6);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400214 i++;
215 }
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400216 if (bits)
217 *cp++ = lookup_table[ac & 0x3f];
218 return cp - dst;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400219}
220
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400221static int digest_decode(const char *src, int len, char *dst)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400222{
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400223 int i = 0, bits = 0, ac = 0;
224 const char *p;
225 char *cp = dst;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400226
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400227 while (i < len) {
228 p = strchr(lookup_table, src[i]);
229 if (p == NULL || src[i] == 0)
230 return -2;
231 ac += (p - lookup_table) << bits;
232 bits += 6;
233 if (bits >= 8) {
234 *cp++ = ac & 0xff;
235 ac >>= 8;
236 bits -= 8;
237 }
238 i++;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400239 }
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400240 if (ac)
241 return -1;
242 return cp - dst;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400243}
244
245/**
246 * ext4_free_fname_crypto_ctx() -
247 *
248 * Frees up a crypto context.
249 */
250void ext4_free_fname_crypto_ctx(struct ext4_fname_crypto_ctx *ctx)
251{
252 if (ctx == NULL || IS_ERR(ctx))
253 return;
254
255 if (ctx->ctfm && !IS_ERR(ctx->ctfm))
256 crypto_free_ablkcipher(ctx->ctfm);
257 if (ctx->htfm && !IS_ERR(ctx->htfm))
258 crypto_free_hash(ctx->htfm);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400259 kfree(ctx);
260}
261
262/**
263 * ext4_put_fname_crypto_ctx() -
264 *
265 * Return: The crypto context onto free list. If the free list is above a
266 * threshold, completely frees up the context, and returns the memory.
267 *
268 * TODO: Currently we directly free the crypto context. Eventually we should
269 * add code it to return to free list. Such an approach will increase
270 * efficiency of directory lookup.
271 */
272void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx)
273{
274 if (*ctx == NULL || IS_ERR(*ctx))
275 return;
276 ext4_free_fname_crypto_ctx(*ctx);
277 *ctx = NULL;
278}
279
280/**
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400281 * ext4_alloc_fname_crypto_ctx() -
282 */
283struct ext4_fname_crypto_ctx *ext4_alloc_fname_crypto_ctx(
Theodore Ts'oe2881b1b2015-05-18 13:16:47 -0400284 const struct ext4_crypt_info *ci)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400285{
286 struct ext4_fname_crypto_ctx *ctx;
287
288 ctx = kmalloc(sizeof(struct ext4_fname_crypto_ctx), GFP_NOFS);
289 if (ctx == NULL)
290 return ERR_PTR(-ENOMEM);
Theodore Ts'oe2881b1b2015-05-18 13:16:47 -0400291 if (ci->ci_mode == EXT4_ENCRYPTION_MODE_INVALID) {
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400292 /* This will automatically set key mode to invalid
293 * As enum for ENCRYPTION_MODE_INVALID is zero */
Theodore Ts'oe2881b1b2015-05-18 13:16:47 -0400294 memset(&ctx->ci, 0, sizeof(ctx->ci));
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400295 } else {
Theodore Ts'oe2881b1b2015-05-18 13:16:47 -0400296 memcpy(&ctx->ci, ci, sizeof(struct ext4_crypt_info));
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400297 }
Theodore Ts'oe2881b1b2015-05-18 13:16:47 -0400298 ctx->has_valid_key = (EXT4_ENCRYPTION_MODE_INVALID == ci->ci_mode)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400299 ? 0 : 1;
300 ctx->ctfm_key_is_ready = 0;
301 ctx->ctfm = NULL;
302 ctx->htfm = NULL;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400303 return ctx;
304}
305
306/**
307 * ext4_get_fname_crypto_ctx() -
308 *
309 * Allocates a free crypto context and initializes it to hold
310 * the crypto material for the inode.
311 *
312 * Return: NULL if not encrypted. Error value on error. Valid pointer otherwise.
313 */
314struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
315 struct inode *inode, u32 max_ciphertext_len)
316{
317 struct ext4_fname_crypto_ctx *ctx;
318 struct ext4_inode_info *ei = EXT4_I(inode);
319 int res;
320
321 /* Check if the crypto policy is set on the inode */
322 res = ext4_encrypted_inode(inode);
323 if (res == 0)
324 return NULL;
325
326 if (!ext4_has_encryption_key(inode))
327 ext4_generate_encryption_key(inode);
328
Theodore Ts'oe2881b1b2015-05-18 13:16:47 -0400329 /* Get a crypto context based on the key. */
330 ctx = ext4_alloc_fname_crypto_ctx(&(ei->i_crypt_info));
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400331 if (IS_ERR(ctx))
332 return ctx;
333
Theodore Ts'oa44cd7a2015-05-01 16:56:50 -0400334 ctx->flags = ei->i_crypt_policy_flags;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400335 if (ctx->has_valid_key) {
Theodore Ts'oe2881b1b2015-05-18 13:16:47 -0400336 if (ctx->ci.ci_mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400337 printk_once(KERN_WARNING
338 "ext4: unsupported key mode %d\n",
Theodore Ts'oe2881b1b2015-05-18 13:16:47 -0400339 ctx->ci.ci_mode);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400340 return ERR_PTR(-ENOKEY);
341 }
342
343 /* As a first cut, we will allocate new tfm in every call.
344 * later, we will keep the tfm around, in case the key gets
345 * re-used */
346 if (ctx->ctfm == NULL) {
347 ctx->ctfm = crypto_alloc_ablkcipher("cts(cbc(aes))",
348 0, 0);
349 }
350 if (IS_ERR(ctx->ctfm)) {
351 res = PTR_ERR(ctx->ctfm);
352 printk(
353 KERN_DEBUG "%s: error (%d) allocating crypto tfm\n",
354 __func__, res);
355 ctx->ctfm = NULL;
356 ext4_put_fname_crypto_ctx(&ctx);
357 return ERR_PTR(res);
358 }
359 if (ctx->ctfm == NULL) {
360 printk(
361 KERN_DEBUG "%s: could not allocate crypto tfm\n",
362 __func__);
363 ext4_put_fname_crypto_ctx(&ctx);
364 return ERR_PTR(-ENOMEM);
365 }
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400366 ctx->lim = max_ciphertext_len;
367 crypto_ablkcipher_clear_flags(ctx->ctfm, ~0);
368 crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctx->ctfm),
369 CRYPTO_TFM_REQ_WEAK_KEY);
370
371 /* If we are lucky, we will get a context that is already
372 * set up with the right key. Else, we will have to
373 * set the key */
374 if (!ctx->ctfm_key_is_ready) {
375 /* Since our crypto objectives for filename encryption
376 * are pretty weak,
377 * we directly use the inode master key */
378 res = crypto_ablkcipher_setkey(ctx->ctfm,
Theodore Ts'oe2881b1b2015-05-18 13:16:47 -0400379 ctx->ci.ci_raw, ctx->ci.ci_size);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400380 if (res) {
381 ext4_put_fname_crypto_ctx(&ctx);
382 return ERR_PTR(-EIO);
383 }
384 ctx->ctfm_key_is_ready = 1;
385 } else {
386 /* In the current implementation, key should never be
387 * marked "ready" for a context that has just been
388 * allocated. So we should never reach here */
389 BUG();
390 }
391 }
392 if (ctx->htfm == NULL)
393 ctx->htfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
394 if (IS_ERR(ctx->htfm)) {
395 res = PTR_ERR(ctx->htfm);
396 printk(KERN_DEBUG "%s: error (%d) allocating hash tfm\n",
397 __func__, res);
398 ctx->htfm = NULL;
399 ext4_put_fname_crypto_ctx(&ctx);
400 return ERR_PTR(res);
401 }
402 if (ctx->htfm == NULL) {
403 printk(KERN_DEBUG "%s: could not allocate hash tfm\n",
404 __func__);
405 ext4_put_fname_crypto_ctx(&ctx);
406 return ERR_PTR(-ENOMEM);
407 }
408
409 return ctx;
410}
411
412/**
413 * ext4_fname_crypto_round_up() -
414 *
415 * Return: The next multiple of block size
416 */
417u32 ext4_fname_crypto_round_up(u32 size, u32 blksize)
418{
419 return ((size+blksize-1)/blksize)*blksize;
420}
421
422/**
423 * ext4_fname_crypto_namelen_on_disk() -
424 */
425int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
426 u32 namelen)
427{
428 u32 ciphertext_len;
Theodore Ts'oa44cd7a2015-05-01 16:56:50 -0400429 int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400430
431 if (ctx == NULL)
432 return -EIO;
433 if (!(ctx->has_valid_key))
434 return -EACCES;
435 ciphertext_len = (namelen < EXT4_CRYPTO_BLOCK_SIZE) ?
436 EXT4_CRYPTO_BLOCK_SIZE : namelen;
Theodore Ts'oa44cd7a2015-05-01 16:56:50 -0400437 ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400438 ciphertext_len = (ciphertext_len > ctx->lim)
439 ? ctx->lim : ciphertext_len;
440 return (int) ciphertext_len;
441}
442
443/**
444 * ext4_fname_crypto_alloc_obuff() -
445 *
446 * Allocates an output buffer that is sufficient for the crypto operation
447 * specified by the context and the direction.
448 */
449int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx,
450 u32 ilen, struct ext4_str *crypto_str)
451{
452 unsigned int olen;
Theodore Ts'oa44cd7a2015-05-01 16:56:50 -0400453 int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400454
455 if (!ctx)
456 return -EIO;
Theodore Ts'oa44cd7a2015-05-01 16:56:50 -0400457 if (padding < EXT4_CRYPTO_BLOCK_SIZE)
458 padding = EXT4_CRYPTO_BLOCK_SIZE;
459 olen = ext4_fname_crypto_round_up(ilen, padding);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400460 crypto_str->len = olen;
461 if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2)
462 olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2;
463 /* Allocated buffer can hold one more character to null-terminate the
464 * string */
465 crypto_str->name = kmalloc(olen+1, GFP_NOFS);
466 if (!(crypto_str->name))
467 return -ENOMEM;
468 return 0;
469}
470
471/**
472 * ext4_fname_crypto_free_buffer() -
473 *
474 * Frees the buffer allocated for crypto operation.
475 */
476void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str)
477{
478 if (!crypto_str)
479 return;
480 kfree(crypto_str->name);
481 crypto_str->name = NULL;
482}
483
484/**
485 * ext4_fname_disk_to_usr() - converts a filename from disk space to user space
486 */
487int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400488 struct dx_hash_info *hinfo,
489 const struct ext4_str *iname,
490 struct ext4_str *oname)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400491{
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400492 char buf[24];
493 int ret;
494
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400495 if (ctx == NULL)
496 return -EIO;
497 if (iname->len < 3) {
498 /*Check for . and .. */
499 if (iname->name[0] == '.' && iname->name[iname->len-1] == '.') {
500 oname->name[0] = '.';
501 oname->name[iname->len-1] = '.';
502 oname->len = iname->len;
503 return oname->len;
504 }
505 }
506 if (ctx->has_valid_key)
507 return ext4_fname_decrypt(ctx, iname, oname);
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400508
509 if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) {
510 ret = digest_encode(iname->name, iname->len, oname->name);
511 oname->len = ret;
512 return ret;
513 }
514 if (hinfo) {
515 memcpy(buf, &hinfo->hash, 4);
516 memcpy(buf+4, &hinfo->minor_hash, 4);
517 } else
518 memset(buf, 0, 8);
519 memcpy(buf + 8, iname->name + iname->len - 16, 16);
520 oname->name[0] = '_';
521 ret = digest_encode(buf, 24, oname->name+1);
522 oname->len = ret + 1;
523 return ret + 1;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400524}
525
526int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400527 struct dx_hash_info *hinfo,
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400528 const struct ext4_dir_entry_2 *de,
529 struct ext4_str *oname)
530{
531 struct ext4_str iname = {.name = (unsigned char *) de->name,
532 .len = de->name_len };
533
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400534 return _ext4_fname_disk_to_usr(ctx, hinfo, &iname, oname);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400535}
536
537
538/**
539 * ext4_fname_usr_to_disk() - converts a filename from user space to disk space
540 */
541int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
542 const struct qstr *iname,
543 struct ext4_str *oname)
544{
545 int res;
546
547 if (ctx == NULL)
548 return -EIO;
549 if (iname->len < 3) {
550 /*Check for . and .. */
551 if (iname->name[0] == '.' &&
552 iname->name[iname->len-1] == '.') {
553 oname->name[0] = '.';
554 oname->name[iname->len-1] = '.';
555 oname->len = iname->len;
556 return oname->len;
557 }
558 }
559 if (ctx->has_valid_key) {
560 res = ext4_fname_encrypt(ctx, iname, oname);
561 return res;
562 }
563 /* Without a proper key, a user is not allowed to modify the filenames
564 * in a directory. Consequently, a user space name cannot be mapped to
565 * a disk-space name */
566 return -EACCES;
567}
568
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400569int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
570 int lookup, struct ext4_filename *fname)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400571{
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400572 struct ext4_fname_crypto_ctx *ctx;
573 int ret = 0, bigname = 0;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400574
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400575 memset(fname, 0, sizeof(struct ext4_filename));
576 fname->usr_fname = iname;
577
578 ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
579 if (IS_ERR(ctx))
580 return PTR_ERR(ctx);
581 if ((ctx == NULL) ||
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400582 ((iname->name[0] == '.') &&
583 ((iname->len == 1) ||
584 ((iname->name[1] == '.') && (iname->len == 2))))) {
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400585 fname->disk_name.name = (unsigned char *) iname->name;
586 fname->disk_name.len = iname->len;
587 goto out;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400588 }
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400589 if (ctx->has_valid_key) {
590 ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len,
591 &fname->crypto_buf);
592 if (ret < 0)
593 goto out;
594 ret = ext4_fname_encrypt(ctx, iname, &fname->crypto_buf);
595 if (ret < 0)
596 goto out;
597 fname->disk_name.name = fname->crypto_buf.name;
598 fname->disk_name.len = fname->crypto_buf.len;
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400599 ret = 0;
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400600 goto out;
601 }
602 if (!lookup) {
603 ret = -EACCES;
604 goto out;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400605 }
606
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400607 /* We don't have the key and we are doing a lookup; decode the
608 * user-supplied name
609 */
610 if (iname->name[0] == '_')
611 bigname = 1;
612 if ((bigname && (iname->len != 33)) ||
613 (!bigname && (iname->len > 43))) {
614 ret = -ENOENT;
615 }
616 fname->crypto_buf.name = kmalloc(32, GFP_KERNEL);
617 if (fname->crypto_buf.name == NULL) {
618 ret = -ENOMEM;
619 goto out;
620 }
621 ret = digest_decode(iname->name + bigname, iname->len - bigname,
622 fname->crypto_buf.name);
623 if (ret < 0) {
624 ret = -ENOENT;
625 goto out;
626 }
627 fname->crypto_buf.len = ret;
628 if (bigname) {
629 memcpy(&fname->hinfo.hash, fname->crypto_buf.name, 4);
630 memcpy(&fname->hinfo.minor_hash, fname->crypto_buf.name + 4, 4);
631 } else {
632 fname->disk_name.name = fname->crypto_buf.name;
633 fname->disk_name.len = fname->crypto_buf.len;
634 }
635 ret = 0;
636out:
637 ext4_put_fname_crypto_ctx(&ctx);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400638 return ret;
639}
640
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400641void ext4_fname_free_filename(struct ext4_filename *fname)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400642{
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400643 kfree(fname->crypto_buf.name);
644 fname->crypto_buf.name = NULL;
645 fname->usr_fname = NULL;
646 fname->disk_name.name = NULL;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400647}