blob: cc82f142f811f63065aa9299a2bdc772d79660aa [file] [log] [blame]
Chao Yu6d1a8322018-09-12 09:16:07 +08001// SPDX-License-Identifier: GPL-2.0
Jaegeuk Kim0a8165d2012-11-29 13:28:09 +09002/*
Jaegeuk Kim6b4ea012012-11-14 16:59:04 +09003 * fs/f2fs/hash.c
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
6 * http://www.samsung.com/
7 *
8 * Portions of this code from linux/fs/ext3/hash.c
9 *
10 * Copyright (C) 2002 by Theodore Ts'o
Jaegeuk Kim6b4ea012012-11-14 16:59:04 +090011 */
12#include <linux/types.h>
13#include <linux/fs.h>
14#include <linux/f2fs_fs.h>
15#include <linux/cryptohash.h>
16#include <linux/pagemap.h>
17
18#include "f2fs.h"
19
20/*
21 * Hashing code copied from ext3
22 */
23#define DELTA 0x9E3779B9
24
25static void TEA_transform(unsigned int buf[4], unsigned int const in[])
26{
27 __u32 sum = 0;
28 __u32 b0 = buf[0], b1 = buf[1];
29 __u32 a = in[0], b = in[1], c = in[2], d = in[3];
30 int n = 16;
31
32 do {
33 sum += DELTA;
34 b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
35 b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
36 } while (--n);
37
38 buf[0] += b0;
39 buf[1] += b1;
40}
41
Jaegeuk Kim3304b562014-08-29 00:26:50 -070042static void str2hashbuf(const unsigned char *msg, size_t len,
43 unsigned int *buf, int num)
Jaegeuk Kim6b4ea012012-11-14 16:59:04 +090044{
45 unsigned pad, val;
46 int i;
47
48 pad = (__u32)len | ((__u32)len << 8);
49 pad |= pad << 16;
50
51 val = pad;
52 if (len > num * 4)
53 len = num * 4;
54 for (i = 0; i < len; i++) {
55 if ((i % 4) == 0)
56 val = pad;
57 val = msg[i] + (val << 8);
58 if ((i % 4) == 3) {
59 *buf++ = val;
60 val = pad;
61 num--;
62 }
63 }
64 if (--num >= 0)
65 *buf++ = val;
66 while (--num >= 0)
67 *buf++ = pad;
68}
69
Jaegeuk Kim8daed212017-04-24 10:00:08 -070070f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info,
71 struct fscrypt_name *fname)
Jaegeuk Kim6b4ea012012-11-14 16:59:04 +090072{
Jaegeuk Kim2b506382012-12-26 14:39:50 +090073 __u32 hash;
Jaegeuk Kim6b4ea012012-11-14 16:59:04 +090074 f2fs_hash_t f2fs_hash;
Jaegeuk Kim3304b562014-08-29 00:26:50 -070075 const unsigned char *p;
Jaegeuk Kim6b4ea012012-11-14 16:59:04 +090076 __u32 in[8], buf[4];
Jaegeuk Kim3304b562014-08-29 00:26:50 -070077 const unsigned char *name = name_info->name;
Gu Zhengeee61602014-06-24 18:21:23 +080078 size_t len = name_info->len;
Jaegeuk Kim6b4ea012012-11-14 16:59:04 +090079
Jaegeuk Kim8daed212017-04-24 10:00:08 -070080 /* encrypted bigname case */
81 if (fname && !fname->disk_name.name)
82 return cpu_to_le32(fname->hash);
83
Jaegeuk Kimeaa693f2015-04-26 00:15:29 -070084 if (is_dot_dotdot(name_info))
Namjae Jeon38e0abd2012-12-13 23:44:11 +090085 return 0;
86
Jaegeuk Kim6b4ea012012-11-14 16:59:04 +090087 /* Initialize the default seed for the hash checksum functions */
88 buf[0] = 0x67452301;
89 buf[1] = 0xefcdab89;
90 buf[2] = 0x98badcfe;
91 buf[3] = 0x10325476;
92
93 p = name;
Leon Romanovsky9836b8b2012-12-27 19:55:46 +020094 while (1) {
Jaegeuk Kim6b4ea012012-11-14 16:59:04 +090095 str2hashbuf(p, len, in, 4);
96 TEA_transform(buf, in);
Jaegeuk Kim6b4ea012012-11-14 16:59:04 +090097 p += 16;
Leon Romanovsky9836b8b2012-12-27 19:55:46 +020098 if (len <= 16)
99 break;
100 len -= 16;
Jaegeuk Kim6b4ea012012-11-14 16:59:04 +0900101 }
102 hash = buf[0];
Jaegeuk Kim25ca9232012-11-28 16:12:41 +0900103 f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT);
Jaegeuk Kim6b4ea012012-11-14 16:59:04 +0900104 return f2fs_hash;
105}