aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/crypto_fname.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/crypto_fname.c')
-rw-r--r--fs/ext4/crypto_fname.c280
1 files changed, 145 insertions, 135 deletions
diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
index ca2f5948c1ac..fded02f72299 100644
--- a/fs/ext4/crypto_fname.c
+++ b/fs/ext4/crypto_fname.c
@@ -66,6 +66,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
66 int res = 0; 66 int res = 0;
67 char iv[EXT4_CRYPTO_BLOCK_SIZE]; 67 char iv[EXT4_CRYPTO_BLOCK_SIZE];
68 struct scatterlist sg[1]; 68 struct scatterlist sg[1];
69 int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
69 char *workbuf; 70 char *workbuf;
70 71
71 if (iname->len <= 0 || iname->len > ctx->lim) 72 if (iname->len <= 0 || iname->len > ctx->lim)
@@ -73,6 +74,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
73 74
74 ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ? 75 ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ?
75 EXT4_CRYPTO_BLOCK_SIZE : iname->len; 76 EXT4_CRYPTO_BLOCK_SIZE : iname->len;
77 ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
76 ciphertext_len = (ciphertext_len > ctx->lim) 78 ciphertext_len = (ciphertext_len > ctx->lim)
77 ? ctx->lim : ciphertext_len; 79 ? ctx->lim : ciphertext_len;
78 80
@@ -101,7 +103,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
101 /* Create encryption request */ 103 /* Create encryption request */
102 sg_init_table(sg, 1); 104 sg_init_table(sg, 1);
103 sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0); 105 sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0);
104 ablkcipher_request_set_crypt(req, sg, sg, iname->len, iv); 106 ablkcipher_request_set_crypt(req, sg, sg, ciphertext_len, iv);
105 res = crypto_ablkcipher_encrypt(req); 107 res = crypto_ablkcipher_encrypt(req);
106 if (res == -EINPROGRESS || res == -EBUSY) { 108 if (res == -EINPROGRESS || res == -EBUSY) {
107 BUG_ON(req->base.data != &ecr); 109 BUG_ON(req->base.data != &ecr);
@@ -198,106 +200,57 @@ static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx,
198 return oname->len; 200 return oname->len;
199} 201}
200 202
203static const char *lookup_table =
204 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
205
201/** 206/**
202 * ext4_fname_encode_digest() - 207 * ext4_fname_encode_digest() -
203 * 208 *
204 * Encodes the input digest using characters from the set [a-zA-Z0-9_+]. 209 * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
205 * The encoded string is roughly 4/3 times the size of the input string. 210 * The encoded string is roughly 4/3 times the size of the input string.
206 */ 211 */
207int ext4_fname_encode_digest(char *dst, char *src, u32 len) 212static int digest_encode(const char *src, int len, char *dst)
208{ 213{
209 static const char *lookup_table = 214 int i = 0, bits = 0, ac = 0;
210 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+"; 215 char *cp = dst;
211 u32 current_chunk, num_chunks, i; 216
212 char tmp_buf[3]; 217 while (i < len) {
213 u32 c0, c1, c2, c3; 218 ac += (((unsigned char) src[i]) << bits);
214 219 bits += 8;
215 current_chunk = 0; 220 do {
216 num_chunks = len/3; 221 *cp++ = lookup_table[ac & 0x3f];
217 for (i = 0; i < num_chunks; i++) { 222 ac >>= 6;
218 c0 = src[3*i] & 0x3f; 223 bits -= 6;
219 c1 = (((src[3*i]>>6)&0x3) | ((src[3*i+1] & 0xf)<<2)) & 0x3f; 224 } while (bits >= 6);
220 c2 = (((src[3*i+1]>>4)&0xf) | ((src[3*i+2] & 0x3)<<4)) & 0x3f;
221 c3 = (src[3*i+2]>>2) & 0x3f;
222 dst[4*i] = lookup_table[c0];
223 dst[4*i+1] = lookup_table[c1];
224 dst[4*i+2] = lookup_table[c2];
225 dst[4*i+3] = lookup_table[c3];
226 }
227 if (i*3 < len) {
228 memset(tmp_buf, 0, 3);
229 memcpy(tmp_buf, &src[3*i], len-3*i);
230 c0 = tmp_buf[0] & 0x3f;
231 c1 = (((tmp_buf[0]>>6)&0x3) | ((tmp_buf[1] & 0xf)<<2)) & 0x3f;
232 c2 = (((tmp_buf[1]>>4)&0xf) | ((tmp_buf[2] & 0x3)<<4)) & 0x3f;
233 c3 = (tmp_buf[2]>>2) & 0x3f;
234 dst[4*i] = lookup_table[c0];
235 dst[4*i+1] = lookup_table[c1];
236 dst[4*i+2] = lookup_table[c2];
237 dst[4*i+3] = lookup_table[c3];
238 i++; 225 i++;
239 } 226 }
240 return (i * 4); 227 if (bits)
228 *cp++ = lookup_table[ac & 0x3f];
229 return cp - dst;
241} 230}
242 231
243/** 232static int digest_decode(const char *src, int len, char *dst)
244 * ext4_fname_hash() -
245 *
246 * This function computes the hash of the input filename, and sets the output
247 * buffer to the *encoded* digest. It returns the length of the digest as its
248 * return value. Errors are returned as negative numbers. We trust the caller
249 * to allocate sufficient memory to oname string.
250 */
251static int ext4_fname_hash(struct ext4_fname_crypto_ctx *ctx,
252 const struct ext4_str *iname,
253 struct ext4_str *oname)
254{ 233{
255 struct scatterlist sg; 234 int i = 0, bits = 0, ac = 0;
256 struct hash_desc desc = { 235 const char *p;
257 .tfm = (struct crypto_hash *)ctx->htfm, 236 char *cp = dst;
258 .flags = CRYPTO_TFM_REQ_MAY_SLEEP 237
259 }; 238 while (i < len) {
260 int res = 0; 239 p = strchr(lookup_table, src[i]);
261 240 if (p == NULL || src[i] == 0)
262 if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) { 241 return -2;
263 res = ext4_fname_encode_digest(oname->name, iname->name, 242 ac += (p - lookup_table) << bits;
264 iname->len); 243 bits += 6;
265 oname->len = res; 244 if (bits >= 8) {
266 return res; 245 *cp++ = ac & 0xff;
267 } 246 ac >>= 8;
268 247 bits -= 8;
269 sg_init_one(&sg, iname->name, iname->len); 248 }
270 res = crypto_hash_init(&desc); 249 i++;
271 if (res) {
272 printk(KERN_ERR
273 "%s: Error initializing crypto hash; res = [%d]\n",
274 __func__, res);
275 goto out;
276 }
277 res = crypto_hash_update(&desc, &sg, iname->len);
278 if (res) {
279 printk(KERN_ERR
280 "%s: Error updating crypto hash; res = [%d]\n",
281 __func__, res);
282 goto out;
283 }
284 res = crypto_hash_final(&desc,
285 &oname->name[EXT4_FNAME_CRYPTO_DIGEST_SIZE]);
286 if (res) {
287 printk(KERN_ERR
288 "%s: Error finalizing crypto hash; res = [%d]\n",
289 __func__, res);
290 goto out;
291 } 250 }
292 /* Encode the digest as a printable string--this will increase the 251 if (ac)
293 * size of the digest */ 252 return -1;
294 oname->name[0] = 'I'; 253 return cp - dst;
295 res = ext4_fname_encode_digest(oname->name+1,
296 &oname->name[EXT4_FNAME_CRYPTO_DIGEST_SIZE],
297 EXT4_FNAME_CRYPTO_DIGEST_SIZE) + 1;
298 oname->len = res;
299out:
300 return res;
301} 254}
302 255
303/** 256/**
@@ -405,6 +358,7 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
405 if (IS_ERR(ctx)) 358 if (IS_ERR(ctx))
406 return ctx; 359 return ctx;
407 360
361 ctx->flags = ei->i_crypt_policy_flags;
408 if (ctx->has_valid_key) { 362 if (ctx->has_valid_key) {
409 if (ctx->key.mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) { 363 if (ctx->key.mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
410 printk_once(KERN_WARNING 364 printk_once(KERN_WARNING
@@ -517,6 +471,7 @@ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
517 u32 namelen) 471 u32 namelen)
518{ 472{
519 u32 ciphertext_len; 473 u32 ciphertext_len;
474 int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
520 475
521 if (ctx == NULL) 476 if (ctx == NULL)
522 return -EIO; 477 return -EIO;
@@ -524,6 +479,7 @@ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
524 return -EACCES; 479 return -EACCES;
525 ciphertext_len = (namelen < EXT4_CRYPTO_BLOCK_SIZE) ? 480 ciphertext_len = (namelen < EXT4_CRYPTO_BLOCK_SIZE) ?
526 EXT4_CRYPTO_BLOCK_SIZE : namelen; 481 EXT4_CRYPTO_BLOCK_SIZE : namelen;
482 ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
527 ciphertext_len = (ciphertext_len > ctx->lim) 483 ciphertext_len = (ciphertext_len > ctx->lim)
528 ? ctx->lim : ciphertext_len; 484 ? ctx->lim : ciphertext_len;
529 return (int) ciphertext_len; 485 return (int) ciphertext_len;
@@ -539,10 +495,13 @@ int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx,
539 u32 ilen, struct ext4_str *crypto_str) 495 u32 ilen, struct ext4_str *crypto_str)
540{ 496{
541 unsigned int olen; 497 unsigned int olen;
498 int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
542 499
543 if (!ctx) 500 if (!ctx)
544 return -EIO; 501 return -EIO;
545 olen = ext4_fname_crypto_round_up(ilen, EXT4_CRYPTO_BLOCK_SIZE); 502 if (padding < EXT4_CRYPTO_BLOCK_SIZE)
503 padding = EXT4_CRYPTO_BLOCK_SIZE;
504 olen = ext4_fname_crypto_round_up(ilen, padding);
546 crypto_str->len = olen; 505 crypto_str->len = olen;
547 if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) 506 if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2)
548 olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2; 507 olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2;
@@ -571,9 +530,13 @@ void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str)
571 * ext4_fname_disk_to_usr() - converts a filename from disk space to user space 530 * ext4_fname_disk_to_usr() - converts a filename from disk space to user space
572 */ 531 */
573int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, 532int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
574 const struct ext4_str *iname, 533 struct dx_hash_info *hinfo,
575 struct ext4_str *oname) 534 const struct ext4_str *iname,
535 struct ext4_str *oname)
576{ 536{
537 char buf[24];
538 int ret;
539
577 if (ctx == NULL) 540 if (ctx == NULL)
578 return -EIO; 541 return -EIO;
579 if (iname->len < 3) { 542 if (iname->len < 3) {
@@ -587,18 +550,33 @@ int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
587 } 550 }
588 if (ctx->has_valid_key) 551 if (ctx->has_valid_key)
589 return ext4_fname_decrypt(ctx, iname, oname); 552 return ext4_fname_decrypt(ctx, iname, oname);
590 else 553
591 return ext4_fname_hash(ctx, iname, oname); 554 if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) {
555 ret = digest_encode(iname->name, iname->len, oname->name);
556 oname->len = ret;
557 return ret;
558 }
559 if (hinfo) {
560 memcpy(buf, &hinfo->hash, 4);
561 memcpy(buf+4, &hinfo->minor_hash, 4);
562 } else
563 memset(buf, 0, 8);
564 memcpy(buf + 8, iname->name + iname->len - 16, 16);
565 oname->name[0] = '_';
566 ret = digest_encode(buf, 24, oname->name+1);
567 oname->len = ret + 1;
568 return ret + 1;
592} 569}
593 570
594int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, 571int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
572 struct dx_hash_info *hinfo,
595 const struct ext4_dir_entry_2 *de, 573 const struct ext4_dir_entry_2 *de,
596 struct ext4_str *oname) 574 struct ext4_str *oname)
597{ 575{
598 struct ext4_str iname = {.name = (unsigned char *) de->name, 576 struct ext4_str iname = {.name = (unsigned char *) de->name,
599 .len = de->name_len }; 577 .len = de->name_len };
600 578
601 return _ext4_fname_disk_to_usr(ctx, &iname, oname); 579 return _ext4_fname_disk_to_usr(ctx, hinfo, &iname, oname);
602} 580}
603 581
604 582
@@ -640,10 +618,11 @@ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
640 const struct qstr *iname, 618 const struct qstr *iname,
641 struct dx_hash_info *hinfo) 619 struct dx_hash_info *hinfo)
642{ 620{
643 struct ext4_str tmp, tmp2; 621 struct ext4_str tmp;
644 int ret = 0; 622 int ret = 0;
623 char buf[EXT4_FNAME_CRYPTO_DIGEST_SIZE+1];
645 624
646 if (!ctx || !ctx->has_valid_key || 625 if (!ctx ||
647 ((iname->name[0] == '.') && 626 ((iname->name[0] == '.') &&
648 ((iname->len == 1) || 627 ((iname->len == 1) ||
649 ((iname->name[1] == '.') && (iname->len == 2))))) { 628 ((iname->name[1] == '.') && (iname->len == 2))))) {
@@ -651,59 +630,90 @@ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
651 return 0; 630 return 0;
652 } 631 }
653 632
633 if (!ctx->has_valid_key && iname->name[0] == '_') {
634 if (iname->len != 33)
635 return -ENOENT;
636 ret = digest_decode(iname->name+1, iname->len, buf);
637 if (ret != 24)
638 return -ENOENT;
639 memcpy(&hinfo->hash, buf, 4);
640 memcpy(&hinfo->minor_hash, buf + 4, 4);
641 return 0;
642 }
643
644 if (!ctx->has_valid_key && iname->name[0] != '_') {
645 if (iname->len > 43)
646 return -ENOENT;
647 ret = digest_decode(iname->name, iname->len, buf);
648 ext4fs_dirhash(buf, ret, hinfo);
649 return 0;
650 }
651
654 /* First encrypt the plaintext name */ 652 /* First encrypt the plaintext name */
655 ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len, &tmp); 653 ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len, &tmp);
656 if (ret < 0) 654 if (ret < 0)
657 return ret; 655 return ret;
658 656
659 ret = ext4_fname_encrypt(ctx, iname, &tmp); 657 ret = ext4_fname_encrypt(ctx, iname, &tmp);
660 if (ret < 0) 658 if (ret >= 0) {
661 goto out; 659 ext4fs_dirhash(tmp.name, tmp.len, hinfo);
662 660 ret = 0;
663 tmp2.len = (4 * ((EXT4_FNAME_CRYPTO_DIGEST_SIZE + 2) / 3)) + 1;
664 tmp2.name = kmalloc(tmp2.len + 1, GFP_KERNEL);
665 if (tmp2.name == NULL) {
666 ret = -ENOMEM;
667 goto out;
668 } 661 }
669 662
670 ret = ext4_fname_hash(ctx, &tmp, &tmp2);
671 if (ret > 0)
672 ext4fs_dirhash(tmp2.name, tmp2.len, hinfo);
673 ext4_fname_crypto_free_buffer(&tmp2);
674out:
675 ext4_fname_crypto_free_buffer(&tmp); 663 ext4_fname_crypto_free_buffer(&tmp);
676 return ret; 664 return ret;
677} 665}
678 666
679/** 667int ext4_fname_match(struct ext4_fname_crypto_ctx *ctx, struct ext4_str *cstr,
680 * ext4_fname_disk_to_htree() - converts a filename from disk space to htree-access string 668 int len, const char * const name,
681 */ 669 struct ext4_dir_entry_2 *de)
682int ext4_fname_disk_to_hash(struct ext4_fname_crypto_ctx *ctx,
683 const struct ext4_dir_entry_2 *de,
684 struct dx_hash_info *hinfo)
685{ 670{
686 struct ext4_str iname = {.name = (unsigned char *) de->name, 671 int ret = -ENOENT;
687 .len = de->name_len}; 672 int bigname = (*name == '_');
688 struct ext4_str tmp;
689 int ret;
690 673
691 if (!ctx || 674 if (ctx->has_valid_key) {
692 ((iname.name[0] == '.') && 675 if (cstr->name == NULL) {
693 ((iname.len == 1) || 676 struct qstr istr;
694 ((iname.name[1] == '.') && (iname.len == 2))))) { 677
695 ext4fs_dirhash(iname.name, iname.len, hinfo); 678 ret = ext4_fname_crypto_alloc_buffer(ctx, len, cstr);
696 return 0; 679 if (ret < 0)
680 goto errout;
681 istr.name = name;
682 istr.len = len;
683 ret = ext4_fname_encrypt(ctx, &istr, cstr);
684 if (ret < 0)
685 goto errout;
686 }
687 } else {
688 if (cstr->name == NULL) {
689 cstr->name = kmalloc(32, GFP_KERNEL);
690 if (cstr->name == NULL)
691 return -ENOMEM;
692 if ((bigname && (len != 33)) ||
693 (!bigname && (len > 43)))
694 goto errout;
695 ret = digest_decode(name+bigname, len-bigname,
696 cstr->name);
697 if (ret < 0) {
698 ret = -ENOENT;
699 goto errout;
700 }
701 cstr->len = ret;
702 }
703 if (bigname) {
704 if (de->name_len < 16)
705 return 0;
706 ret = memcmp(de->name + de->name_len - 16,
707 cstr->name + 8, 16);
708 return (ret == 0) ? 1 : 0;
709 }
697 } 710 }
698 711 if (de->name_len != cstr->len)
699 tmp.len = (4 * ((EXT4_FNAME_CRYPTO_DIGEST_SIZE + 2) / 3)) + 1; 712 return 0;
700 tmp.name = kmalloc(tmp.len + 1, GFP_KERNEL); 713 ret = memcmp(de->name, cstr->name, cstr->len);
701 if (tmp.name == NULL) 714 return (ret == 0) ? 1 : 0;
702 return -ENOMEM; 715errout:
703 716 kfree(cstr->name);
704 ret = ext4_fname_hash(ctx, &iname, &tmp); 717 cstr->name = NULL;
705 if (ret > 0)
706 ext4fs_dirhash(tmp.name, tmp.len, hinfo);
707 ext4_fname_crypto_free_buffer(&tmp);
708 return ret; 718 return ret;
709} 719}