ext2_hash.c revision 254104
11573Srgrimes/*- 250476Speter * Copyright (c) 2010, 2013 Zheng Liu <lz@freebsd.org> 3156813Sru * Copyright (c) 2012, Vyacheslav Matyushin 4156837Sru * All rights reserved. 5156837Sru * 6156813Sru * Redistribution and use in source and binary forms, with or without 7156813Sru * modification, are permitted provided that the following conditions 8211822Snwhitehorn * are met: 9211822Snwhitehorn * 1. Redistributions of source code must retain the above copyright 10211822Snwhitehorn * notice, this list of conditions and the following disclaimer. 11211822Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 12211822Snwhitehorn * notice, this list of conditions and the following disclaimer in the 13211774Simp * documentation and/or other materials provided with the distribution. 14211774Simp * 15211778Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 16211774Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17211774Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1893048Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 191573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2093253Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21123440Sbde * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22123440Sbde * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23123440Sbde * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 241573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25158794Sume * SUCH DAMAGE. 26251668Sjlh * 27124723Snectar * $FreeBSD: head/sys/fs/ext2fs/ext2_hash.c 254104 2013-08-08 22:07:59Z pfg $ 28117120Sru */ 29211774Simp 30235720Sgleb/* 31189765Sgabor * The following notice applies to the code in ext2_half_md4(): 32235720Sgleb * 331573Srgrimes * Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. 34136910Sru * 35136910Sru * License to copy and use this software is granted provided that it 361573Srgrimes * is identified as the "RSA Data Security, Inc. MD4 Message-Digest 37213153Sdavidxu * Algorithm" in all material mentioning or referencing this software 38213153Sdavidxu * or this function. 39213153Sdavidxu * 40213153Sdavidxu * License is also granted to make and use derivative works provided 41213153Sdavidxu * that such works are identified as "derived from the RSA Data 42169720Skan * Security, Inc. MD4 Message-Digest Algorithm" in all material 43169720Skan * mentioning or referencing the derived work. 44169720Skan * 45172401Sru * RSA Data Security, Inc. makes no representations concerning either 46169771Skan * the merchantability of this software or the suitability of this 47235653Smarcel * software for any particular purpose. It is provided "as is" 48169720Skan * without express or implied warranty of any kind. 49235653Smarcel * 50235653Smarcel * These notices must be retained in any copies of any part of this 51235653Smarcel * documentation and/or software. 52235653Smarcel */ 53258750Sgjb 54258750Sgjb#include <sys/param.h> 55258750Sgjb#include <sys/systm.h> 56107052Sru#include <sys/conf.h> 57107052Sru#include <sys/vnode.h> 58107052Sru#include <sys/stat.h> 59107052Sru#include <sys/mount.h> 60107052Sru 61107052Sru#include <fs/ext2fs/htree.h> 62107052Sru#include <fs/ext2fs/inode.h> 63107052Sru#include <fs/ext2fs/ext2_mount.h> 64211774Simp#include <fs/ext2fs/ext2_extern.h> 65107052Sru 66107052Sru/* F, G, and H are MD4 functions */ 67112202Sobrien#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 68107052Sru#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) 69107052Sru#define H(x, y, z) ((x) ^ (y) ^ (z)) 70219019Sgabor 71219019Sgabor/* ROTATE_LEFT rotates x left n bits */ 72219019Sgabor#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) 73156960Sume 74156960Sume/* 75107052Sru * FF, GG, and HH are transformations for rounds 1, 2, and 3. 76156960Sume * Rotation is separated from addition to prevent recomputation. 77107052Sru */ 78107052Sru#define FF(a, b, c, d, x, s) { \ 79107052Sru (a) += F ((b), (c), (d)) + (x); \ 80211774Simp (a) = ROTATE_LEFT ((a), (s)); \ 81211774Simp} 82211774Simp 83211774Simp#define GG(a, b, c, d, x, s) { \ 84217942Sjchandra (a) += G ((b), (c), (d)) + (x) + (uint32_t)0x5A827999; \ 85217123Simp (a) = ROTATE_LEFT ((a), (s)); \ 86107052Sru} 87107052Sru 88107052Sru#define HH(a, b, c, d, x, s) { \ 89156960Sume (a) += H ((b), (c), (d)) + (x) + (uint32_t)0x6ED9EBA1; \ 90107052Sru (a) = ROTATE_LEFT ((a), (s)); \ 91107052Sru} 92234370Sjasone 93107052Sru/* 94107052Sru * MD4 basic transformation. It transforms state based on block. 95107052Sru * 96107052Sru * This is a half md4 algorithm since Linux uses this algorithm for dir 97107052Sru * index. This function is derived from the RSA Data Security, Inc. MD4 98107052Sru * Message-Digest Algorithm and was modified as necessary. 99211774Simp * 100129202Scognet * The return value of this function is uint32_t in Linux, but actually we don't 101129202Scognet * need to check this value, so in our version this function doesn't return any 102156813Sru * value. 103107052Sru */ 104107052Srustatic void 105107052Sruext2_half_md4(uint32_t hash[4], uint32_t data[8]) 106255219Spjd{ 107156813Sru uint32_t a = hash[0], b = hash[1], c = hash[2], d = hash[3]; 108107052Sru 109107052Sru /* Round 1 */ 110156813Sru FF(a, b, c, d, data[0], 3); 111128820Sdas FF(d, a, b, c, data[1], 7); 112128820Sdas FF(c, d, a, b, data[2], 11); 113158115Sume FF(b, c, d, a, data[3], 19); 114158115Sume FF(a, b, c, d, data[4], 3); 115158115Sume FF(d, a, b, c, data[5], 7); 116167199Ssimon FF(c, d, a, b, data[6], 11); 117167199Ssimon FF(b, c, d, a, data[7], 19); 118167199Ssimon 119107052Sru /* Round 2 */ 120258750Sgjb GG(a, b, c, d, data[1], 3); 121258750Sgjb GG(d, a, b, c, data[3], 5); 122156773Sdeischen GG(c, d, a, b, data[5], 9); 123156773Sdeischen GG(b, c, d, a, data[7], 13); 124156773Sdeischen GG(a, b, c, d, data[0], 3); 125156773Sdeischen GG(d, a, b, c, data[2], 5); 126107052Sru GG(c, d, a, b, data[4], 9); 127107052Sru GG(b, c, d, a, data[6], 13); 128107052Sru 129107052Sru /* Round 3 */ 130107052Sru HH(a, b, c, d, data[3], 3); 131107052Sru HH(d, a, b, c, data[7], 9); 132107052Sru HH(c, d, a, b, data[2], 11); 133107052Sru HH(b, c, d, a, data[6], 15); 134107052Sru HH(a, b, c, d, data[1], 3); 135107052Sru HH(d, a, b, c, data[5], 9); 136107052Sru HH(c, d, a, b, data[0], 11); 137107052Sru HH(b, c, d, a, data[4], 15); 138107052Sru 139107052Sru hash[0] += a; 140107052Sru hash[1] += b; 1411573Srgrimes hash[2] += c; 1421573Srgrimes hash[3] += d; 1431573Srgrimes} 144229368Sed 145229368Sed/* 1461573Srgrimes * Tiny Encryption Algorithm. 147211774Simp */ 1481573Srgrimesstatic void 1491573Srgrimesext2_tea(uint32_t hash[4], uint32_t data[8]) 15026047Sasami{ 1511573Srgrimes uint32_t tea_delta = 0x9E3779B9; 152211774Simp uint32_t sum; 1531573Srgrimes uint32_t x = hash[0], y = hash[1]; 154211774Simp int n = 16; 1551573Srgrimes int i = 1; 156211704Skib 1571573Srgrimes while (n-- > 0) { 158124374Sru sum = i * tea_delta; 159124374Sru x += ((y << 4) + data[0]) ^ (y + sum) ^ ((y >> 5) + data[1]); 160210731Srpaulo y += ((x << 4) + data[2]) ^ (x + sum) ^ ((x >> 5) + data[3]); 161180012Sru i++; 162180012Sru } 163180012Sru 164180012Sru hash[0] += x; 165180012Sru hash[1] += y; 166180012Sru} 167213153Sdavidxu 168213153Sdavidxustatic uint32_t 169ext2_legacy_hash(const char *name, int len, int unsigned_char) 170{ 171 uint32_t h0, h1 = 0x12A3FE2D, h2 = 0x37ABE8F9; 172 uint32_t multi = 0x6D22F5; 173 const unsigned char *uname = (const unsigned char *)name; 174 const signed char *sname = (const signed char *)name; 175 int val, i; 176 177 for (i = 0; i < len; i++) { 178 if (unsigned_char) 179 val = (u_int)*uname++; 180 else 181 val = (int)*sname++; 182 183 h0 = h2 + (h1 ^ (val * multi)); 184 if (h0 & 0x80000000) 185 h0 -= 0x7FFFFFFF; 186 h2 = h1; 187 h1 = h0; 188 } 189 190 return (h1 << 1); 191} 192 193static void 194ext2_prep_hashbuf(const char *src, int slen, uint32_t *dst, int dlen, 195 int unsigned_char) 196{ 197 uint32_t padding = slen | (slen << 8) | (slen << 16) | (slen << 24); 198 uint32_t buf_val; 199 int len, i; 200 int buf_byte; 201 const unsigned char *ubuf = (const unsigned char *)src; 202 const signed char *sbuf = (const signed char *)src; 203 204 if (slen > dlen) 205 len = dlen; 206 else 207 len = slen; 208 209 buf_val = padding; 210 211 for (i = 0; i < len; i++) { 212 if (unsigned_char) 213 buf_byte = (u_int)ubuf[i]; 214 else 215 buf_byte = (int)sbuf[i]; 216 217 if ((i % 4) == 0) 218 buf_val = padding; 219 220 buf_val <<= 8; 221 buf_val += buf_byte; 222 223 if ((i % 4) == 3) { 224 *dst++ = buf_val; 225 dlen -= sizeof(uint32_t); 226 buf_val = padding; 227 } 228 } 229 230 dlen -= sizeof(uint32_t); 231 if (dlen >= 0) 232 *dst++ = buf_val; 233 234 dlen -= sizeof(uint32_t); 235 while (dlen >= 0) { 236 *dst++ = padding; 237 dlen -= sizeof(uint32_t); 238 } 239} 240 241int 242ext2_htree_hash(const char *name, int len, 243 uint32_t *hash_seed, int hash_version, 244 uint32_t *hash_major, uint32_t *hash_minor) 245{ 246 uint32_t hash[4]; 247 uint32_t data[8]; 248 uint32_t major = 0, minor = 0; 249 int unsigned_char = 0; 250 251 if (!name || !hash_major) 252 return (-1); 253 254 if (len < 1 || len > 255) 255 goto error; 256 257 hash[0] = 0x67452301; 258 hash[1] = 0xEFCDAB89; 259 hash[2] = 0x98BADCFE; 260 hash[3] = 0x10325476; 261 262 if (hash_seed) 263 memcpy(hash, hash_seed, sizeof(hash)); 264 265 switch (hash_version) { 266 case EXT2_HTREE_TEA_UNSIGNED: 267 unsigned_char = 1; 268 case EXT2_HTREE_TEA: 269 while (len > 0) { 270 ext2_prep_hashbuf(name, len, data, 16, unsigned_char); 271 ext2_tea(hash, data); 272 len -= 16; 273 name += 16; 274 } 275 major = hash[0]; 276 minor = hash[1]; 277 break; 278 case EXT2_HTREE_LEGACY_UNSIGNED: 279 unsigned_char = 1; 280 case EXT2_HTREE_LEGACY: 281 major = ext2_legacy_hash(name, len, unsigned_char); 282 break; 283 case EXT2_HTREE_HALF_MD4_UNSIGNED: 284 unsigned_char = 1; 285 case EXT2_HTREE_HALF_MD4: 286 while (len > 0) { 287 ext2_prep_hashbuf(name, len, data, 32, unsigned_char); 288 ext2_half_md4(hash, data); 289 len -= 32; 290 name += 32; 291 } 292 major = hash[0]; 293 minor = hash[1]; 294 break; 295 default: 296 goto error; 297 } 298 299 major &= ~1; 300 if (major == (EXT2_HTREE_EOF << 1)) 301 major = (EXT2_HTREE_EOF - 1) << 1; 302 *hash_major = major; 303 if (hash_minor) 304 *hash_minor = minor; 305 306 return (0); 307 308error: 309 *hash_major = 0; 310 if (hash_minor) 311 *hash_minor = 0; 312 return (-1); 313} 314