mirror of
https://github.com/ip7z/7zip.git
synced 2025-12-06 07:12:00 +01:00
207 lines
5.8 KiB
C
207 lines
5.8 KiB
C
|
|
/* Md5.c -- MD5 Hash
|
||
|
|
: Igor Pavlov : Public domain
|
||
|
|
This code is based on Colin Plumb's public domain md5.c code */
|
||
|
|
|
||
|
|
#include "Precomp.h"
|
||
|
|
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
#include "Md5.h"
|
||
|
|
#include "RotateDefs.h"
|
||
|
|
#include "CpuArch.h"
|
||
|
|
|
||
|
|
#define MD5_UPDATE_BLOCKS(p) Md5_UpdateBlocks
|
||
|
|
|
||
|
|
Z7_NO_INLINE
|
||
|
|
void Md5_Init(CMd5 *p)
|
||
|
|
{
|
||
|
|
p->count = 0;
|
||
|
|
p->state[0] = 0x67452301;
|
||
|
|
p->state[1] = 0xefcdab89;
|
||
|
|
p->state[2] = 0x98badcfe;
|
||
|
|
p->state[3] = 0x10325476;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if 0 && !defined(MY_CPU_LE_UNALIGN)
|
||
|
|
// optional optimization for Big-endian processors or processors without unaligned access:
|
||
|
|
// it is intended to reduce the number of complex LE32 memory reading from 64 to 16.
|
||
|
|
// But some compilers (sparc, armt) are better without this optimization.
|
||
|
|
#define Z7_MD5_USE_DATA32_ARRAY
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define LOAD_DATA(i) GetUi32((const UInt32 *)(const void *)data + (i))
|
||
|
|
|
||
|
|
#ifdef Z7_MD5_USE_DATA32_ARRAY
|
||
|
|
#define D(i) data32[i]
|
||
|
|
#else
|
||
|
|
#define D(i) LOAD_DATA(i)
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||
|
|
#define F2(x, y, z) F1(z, x, y)
|
||
|
|
#define F3(x, y, z) (x ^ y ^ z)
|
||
|
|
#define F4(x, y, z) (y ^ (x | ~z))
|
||
|
|
|
||
|
|
#define R1(i, f, start, step, w, x, y, z, s, k) \
|
||
|
|
w += D((start + step * (i)) % 16) + k; \
|
||
|
|
w += f(x, y, z); \
|
||
|
|
w = rotlFixed(w, s) + x; \
|
||
|
|
|
||
|
|
#define R4(i4, f, start, step, s0,s1,s2,s3, k0,k1,k2,k3) \
|
||
|
|
R1 (i4*4+0, f, start, step, a,b,c,d, s0, k0) \
|
||
|
|
R1 (i4*4+1, f, start, step, d,a,b,c, s1, k1) \
|
||
|
|
R1 (i4*4+2, f, start, step, c,d,a,b, s2, k2) \
|
||
|
|
R1 (i4*4+3, f, start, step, b,c,d,a, s3, k3) \
|
||
|
|
|
||
|
|
#define R16(f, start, step, s0,s1,s2,s3, k00,k01,k02,k03, k10,k11,k12,k13, k20,k21,k22,k23, k30,k31,k32,k33) \
|
||
|
|
R4 (0, f, start, step, s0,s1,s2,s3, k00,k01,k02,k03) \
|
||
|
|
R4 (1, f, start, step, s0,s1,s2,s3, k10,k11,k12,k13) \
|
||
|
|
R4 (2, f, start, step, s0,s1,s2,s3, k20,k21,k22,k23) \
|
||
|
|
R4 (3, f, start, step, s0,s1,s2,s3, k30,k31,k32,k33) \
|
||
|
|
|
||
|
|
static
|
||
|
|
Z7_NO_INLINE
|
||
|
|
void Z7_FASTCALL Md5_UpdateBlocks(UInt32 state[4], const Byte *data, size_t numBlocks)
|
||
|
|
{
|
||
|
|
UInt32 a, b, c, d;
|
||
|
|
// if (numBlocks == 0) return;
|
||
|
|
a = state[0];
|
||
|
|
b = state[1];
|
||
|
|
c = state[2];
|
||
|
|
d = state[3];
|
||
|
|
do
|
||
|
|
{
|
||
|
|
#ifdef Z7_MD5_USE_DATA32_ARRAY
|
||
|
|
UInt32 data32[MD5_NUM_BLOCK_WORDS];
|
||
|
|
{
|
||
|
|
#define LOAD_data32_x4(i) { \
|
||
|
|
data32[i ] = LOAD_DATA(i ); \
|
||
|
|
data32[i + 1] = LOAD_DATA(i + 1); \
|
||
|
|
data32[i + 2] = LOAD_DATA(i + 2); \
|
||
|
|
data32[i + 3] = LOAD_DATA(i + 3); }
|
||
|
|
#if 1
|
||
|
|
LOAD_data32_x4 (0 * 4)
|
||
|
|
LOAD_data32_x4 (1 * 4)
|
||
|
|
LOAD_data32_x4 (2 * 4)
|
||
|
|
LOAD_data32_x4 (3 * 4)
|
||
|
|
#else
|
||
|
|
unsigned i;
|
||
|
|
for (i = 0; i < MD5_NUM_BLOCK_WORDS; i += 4)
|
||
|
|
{
|
||
|
|
LOAD_data32_x4(i)
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
R16 (F1, 0, 1, 7,12,17,22, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||
|
|
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||
|
|
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||
|
|
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821)
|
||
|
|
R16 (F2, 1, 5, 5, 9,14,20, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||
|
|
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||
|
|
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||
|
|
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a)
|
||
|
|
R16 (F3, 5, 3, 4,11,16,23, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||
|
|
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||
|
|
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||
|
|
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665)
|
||
|
|
R16 (F4, 0, 7, 6,10,15,21, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||
|
|
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||
|
|
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||
|
|
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391)
|
||
|
|
|
||
|
|
a += state[0];
|
||
|
|
b += state[1];
|
||
|
|
c += state[2];
|
||
|
|
d += state[3];
|
||
|
|
|
||
|
|
state[0] = a;
|
||
|
|
state[1] = b;
|
||
|
|
state[2] = c;
|
||
|
|
state[3] = d;
|
||
|
|
|
||
|
|
data += MD5_BLOCK_SIZE;
|
||
|
|
}
|
||
|
|
while (--numBlocks);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
#define Md5_UpdateBlock(p) MD5_UPDATE_BLOCKS(p)(p->state, p->buffer, 1)
|
||
|
|
|
||
|
|
void Md5_Update(CMd5 *p, const Byte *data, size_t size)
|
||
|
|
{
|
||
|
|
if (size == 0)
|
||
|
|
return;
|
||
|
|
{
|
||
|
|
const unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1);
|
||
|
|
const unsigned num = MD5_BLOCK_SIZE - pos;
|
||
|
|
p->count += size;
|
||
|
|
if (num > size)
|
||
|
|
{
|
||
|
|
memcpy(p->buffer + pos, data, size);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (pos != 0)
|
||
|
|
{
|
||
|
|
size -= num;
|
||
|
|
memcpy(p->buffer + pos, data, num);
|
||
|
|
data += num;
|
||
|
|
Md5_UpdateBlock(p);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
{
|
||
|
|
const size_t numBlocks = size >> 6;
|
||
|
|
if (numBlocks)
|
||
|
|
MD5_UPDATE_BLOCKS(p)(p->state, data, numBlocks);
|
||
|
|
size &= MD5_BLOCK_SIZE - 1;
|
||
|
|
if (size == 0)
|
||
|
|
return;
|
||
|
|
data += (numBlocks << 6);
|
||
|
|
memcpy(p->buffer, data, size);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void Md5_Final(CMd5 *p, Byte *digest)
|
||
|
|
{
|
||
|
|
unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1);
|
||
|
|
p->buffer[pos++] = 0x80;
|
||
|
|
if (pos > (MD5_BLOCK_SIZE - 4 * 2))
|
||
|
|
{
|
||
|
|
while (pos != MD5_BLOCK_SIZE) { p->buffer[pos++] = 0; }
|
||
|
|
// memset(&p->buf.buffer[pos], 0, MD5_BLOCK_SIZE - pos);
|
||
|
|
Md5_UpdateBlock(p);
|
||
|
|
pos = 0;
|
||
|
|
}
|
||
|
|
memset(&p->buffer[pos], 0, (MD5_BLOCK_SIZE - 4 * 2) - pos);
|
||
|
|
{
|
||
|
|
const UInt64 numBits = p->count << 3;
|
||
|
|
#if defined(MY_CPU_LE_UNALIGN)
|
||
|
|
SetUi64 (p->buffer + MD5_BLOCK_SIZE - 4 * 2, numBits)
|
||
|
|
#else
|
||
|
|
SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 2, (UInt32)(numBits))
|
||
|
|
SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 1, (UInt32)(numBits >> 32))
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
Md5_UpdateBlock(p);
|
||
|
|
|
||
|
|
SetUi32(digest, p->state[0])
|
||
|
|
SetUi32(digest + 4, p->state[1])
|
||
|
|
SetUi32(digest + 8, p->state[2])
|
||
|
|
SetUi32(digest + 12, p->state[3])
|
||
|
|
|
||
|
|
Md5_Init(p);
|
||
|
|
}
|
||
|
|
|
||
|
|
#undef R1
|
||
|
|
#undef R4
|
||
|
|
#undef R16
|
||
|
|
#undef D
|
||
|
|
#undef LOAD_DATA
|
||
|
|
#undef LOAD_data32_x4
|
||
|
|
#undef F1
|
||
|
|
#undef F2
|
||
|
|
#undef F3
|
||
|
|
#undef F4
|