1 1.2 christos /* $NetBSD: ext2fs_hash.c,v 1.2 2016/08/13 07:40:10 christos Exp $ */ 2 1.1 christos 3 1.1 christos /*- 4 1.1 christos * Copyright (c) 2010, 2013 Zheng Liu <lz (at) freebsd.org> 5 1.1 christos * Copyright (c) 2012, Vyacheslav Matyushin 6 1.1 christos * All rights reserved. 7 1.1 christos * 8 1.1 christos * Redistribution and use in source and binary forms, with or without 9 1.1 christos * modification, are permitted provided that the following conditions 10 1.1 christos * are met: 11 1.1 christos * 1. Redistributions of source code must retain the above copyright 12 1.1 christos * notice, this list of conditions and the following disclaimer. 13 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 christos * notice, this list of conditions and the following disclaimer in the 15 1.1 christos * documentation and/or other materials provided with the distribution. 16 1.1 christos * 17 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 1.1 christos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 1.1 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 1.1 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 1.1 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 1.1 christos * SUCH DAMAGE. 28 1.1 christos * 29 1.1 christos * $FreeBSD: head/sys/fs/ext2fs/ext2_hash.c 294504 2016-01-21 14:50:28Z pfg $ 30 1.1 christos */ 31 1.1 christos 32 1.1 christos /* 33 1.1 christos * The following notice applies to the code in ext2_half_md4(): 34 1.1 christos * 35 1.1 christos * Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. 36 1.1 christos * 37 1.1 christos * License to copy and use this software is granted provided that it 38 1.1 christos * is identified as the "RSA Data Security, Inc. MD4 Message-Digest 39 1.1 christos * Algorithm" in all material mentioning or referencing this software 40 1.1 christos * or this function. 41 1.1 christos * 42 1.1 christos * License is also granted to make and use derivative works provided 43 1.1 christos * that such works are identified as "derived from the RSA Data 44 1.1 christos * Security, Inc. MD4 Message-Digest Algorithm" in all material 45 1.1 christos * mentioning or referencing the derived work. 46 1.1 christos * 47 1.1 christos * RSA Data Security, Inc. makes no representations concerning either 48 1.1 christos * the merchantability of this software or the suitability of this 49 1.1 christos * software for any particular purpose. It is provided "as is" 50 1.1 christos * without express or implied warranty of any kind. 51 1.1 christos * 52 1.1 christos * These notices must be retained in any copies of any part of this 53 1.1 christos * documentation and/or software. 54 1.1 christos */ 55 1.1 christos 56 1.1 christos #include <sys/cdefs.h> 57 1.2 christos __KERNEL_RCSID(0, "$NetBSD: ext2fs_hash.c,v 1.2 2016/08/13 07:40:10 christos Exp $"); 58 1.1 christos 59 1.1 christos #include <sys/param.h> 60 1.1 christos #include <sys/systm.h> 61 1.1 christos #include <sys/conf.h> 62 1.1 christos #include <sys/vnode.h> 63 1.1 christos #include <sys/stat.h> 64 1.1 christos #include <sys/mount.h> 65 1.1 christos 66 1.1 christos #include <ufs/ext2fs/ext2fs_htree.h> 67 1.1 christos #include <ufs/ext2fs/ext2fs_hash.h> 68 1.1 christos #include <ufs/ufs/inode.h> 69 1.1 christos #include <ufs/ufs/ufsmount.h> 70 1.1 christos #include <ufs/ext2fs/ext2fs_extern.h> 71 1.1 christos 72 1.1 christos /* 73 1.1 christos * FF, GG, and HH are transformations for rounds 1, 2, and 3. 74 1.1 christos * Rotation is separated from addition to prevent recomputation. 75 1.1 christos */ 76 1.1 christos #define FF(a, b, c, d, x, s) { \ 77 1.1 christos (a) += F ((b), (c), (d)) + (x); \ 78 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \ 79 1.1 christos } 80 1.1 christos 81 1.1 christos #define GG(a, b, c, d, x, s) { \ 82 1.1 christos (a) += G ((b), (c), (d)) + (x) + (uint32_t)0x5A827999; \ 83 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \ 84 1.1 christos } 85 1.1 christos 86 1.1 christos #define HH(a, b, c, d, x, s) { \ 87 1.1 christos (a) += H ((b), (c), (d)) + (x) + (uint32_t)0x6ED9EBA1; \ 88 1.1 christos (a) = ROTATE_LEFT ((a), (s)); \ 89 1.1 christos } 90 1.1 christos 91 1.1 christos static void 92 1.1 christos ext2fs_prep_hashbuf(const char *src, int slen, uint32_t *dst, int dlen, 93 1.1 christos int unsigned_char) 94 1.1 christos { 95 1.1 christos uint32_t padding = slen | (slen << 8) | (slen << 16) | (slen << 24); 96 1.1 christos uint32_t buf_val; 97 1.1 christos const unsigned char *ubuf = (const unsigned char *)src; 98 1.1 christos const signed char *sbuf = (const signed char *)src; 99 1.1 christos int len, i; 100 1.1 christos int buf_byte; 101 1.1 christos 102 1.1 christos if (slen > dlen) 103 1.1 christos len = dlen; 104 1.1 christos else 105 1.1 christos len = slen; 106 1.1 christos 107 1.1 christos buf_val = padding; 108 1.1 christos 109 1.1 christos for (i = 0; i < len; i++) { 110 1.1 christos if (unsigned_char) 111 1.1 christos buf_byte = (u_int)ubuf[i]; 112 1.1 christos else 113 1.1 christos buf_byte = (int)sbuf[i]; 114 1.1 christos 115 1.1 christos if ((i % 4) == 0) 116 1.1 christos buf_val = padding; 117 1.1 christos 118 1.1 christos buf_val <<= 8; 119 1.1 christos buf_val += buf_byte; 120 1.1 christos 121 1.1 christos if ((i % 4) == 3) { 122 1.1 christos *dst++ = buf_val; 123 1.1 christos dlen -= sizeof(uint32_t); 124 1.1 christos buf_val = padding; 125 1.1 christos } 126 1.1 christos } 127 1.1 christos 128 1.1 christos dlen -= sizeof(uint32_t); 129 1.1 christos if (dlen >= 0) 130 1.1 christos *dst++ = buf_val; 131 1.1 christos 132 1.1 christos dlen -= sizeof(uint32_t); 133 1.1 christos while (dlen >= 0) { 134 1.1 christos *dst++ = padding; 135 1.1 christos dlen -= sizeof(uint32_t); 136 1.1 christos } 137 1.1 christos } 138 1.1 christos 139 1.1 christos static uint32_t 140 1.1 christos ext2fs_legacy_hash(const char *name, int len, int unsigned_char) 141 1.1 christos { 142 1.1 christos uint32_t h0, h1 = 0x12A3FE2D, h2 = 0x37ABE8F9; 143 1.1 christos uint32_t multi = 0x6D22F5; 144 1.1 christos const unsigned char *uname = (const unsigned char *)name; 145 1.1 christos const signed char *sname = (const signed char *)name; 146 1.1 christos int val, i; 147 1.1 christos 148 1.1 christos for (i = 0; i < len; i++) { 149 1.1 christos if (unsigned_char) 150 1.1 christos val = (u_int)*uname++; 151 1.1 christos else 152 1.1 christos val = (int)*sname++; 153 1.1 christos 154 1.1 christos h0 = h2 + (h1 ^ (val * multi)); 155 1.1 christos if (h0 & 0x80000000) 156 1.1 christos h0 -= 0x7FFFFFFF; 157 1.1 christos h2 = h1; 158 1.1 christos h1 = h0; 159 1.1 christos } 160 1.1 christos 161 1.1 christos return h1 << 1; 162 1.1 christos } 163 1.1 christos 164 1.1 christos /* 165 1.1 christos * MD4 basic transformation. It transforms state based on block. 166 1.1 christos * 167 1.1 christos * This is a half md4 algorithm since Linux uses this algorithm for dir 168 1.1 christos * index. This function is derived from the RSA Data Security, Inc. MD4 169 1.1 christos * Message-Digest Algorithm and was modified as necessary. 170 1.1 christos * 171 1.1 christos * The return value of this function is uint32_t in Linux, but actually we don't 172 1.1 christos * need to check this value, so in our version this function doesn't return any 173 1.1 christos * value. 174 1.1 christos */ 175 1.1 christos static void 176 1.1 christos ext2fs_half_md4(uint32_t hash[4], uint32_t data[8]) 177 1.1 christos { 178 1.1 christos uint32_t a = hash[0], b = hash[1], c = hash[2], d = hash[3]; 179 1.1 christos 180 1.1 christos /* Round 1 */ 181 1.1 christos FF(a, b, c, d, data[0], 3); 182 1.1 christos FF(d, a, b, c, data[1], 7); 183 1.1 christos FF(c, d, a, b, data[2], 11); 184 1.1 christos FF(b, c, d, a, data[3], 19); 185 1.1 christos FF(a, b, c, d, data[4], 3); 186 1.1 christos FF(d, a, b, c, data[5], 7); 187 1.1 christos FF(c, d, a, b, data[6], 11); 188 1.1 christos FF(b, c, d, a, data[7], 19); 189 1.1 christos 190 1.1 christos /* Round 2 */ 191 1.1 christos GG(a, b, c, d, data[1], 3); 192 1.1 christos GG(d, a, b, c, data[3], 5); 193 1.1 christos GG(c, d, a, b, data[5], 9); 194 1.1 christos GG(b, c, d, a, data[7], 13); 195 1.1 christos GG(a, b, c, d, data[0], 3); 196 1.1 christos GG(d, a, b, c, data[2], 5); 197 1.1 christos GG(c, d, a, b, data[4], 9); 198 1.1 christos GG(b, c, d, a, data[6], 13); 199 1.1 christos 200 1.1 christos /* Round 3 */ 201 1.1 christos HH(a, b, c, d, data[3], 3); 202 1.1 christos HH(d, a, b, c, data[7], 9); 203 1.1 christos HH(c, d, a, b, data[2], 11); 204 1.1 christos HH(b, c, d, a, data[6], 15); 205 1.1 christos HH(a, b, c, d, data[1], 3); 206 1.1 christos HH(d, a, b, c, data[5], 9); 207 1.1 christos HH(c, d, a, b, data[0], 11); 208 1.1 christos HH(b, c, d, a, data[4], 15); 209 1.1 christos 210 1.1 christos hash[0] += a; 211 1.1 christos hash[1] += b; 212 1.1 christos hash[2] += c; 213 1.1 christos hash[3] += d; 214 1.1 christos } 215 1.1 christos 216 1.1 christos /* 217 1.1 christos * Tiny Encryption Algorithm. 218 1.1 christos */ 219 1.1 christos static void 220 1.1 christos ext2fs_tea(uint32_t hash[4], uint32_t data[8]) 221 1.1 christos { 222 1.1 christos uint32_t tea_delta = 0x9E3779B9; 223 1.1 christos uint32_t sum; 224 1.1 christos uint32_t x = hash[0], y = hash[1]; 225 1.1 christos int n = 16; 226 1.1 christos int i = 1; 227 1.1 christos 228 1.1 christos while (n-- > 0) { 229 1.1 christos sum = i * tea_delta; 230 1.1 christos x += ((y << 4) + data[0]) ^ (y + sum) ^ ((y >> 5) + data[1]); 231 1.1 christos y += ((x << 4) + data[2]) ^ (x + sum) ^ ((x >> 5) + data[3]); 232 1.1 christos i++; 233 1.1 christos } 234 1.1 christos 235 1.1 christos hash[0] += x; 236 1.1 christos hash[1] += y; 237 1.1 christos } 238 1.1 christos 239 1.1 christos int 240 1.1 christos ext2fs_htree_hash(const char *name, int len, 241 1.1 christos uint32_t *hash_seed, int hash_version, 242 1.1 christos uint32_t *hash_major, uint32_t *hash_minor) 243 1.1 christos { 244 1.1 christos uint32_t hash[4]; 245 1.1 christos uint32_t data[8]; 246 1.1 christos uint32_t major = 0, minor = 0; 247 1.1 christos int unsigned_char = 0; 248 1.1 christos 249 1.1 christos if (!name || !hash_major) 250 1.2 christos return -1; 251 1.1 christos 252 1.1 christos if (len < 1 || len > 255) 253 1.1 christos goto error; 254 1.1 christos 255 1.1 christos hash[0] = 0x67452301; 256 1.1 christos hash[1] = 0xEFCDAB89; 257 1.1 christos hash[2] = 0x98BADCFE; 258 1.1 christos hash[3] = 0x10325476; 259 1.1 christos 260 1.1 christos if (hash_seed) 261 1.1 christos memcpy(hash, hash_seed, sizeof(hash)); 262 1.1 christos 263 1.1 christos switch (hash_version) { 264 1.1 christos case EXT2_HTREE_TEA_UNSIGNED: 265 1.1 christos unsigned_char = 1; 266 1.1 christos /* FALLTHROUGH */ 267 1.1 christos case EXT2_HTREE_TEA: 268 1.1 christos while (len > 0) { 269 1.1 christos ext2fs_prep_hashbuf(name, len, data, 16, unsigned_char); 270 1.1 christos ext2fs_tea(hash, data); 271 1.1 christos len -= 16; 272 1.1 christos name += 16; 273 1.1 christos } 274 1.1 christos major = hash[0]; 275 1.1 christos minor = hash[1]; 276 1.1 christos break; 277 1.1 christos case EXT2_HTREE_LEGACY_UNSIGNED: 278 1.1 christos unsigned_char = 1; 279 1.1 christos /* FALLTHROUGH */ 280 1.1 christos case EXT2_HTREE_LEGACY: 281 1.1 christos major = ext2fs_legacy_hash(name, len, unsigned_char); 282 1.1 christos break; 283 1.1 christos case EXT2_HTREE_HALF_MD4_UNSIGNED: 284 1.1 christos unsigned_char = 1; 285 1.1 christos /* FALLTHROUGH */ 286 1.1 christos case EXT2_HTREE_HALF_MD4: 287 1.1 christos while (len > 0) { 288 1.1 christos ext2fs_prep_hashbuf(name, len, data, 32, unsigned_char); 289 1.1 christos ext2fs_half_md4(hash, data); 290 1.1 christos len -= 32; 291 1.1 christos name += 32; 292 1.1 christos } 293 1.1 christos major = hash[1]; 294 1.1 christos minor = hash[2]; 295 1.1 christos break; 296 1.1 christos default: 297 1.1 christos goto error; 298 1.1 christos } 299 1.1 christos 300 1.1 christos major &= ~1; 301 1.1 christos if (major == (EXT2_HTREE_EOF << 1)) 302 1.1 christos major = (EXT2_HTREE_EOF - 1) << 1; 303 1.1 christos *hash_major = major; 304 1.1 christos if (hash_minor) 305 1.1 christos *hash_minor = minor; 306 1.1 christos 307 1.1 christos return 0; 308 1.1 christos 309 1.1 christos error: 310 1.1 christos *hash_major = 0; 311 1.1 christos if (hash_minor) 312 1.1 christos *hash_minor = 0; 313 1.1 christos return -1; 314 1.1 christos } 315