xref: /aosp_15_r20/external/lzma/C/Md5.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 /* Md5.c -- MD5 Hash
2 : Igor Pavlov : Public domain
3 This code is based on Colin Plumb's public domain md5.c code */
4 
5 #include "Precomp.h"
6 
7 #include <string.h>
8 
9 #include "Md5.h"
10 #include "RotateDefs.h"
11 #include "CpuArch.h"
12 
13 #define MD5_UPDATE_BLOCKS(p) Md5_UpdateBlocks
14 
15 Z7_NO_INLINE
Md5_Init(CMd5 * p)16 void Md5_Init(CMd5 *p)
17 {
18   p->count = 0;
19   p->state[0] = 0x67452301;
20   p->state[1] = 0xefcdab89;
21   p->state[2] = 0x98badcfe;
22   p->state[3] = 0x10325476;
23 }
24 
25 #if 0 && !defined(MY_CPU_LE_UNALIGN)
26 // optional optimization for Big-endian processors or processors without unaligned access:
27 // it is intended to reduce the number of complex LE32 memory reading from 64 to 16.
28 // But some compilers (sparc, armt) are better without this optimization.
29 #define Z7_MD5_USE_DATA32_ARRAY
30 #endif
31 
32 #define LOAD_DATA(i)  GetUi32((const UInt32 *)(const void *)data + (i))
33 
34 #ifdef Z7_MD5_USE_DATA32_ARRAY
35 #define D(i)  data32[i]
36 #else
37 #define D(i)  LOAD_DATA(i)
38 #endif
39 
40 #define F1(x, y, z)   (z ^ (x & (y ^ z)))
41 #define F2(x, y, z)   F1(z, x, y)
42 #define F3(x, y, z)   (x ^ y ^ z)
43 #define F4(x, y, z)   (y ^ (x | ~z))
44 
45 #define R1(i, f, start, step, w, x, y, z, s, k) \
46     w += D((start + step * (i)) % 16) + k; \
47     w += f(x, y, z); \
48     w = rotlFixed(w, s) + x; \
49 
50 #define R4(i4,  f, start, step, s0,s1,s2,s3, k0,k1,k2,k3) \
51     R1 (i4*4+0, f, start, step, a,b,c,d, s0, k0) \
52     R1 (i4*4+1, f, start, step, d,a,b,c, s1, k1) \
53     R1 (i4*4+2, f, start, step, c,d,a,b, s2, k2) \
54     R1 (i4*4+3, f, start, step, b,c,d,a, s3, k3) \
55 
56 #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)  \
57     R4 (0,  f, start, step, s0,s1,s2,s3, k00,k01,k02,k03) \
58     R4 (1,  f, start, step, s0,s1,s2,s3, k10,k11,k12,k13) \
59     R4 (2,  f, start, step, s0,s1,s2,s3, k20,k21,k22,k23) \
60     R4 (3,  f, start, step, s0,s1,s2,s3, k30,k31,k32,k33) \
61 
62 static
63 Z7_NO_INLINE
Md5_UpdateBlocks(UInt32 state[4],const Byte * data,size_t numBlocks)64 void Z7_FASTCALL Md5_UpdateBlocks(UInt32 state[4], const Byte *data, size_t numBlocks)
65 {
66   UInt32 a, b, c, d;
67   // if (numBlocks == 0) return;
68   a = state[0];
69   b = state[1];
70   c = state[2];
71   d = state[3];
72   do
73   {
74 #ifdef Z7_MD5_USE_DATA32_ARRAY
75     UInt32 data32[MD5_NUM_BLOCK_WORDS];
76     {
77 #define LOAD_data32_x4(i) { \
78       data32[i    ] = LOAD_DATA(i    ); \
79       data32[i + 1] = LOAD_DATA(i + 1); \
80       data32[i + 2] = LOAD_DATA(i + 2); \
81       data32[i + 3] = LOAD_DATA(i + 3); }
82 #if 1
83       LOAD_data32_x4 (0 * 4)
84       LOAD_data32_x4 (1 * 4)
85       LOAD_data32_x4 (2 * 4)
86       LOAD_data32_x4 (3 * 4)
87 #else
88       unsigned i;
89       for (i = 0; i < MD5_NUM_BLOCK_WORDS; i += 4)
90       {
91         LOAD_data32_x4(i)
92       }
93 #endif
94     }
95 #endif
96 
97     R16 (F1, 0, 1,  7,12,17,22, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
98                                 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
99                                 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
100                                 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821)
101     R16 (F2, 1, 5,  5, 9,14,20, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
102                                 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
103                                 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
104                                 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a)
105     R16 (F3, 5, 3,  4,11,16,23, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
106                                 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
107                                 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
108                                 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665)
109     R16 (F4, 0, 7,  6,10,15,21, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
110                                 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
111                                 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
112                                 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391)
113 
114     a += state[0];
115     b += state[1];
116     c += state[2];
117     d += state[3];
118 
119     state[0] = a;
120     state[1] = b;
121     state[2] = c;
122     state[3] = d;
123 
124     data += MD5_BLOCK_SIZE;
125   }
126   while (--numBlocks);
127 }
128 
129 
130 #define Md5_UpdateBlock(p) MD5_UPDATE_BLOCKS(p)(p->state, p->buffer, 1)
131 
Md5_Update(CMd5 * p,const Byte * data,size_t size)132 void Md5_Update(CMd5 *p, const Byte *data, size_t size)
133 {
134   if (size == 0)
135     return;
136   {
137     const unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1);
138     const unsigned num = MD5_BLOCK_SIZE - pos;
139     p->count += size;
140     if (num > size)
141     {
142       memcpy(p->buffer + pos, data, size);
143       return;
144     }
145     if (pos != 0)
146     {
147       size -= num;
148       memcpy(p->buffer + pos, data, num);
149       data += num;
150       Md5_UpdateBlock(p);
151     }
152   }
153   {
154     const size_t numBlocks = size >> 6;
155     if (numBlocks)
156     MD5_UPDATE_BLOCKS(p)(p->state, data, numBlocks);
157     size &= MD5_BLOCK_SIZE - 1;
158     if (size == 0)
159       return;
160     data += (numBlocks << 6);
161     memcpy(p->buffer, data, size);
162   }
163 }
164 
165 
Md5_Final(CMd5 * p,Byte * digest)166 void Md5_Final(CMd5 *p, Byte *digest)
167 {
168   unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1);
169   p->buffer[pos++] = 0x80;
170   if (pos > (MD5_BLOCK_SIZE - 4 * 2))
171   {
172     while (pos != MD5_BLOCK_SIZE) { p->buffer[pos++] = 0; }
173     // memset(&p->buf.buffer[pos], 0, MD5_BLOCK_SIZE - pos);
174     Md5_UpdateBlock(p);
175     pos = 0;
176   }
177   memset(&p->buffer[pos], 0, (MD5_BLOCK_SIZE - 4 * 2) - pos);
178   {
179     const UInt64 numBits = p->count << 3;
180 #if defined(MY_CPU_LE_UNALIGN)
181     SetUi64 (p->buffer + MD5_BLOCK_SIZE - 4 * 2, numBits)
182 #else
183     SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 2, (UInt32)(numBits))
184     SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 1, (UInt32)(numBits >> 32))
185 #endif
186   }
187   Md5_UpdateBlock(p);
188 
189   SetUi32(digest,      p->state[0])
190   SetUi32(digest + 4,  p->state[1])
191   SetUi32(digest + 8,  p->state[2])
192   SetUi32(digest + 12, p->state[3])
193 
194   Md5_Init(p);
195 }
196 
197 #undef R1
198 #undef R4
199 #undef R16
200 #undef D
201 #undef LOAD_DATA
202 #undef LOAD_data32_x4
203 #undef F1
204 #undef F2
205 #undef F3
206 #undef F4
207