Blame |
Last modification |
View Log
| Download
| RSS feed
// hashplay framework
// (c) 2019 lvd^mhm
/*
This file is part of hashplay framework.
hashplay framework is free software:
you can redistribute it and/or modify it under the terms of
the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
hashplay framework is distributed in the hope that
it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with hashplay framework.
If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "hash-common.h"
#include "md5-my.h"
struct my_md5
{
uint64_t pos
;
uint8_t buf
[64];
uint32_t state
[4];
};
static const uint32_t a0
= 0x67452301;
static const uint32_t b0
= 0xefcdab89;
static const uint32_t c0
= 0x98badcfe;
static const uint32_t d0
= 0x10325476;
static inline void md5_compress
( const uint32_t * m
, uint32_t * state
)
{
#define F(b,c,d) ( ( (b) & (c) ) | ( (~(b)) & (d) ) )
#define G(b,c,d) ( ( (b) & (d)) | ( (c) & (~(d)) ) )
#define H(b,c,d) ( (b) ^ (c) ^ (d) )
#define I(b,c,d) ( (c) ^ ( (b) | (~(d)) ) )
#define ROL(x,n) ( ( (x)<<(n) ) | ( (x)>>(32-(n)) ) )
#define ROUND_1(a,b,c,d,msg,add,shift) \
do { \
a += F(b,c,d) + msg + add; \
a = ROL(a,shift); \
a += b; \
} while(0)
#define ROUND_2(a,b,c,d,msg,add,shift) \
do { \
a += G(b,c,d) + msg + add; \
a = ROL(a,shift); \
a += b; \
} while(0)
#define ROUND_3(a,b,c,d,msg,add,shift) \
do { \
a += H(b,c,d) + msg + add; \
a = ROL(a,shift); \
a += b; \
} while(0)
#define ROUND_4(a,b,c,d,msg,add,shift) \
do { \
a += I(b,c,d) + msg + add; \
a = ROL(a,shift); \
a += b; \
} while(0)
uint32_t A
= state
[0];
uint32_t B
= state
[1];
uint32_t C
= state
[2];
uint32_t D
= state
[3];
ROUND_1
(A
,B
,C
,D
, m
[ 0], 0xd76aa478, 7);
ROUND_1
(D
,A
,B
,C
, m
[ 1], 0xe8c7b756, 12);
ROUND_1
(C
,D
,A
,B
, m
[ 2], 0x242070db, 17);
ROUND_1
(B
,C
,D
,A
, m
[ 3], 0xc1bdceee, 22);
ROUND_1
(A
,B
,C
,D
, m
[ 4], 0xf57c0faf, 7);
ROUND_1
(D
,A
,B
,C
, m
[ 5], 0x4787c62a, 12);
ROUND_1
(C
,D
,A
,B
, m
[ 6], 0xa8304613, 17);
ROUND_1
(B
,C
,D
,A
, m
[ 7], 0xfd469501, 22);
ROUND_1
(A
,B
,C
,D
, m
[ 8], 0x698098d8, 7);
ROUND_1
(D
,A
,B
,C
, m
[ 9], 0x8b44f7af, 12);
ROUND_1
(C
,D
,A
,B
, m
[10], 0xffff5bb1, 17);
ROUND_1
(B
,C
,D
,A
, m
[11], 0x895cd7be, 22);
ROUND_1
(A
,B
,C
,D
, m
[12], 0x6b901122, 7);
ROUND_1
(D
,A
,B
,C
, m
[13], 0xfd987193, 12);
ROUND_1
(C
,D
,A
,B
, m
[14], 0xa679438e, 17);
ROUND_1
(B
,C
,D
,A
, m
[15], 0x49b40821, 22);
ROUND_2
(A
,B
,C
,D
, m
[ 1], 0xf61e2562, 5);
ROUND_2
(D
,A
,B
,C
, m
[ 6], 0xc040b340, 9);
ROUND_2
(C
,D
,A
,B
, m
[11], 0x265e5a51, 14);
ROUND_2
(B
,C
,D
,A
, m
[ 0], 0xe9b6c7aa, 20);
ROUND_2
(A
,B
,C
,D
, m
[ 5], 0xd62f105d, 5);
ROUND_2
(D
,A
,B
,C
, m
[10], 0x02441453, 9);
ROUND_2
(C
,D
,A
,B
, m
[15], 0xd8a1e681, 14);
ROUND_2
(B
,C
,D
,A
, m
[ 4], 0xe7d3fbc8, 20);
ROUND_2
(A
,B
,C
,D
, m
[ 9], 0x21e1cde6, 5);
ROUND_2
(D
,A
,B
,C
, m
[14], 0xc33707d6, 9);
ROUND_2
(C
,D
,A
,B
, m
[ 3], 0xf4d50d87, 14);
ROUND_2
(B
,C
,D
,A
, m
[ 8], 0x455a14ed, 20);
ROUND_2
(A
,B
,C
,D
, m
[13], 0xa9e3e905, 5);
ROUND_2
(D
,A
,B
,C
, m
[ 2], 0xfcefa3f8, 9);
ROUND_2
(C
,D
,A
,B
, m
[ 7], 0x676f02d9, 14);
ROUND_2
(B
,C
,D
,A
, m
[12], 0x8d2a4c8a, 20);
ROUND_3
(A
,B
,C
,D
, m
[ 5], 0xfffa3942, 4);
ROUND_3
(D
,A
,B
,C
, m
[ 8], 0x8771f681, 11);
ROUND_3
(C
,D
,A
,B
, m
[11], 0x6d9d6122, 16);
ROUND_3
(B
,C
,D
,A
, m
[14], 0xfde5380c, 23);
ROUND_3
(A
,B
,C
,D
, m
[ 1], 0xa4beea44, 4);
ROUND_3
(D
,A
,B
,C
, m
[ 4], 0x4bdecfa9, 11);
ROUND_3
(C
,D
,A
,B
, m
[ 7], 0xf6bb4b60, 16);
ROUND_3
(B
,C
,D
,A
, m
[10], 0xbebfbc70, 23);
ROUND_3
(A
,B
,C
,D
, m
[13], 0x289b7ec6, 4);
ROUND_3
(D
,A
,B
,C
, m
[ 0], 0xeaa127fa, 11);
ROUND_3
(C
,D
,A
,B
, m
[ 3], 0xd4ef3085, 16);
ROUND_3
(B
,C
,D
,A
, m
[ 6], 0x04881d05, 23);
ROUND_3
(A
,B
,C
,D
, m
[ 9], 0xd9d4d039, 4);
ROUND_3
(D
,A
,B
,C
, m
[12], 0xe6db99e5, 11);
ROUND_3
(C
,D
,A
,B
, m
[15], 0x1fa27cf8, 16);
ROUND_3
(B
,C
,D
,A
, m
[ 2], 0xc4ac5665, 23);
ROUND_4
(A
,B
,C
,D
, m
[ 0], 0xf4292244, 6);
ROUND_4
(D
,A
,B
,C
, m
[ 7], 0x432aff97, 10);
ROUND_4
(C
,D
,A
,B
, m
[14], 0xab9423a7, 15);
ROUND_4
(B
,C
,D
,A
, m
[ 5], 0xfc93a039, 21);
ROUND_4
(A
,B
,C
,D
, m
[12], 0x655b59c3, 6);
ROUND_4
(D
,A
,B
,C
, m
[ 3], 0x8f0ccc92, 10);
ROUND_4
(C
,D
,A
,B
, m
[10], 0xffeff47d, 15);
ROUND_4
(B
,C
,D
,A
, m
[ 1], 0x85845dd1, 21);
ROUND_4
(A
,B
,C
,D
, m
[ 8], 0x6fa87e4f, 6);
ROUND_4
(D
,A
,B
,C
, m
[15], 0xfe2ce6e0, 10);
ROUND_4
(C
,D
,A
,B
, m
[ 6], 0xa3014314, 15);
ROUND_4
(B
,C
,D
,A
, m
[13], 0x4e0811a1, 21);
ROUND_4
(A
,B
,C
,D
, m
[ 4], 0xf7537e82, 6);
ROUND_4
(D
,A
,B
,C
, m
[11], 0xbd3af235, 10);
ROUND_4
(C
,D
,A
,B
, m
[ 2], 0x2ad7d2bb, 15);
ROUND_4
(B
,C
,D
,A
, m
[ 9], 0xeb86d391, 21);
state
[0] += A
;
state
[1] += B
;
state
[2] += C
;
state
[3] += D
;
}
static inline size_t my_min
(size_t a
, size_t b
)
{
if( a
<=b
) return a
; else return b
;
}
struct hash_iface
* make_md5_my
(void)
{
static const char name
[]="my MD5";
struct hash_iface
* hash
= malloc(sizeof(struct hash_iface
));
if( !hash
)
{
fprintf(stderr
,"%s: %d, %s: can't allocate memory for hash_iface!\n",__FILE__
,__LINE__
,__func__
);
exit(1);
}
hash
->hash_specific_data
= NULL
;
hash
->name
= name
;
hash
->hash_init
= &md5_my_hash_init
;
hash
->hash_start
= &md5_my_hash_start
;
hash
->hash_addbytes
= &md5_my_hash_addbytes
;
hash
->hash_getsize
= &md5_my_hash_getsize
;
hash
->hash_result
= &md5_my_hash_result
;
hash
->hash_deinit
= &md5_my_hash_deinit
;
return hash
;
}
int md5_my_hash_init
(struct hash_iface
* hash
)
{
struct my_md5
* md5
= (struct my_md5
*)malloc(sizeof(struct my_md5
));
if( !md5
)
{
fprintf(stderr
,"%s: %d, %s: can't allocate memory for struct my_md5!\n",__FILE__
,__LINE__
,__func__
);
exit(1);
}
hash
->hash_specific_data
= (void *)md5
;
return 1;
}
int md5_my_hash_start
(struct hash_iface
* hash
)
{
struct my_md5
* md5
= (struct my_md5
*)hash
->hash_specific_data
;
if( !md5
)
{
fprintf(stderr
,"%s: %d, %s: hash_specific_data was NULL!\n",__FILE__
,__LINE__
,__func__
);
exit(1);
}
md5
->pos
= 0;
for(int i
=0;i
<64;i
++)
md5
->buf
[i
] = 0;
md5
->state
[0] = a0
;
md5
->state
[1] = b0
;
md5
->state
[2] = c0
;
md5
->state
[3] = d0
;
return 1;
}
int md5_my_hash_addbytes
(struct hash_iface
* hash
, const uint8_t * message
, size_t size
)
{
struct my_md5
* md5
= (struct my_md5
*)hash
->hash_specific_data
;
if( !md5
)
{
fprintf(stderr
,"%s: %d, %s: hash_specific_data was NULL!\n",__FILE__
,__LINE__
,__func__
);
exit(1);
}
const uint8_t * ptr
= message
;
size_t remaining_size
= size
;
while( remaining_size
> 0 )
{
// aligned 64-bytes shortcut
if( !(md5
->pos
& 63) && remaining_size
>= 64 )
{
md5_compress
( (const uint32_t *)ptr
, md5
->state
);
md5
->pos
+= 64;
ptr
+= 64;
remaining_size
-= 64;
continue;
}
// otherwise fill buffer and perform MD5 update on it
size_t size_to_add
= my_min
( (64-(md5
->pos
& 63)), remaining_size
);
do
{
md5
->buf
[md5
->pos
& 63] = *ptr
;
ptr
++;
md5
->pos
++;
remaining_size
--;
} while( (--size_to_add
) );
if( !(md5
->pos
& 63) )
md5_compress
( (const uint32_t *)md5
->buf
, md5
->state
);
}
return 1;
}
size_t md5_my_hash_getsize
(struct hash_iface
* hash
)
{
return 16;
}
int md5_my_hash_result
(struct hash_iface
* hash
, uint8_t * result
)
{
struct my_md5
* md5
= (struct my_md5
*)hash
->hash_specific_data
;
if( !md5
)
{
fprintf(stderr
,"%s: %d, %s: hash_specific_data was NULL!\n",__FILE__
,__LINE__
,__func__
);
exit(1);
}
// make padding
uint64_t bits_hashed
= md5
->pos
* 8;
uint8_t padding
[64+8];
for(int i
=0;i
<64;i
++)
padding
[i
]=0;
*(uint64_t *)(&padding
[64]) = bits_hashed
;
int num_pad_bytes
= 56 - (md5
->pos
& 63);
if( num_pad_bytes
<=0 ) num_pad_bytes
+= 64;
padding
[64-num_pad_bytes
] = 0x80;
md5_my_hash_addbytes
(hash
, &padding
[64-num_pad_bytes
], 8+num_pad_bytes
);
assert( !(md5
->pos
& 63) );
memcpy(result
,md5
->state
,16);
return 1;
}
void md5_my_hash_deinit
(struct hash_iface
* hash
)
{
struct my_md5
* md5
= (struct my_md5
*)hash
->hash_specific_data
;
if( !md5
)
{
fprintf(stderr
,"%s: %d, %s: hash_specific_data was NULL!\n",__FILE__
,__LINE__
,__func__
);
exit(1);
}
free(md5
);
hash
->hash_specific_data
= NULL
;
}