Created
August 26, 2019 09:26
-
-
Save charsyam/9ccd31d4143fe924a1eca021584d54a4 to your computer and use it in GitHub Desktop.
Hafl MD4 hash from linux/fs/ext/hash.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-2.0 | |
/* | |
* linux/fs/ext4/hash.c | |
* | |
* Copyright (C) 2002 by Theodore Ts'o | |
*/ | |
#include <stdio.h> | |
#include <string.h> | |
#define DELTA 0x9E3779B9 | |
#define EXT4_HTREE_EOF_32BIT ((1UL << (32 - 1)) - 1) | |
static void TEA_transform(unsigned int buf[4], unsigned int const in[]) | |
{ | |
unsigned int sum = 0; | |
unsigned int b0 = buf[0], b1 = buf[1]; | |
unsigned int a = in[0], b = in[1], c = in[2], d = in[3]; | |
int n = 16; | |
do { | |
sum += DELTA; | |
b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); | |
b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); | |
} while (--n); | |
buf[0] += b0; | |
buf[1] += b1; | |
} | |
/* F, G and H are basic MD4 functions: selection, majority, parity */ | |
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) | |
#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) | |
#define H(x, y, z) ((x) ^ (y) ^ (z)) | |
/* | |
* The generic round function. The application is so specific that | |
* we don't bother protecting all the arguments with parens, as is generally | |
* good macro practice, in favor of extra legibility. | |
* Rotation is separate from addition to prevent recomputation | |
*/ | |
#define ROUND(f, a, b, c, d, x, s) \ | |
(a += f(b, c, d) + x, a = rol32(a, s)) | |
#define K1 0 | |
#define K2 013240474631UL | |
#define K3 015666365641UL | |
static inline unsigned int rol32(unsigned int word, unsigned int shift) | |
{ | |
return (word << (shift & 31)) | (word >> ((-shift) & 31)); | |
} | |
/* | |
* Basic cut-down MD4 transform. Returns only 32 bits of result. | |
*/ | |
static unsigned int half_md4_transform(unsigned int buf[4], unsigned int const in[8]) | |
{ | |
unsigned int a = buf[0], b = buf[1], c = buf[2], d = buf[3]; | |
/* Round 1 */ | |
ROUND(F, a, b, c, d, in[0] + K1, 3); | |
ROUND(F, d, a, b, c, in[1] + K1, 7); | |
ROUND(F, c, d, a, b, in[2] + K1, 11); | |
ROUND(F, b, c, d, a, in[3] + K1, 19); | |
ROUND(F, a, b, c, d, in[4] + K1, 3); | |
ROUND(F, d, a, b, c, in[5] + K1, 7); | |
ROUND(F, c, d, a, b, in[6] + K1, 11); | |
ROUND(F, b, c, d, a, in[7] + K1, 19); | |
/* Round 2 */ | |
ROUND(G, a, b, c, d, in[1] + K2, 3); | |
ROUND(G, d, a, b, c, in[3] + K2, 5); | |
ROUND(G, c, d, a, b, in[5] + K2, 9); | |
ROUND(G, b, c, d, a, in[7] + K2, 13); | |
ROUND(G, a, b, c, d, in[0] + K2, 3); | |
ROUND(G, d, a, b, c, in[2] + K2, 5); | |
ROUND(G, c, d, a, b, in[4] + K2, 9); | |
ROUND(G, b, c, d, a, in[6] + K2, 13); | |
/* Round 3 */ | |
ROUND(H, a, b, c, d, in[3] + K3, 3); | |
ROUND(H, d, a, b, c, in[7] + K3, 9); | |
ROUND(H, c, d, a, b, in[2] + K3, 11); | |
ROUND(H, b, c, d, a, in[6] + K3, 15); | |
ROUND(H, a, b, c, d, in[1] + K3, 3); | |
ROUND(H, d, a, b, c, in[5] + K3, 9); | |
ROUND(H, c, d, a, b, in[0] + K3, 11); | |
ROUND(H, b, c, d, a, in[4] + K3, 15); | |
buf[0] += a; | |
buf[1] += b; | |
buf[2] += c; | |
buf[3] += d; | |
return buf[1]; /* "most hashed" word */ | |
} | |
#undef ROUND | |
#undef K1 | |
#undef K2 | |
#undef K3 | |
#undef F | |
#undef G | |
#undef H | |
/* The old legacy hash */ | |
static unsigned int dx_hack_hash_unsigned(const char *name, int len) | |
{ | |
unsigned int hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; | |
const unsigned char *ucp = (const unsigned char *) name; | |
while (len--) { | |
hash = hash1 + (hash0 ^ (((int) *ucp++) * 7152373)); | |
if (hash & 0x80000000) | |
hash -= 0x7fffffff; | |
hash1 = hash0; | |
hash0 = hash; | |
} | |
return hash0 << 1; | |
} | |
static unsigned int dx_hack_hash_signed(const char *name, int len) | |
{ | |
unsigned int hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; | |
const signed char *scp = (const signed char *) name; | |
while (len--) { | |
hash = hash1 + (hash0 ^ (((int) *scp++) * 7152373)); | |
if (hash & 0x80000000) | |
hash -= 0x7fffffff; | |
hash1 = hash0; | |
hash0 = hash; | |
} | |
return hash0 << 1; | |
} | |
static void str2hashbuf_signed(const char *msg, int len, unsigned int *buf, int num) | |
{ | |
unsigned int pad, val; | |
int i; | |
const signed char *scp = (const signed char *) msg; | |
pad = (unsigned int)len | ((unsigned int)len << 8); | |
pad |= pad << 16; | |
val = pad; | |
if (len > num*4) | |
len = num * 4; | |
for (i = 0; i < len; i++) { | |
val = ((int) scp[i]) + (val << 8); | |
if ((i % 4) == 3) { | |
*buf++ = val; | |
val = pad; | |
num--; | |
} | |
} | |
if (--num >= 0) | |
*buf++ = val; | |
while (--num >= 0) | |
*buf++ = pad; | |
} | |
static void str2hashbuf_unsigned(const char *msg, int len, unsigned int *buf, int num) | |
{ | |
unsigned int pad, val; | |
int i; | |
const unsigned char *ucp = (const unsigned char *) msg; | |
pad = (unsigned int)len | ((unsigned int)len << 8); | |
pad |= pad << 16; | |
val = pad; | |
if (len > num*4) | |
len = num * 4; | |
for (i = 0; i < len; i++) { | |
val = ((int) ucp[i]) + (val << 8); | |
if ((i % 4) == 3) { | |
*buf++ = val; | |
val = pad; | |
num--; | |
} | |
} | |
if (--num >= 0) | |
*buf++ = val; | |
while (--num >= 0) | |
*buf++ = pad; | |
} | |
int __ext4fs_dirhash(const char *name, int len) { | |
unsigned int hash; | |
unsigned int minor_hash = 0; | |
const char *p; | |
int i; | |
unsigned int in[8], buf[4]; | |
void (*str2hashbuf)(const char *, int, unsigned int *, int) = | |
str2hashbuf_signed; | |
/* Initialize the default seed for the hash checksum functions */ | |
/* It needs to read from super block */ | |
buf[0] = 0xf69696b6; | |
buf[1] = 0xa14ee5ab; | |
buf[2] = 0xef542e8a; | |
buf[3] = 0x6d4dea7a; | |
p = name; | |
while (len > 0) { | |
(*str2hashbuf)(p, len, in, 8); | |
half_md4_transform(buf, in); | |
len -= 32; | |
p += 32; | |
} | |
minor_hash = buf[2]; | |
hash = buf[1]; | |
printf("hash: %x\n", hash); | |
printf("minor_hash: %x\n", minor_hash); | |
hash = hash & ~1; | |
if (hash == (EXT4_HTREE_EOF_32BIT << 1)) | |
hash = (EXT4_HTREE_EOF_32BIT - 1) << 1; | |
printf("hash: %x\n", hash); | |
printf("minor_hash: %x\n", minor_hash); | |
return 0; | |
} | |
int main(int argc, char *argv[]) { | |
int len = strlen(argv[1]); | |
__ext4fs_dirhash(argv[1], len); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment